├── .browserslistrc
├── .gitignore
├── README.md
├── babel.config.js
├── jsconfig.json
├── package-lock.json
├── package.json
├── public
├── favicon.ico
└── index.html
├── src
├── App.vue
├── api
│ ├── artists.js
│ ├── dj.js
│ ├── else.js
│ ├── list.js
│ ├── mv.js
│ ├── plugins
│ │ ├── mixin.js
│ │ └── request.js
│ ├── singer.js
│ ├── song.js
│ ├── user.js
│ └── video.js
├── assets
│ ├── area.js
│ ├── css
│ │ ├── common
│ │ │ ├── ad_animate.css
│ │ │ ├── common.less
│ │ │ └── util.less
│ │ └── default
│ │ │ ├── app.less
│ │ │ ├── dj_detail.less
│ │ │ ├── explore.less
│ │ │ ├── home.less
│ │ │ ├── home_search.less
│ │ │ ├── login.less
│ │ │ ├── mv_detail.less
│ │ │ ├── singer_album.less
│ │ │ ├── singer_detail.less
│ │ │ ├── song_detail.less
│ │ │ ├── song_search.less
│ │ │ ├── user_center.less
│ │ │ ├── user_detail.less
│ │ │ └── video_detail.less
│ └── img
│ │ ├── login-bg.jpg
│ │ ├── m-music-banner.jpg
│ │ ├── search-bg.jpg
│ │ └── tx.jpg
├── components
│ ├── Global
│ │ ├── BotLoad.vue
│ │ ├── BotLoadAudioList.vue
│ │ ├── BotLoadRequest.vue
│ │ ├── BreakHeader.vue
│ │ ├── EmptyBox.vue
│ │ ├── EmptyTextBox.vue
│ │ ├── IconText.vue
│ │ ├── ImgLoader.vue
│ │ ├── LoadingBlock.vue
│ │ ├── PullRefresh.vue
│ │ └── Scroll.vue
│ ├── block
│ │ ├── ScrollXBlock.vue
│ │ └── StrMarquee.vue
│ ├── card
│ │ ├── AlbumList.vue
│ │ ├── AudioCoverList.vue
│ │ ├── AudioItem.vue
│ │ ├── AudioList.vue
│ │ ├── CircleCard.vue
│ │ ├── CommentlistCard.vue
│ │ ├── CrowdCard.vue
│ │ ├── MvLgCard.vue
│ │ ├── MvListCard.vue
│ │ ├── MvRmdCard.vue
│ │ ├── PlaylistSmCard.vue
│ │ ├── SearchVideoList.vue
│ │ ├── SonglistCard.vue
│ │ ├── UnfoldCard.vue
│ │ ├── UsPlaylistCard.vue
│ │ ├── VideoCoverCard.vue
│ │ ├── VideoList.vue
│ │ └── ViewsBlockCard.vue
│ ├── carousel
│ │ ├── AdCarousel.vue
│ │ └── AdCarouselItem.vue
│ ├── common
│ │ ├── AAleart.vue
│ │ ├── ADialog.vue
│ │ ├── AdWaterfall.vue
│ │ ├── Fullscreen.vue
│ │ ├── FullscreenScroll.vue
│ │ ├── LoadingBlock.vue
│ │ ├── MovableMask.vue
│ │ └── RequestLoader.vue
│ ├── form
│ │ ├── AreaPickerList.vue
│ │ ├── AvatarList.vue
│ │ ├── DatePickerList.vue
│ │ ├── EditInputList.vue
│ │ ├── RadioItems.vue
│ │ ├── RadioList.vue
│ │ ├── RadioListItems.vue
│ │ ├── TabBarReply.vue
│ │ ├── TextAreaBox.vue
│ │ └── TextAreaList.vue
│ ├── header
│ │ └── AutoHeader.vue
│ ├── item
│ │ ├── ArtistItem.vue
│ │ ├── DjradioItem.vue
│ │ ├── PrivateMsgItem.vue
│ │ ├── SearchAudioItem.vue
│ │ ├── SearchMlogItem.vue
│ │ ├── SingerRadioItem.vue
│ │ ├── SonglistItem.vue
│ │ ├── TrendItem.vue
│ │ └── UserItem.vue
│ ├── player
│ │ ├── TabPlayer.vue
│ │ ├── child
│ │ │ ├── TpControl.vue
│ │ │ ├── TpCover.vue
│ │ │ ├── TpCricleProgress.vue
│ │ │ ├── TpCurList.vue
│ │ │ ├── TpHisList.vue
│ │ │ ├── TpLists.vue
│ │ │ ├── TpLyric.vue
│ │ │ ├── TpOldList.vue
│ │ │ ├── TpProgress.vue
│ │ │ └── TpTools.vue
│ │ └── tabplayer.less
│ ├── popup
│ │ └── SongPopup.vue
│ ├── tool
│ │ └── AvatarsHandler.vue
│ ├── utils
│ │ └── LoadingBlock.js
│ └── video
│ │ ├── AdVideo.vue
│ │ ├── ScreenVideo.vue
│ │ └── SingleVideo.vue
├── main.js
├── plugins
│ ├── ADialog.js
│ ├── GlobalComps.js
│ └── Vant.js
├── router
│ ├── index.js
│ └── route
│ │ ├── home.routes.js
│ │ └── login.routes.js
├── store
│ ├── index.js
│ └── modules
│ │ ├── music.js
│ │ └── user.js
├── utils
│ ├── AdDirect.js
│ ├── Bus.js
│ ├── Constellation.js
│ ├── Decorator.js
│ ├── Filters.js
│ └── ToolFunc.js
└── views
│ ├── Comment
│ └── SongComment.vue
│ ├── Dj
│ ├── DjDetail.vue
│ └── child
│ │ ├── DjAbout.vue
│ │ ├── DjShow.vue
│ │ └── DjSimilar.vue
│ ├── Home
│ ├── Home.vue
│ ├── child
│ │ ├── Explore.vue
│ │ ├── HomeAside.vue
│ │ ├── SkySquare.vue
│ │ ├── UserCenter.vue
│ │ ├── Village copy.vue
│ │ ├── Village.vue
│ │ └── child
│ │ │ ├── ExBanner.vue
│ │ │ ├── ExBoutiqueAudioList.vue
│ │ │ ├── ExMvTop.vue
│ │ │ ├── ExRmdRadiosStation.vue
│ │ │ ├── SsRmdMv.vue
│ │ │ ├── UcBanner.vue
│ │ │ ├── UcMyMusic.vue
│ │ │ └── UcMyPlaylist.vue
│ └── routes
│ │ ├── HomeSearch.vue
│ │ └── child
│ │ ├── HsAlbum.vue
│ │ ├── HsDj.vue
│ │ ├── HsMix.vue
│ │ ├── HsMv.vue
│ │ ├── HsSinger.vue
│ │ ├── HsSong.vue
│ │ ├── HsSonglist.vue
│ │ ├── HsSuggest.vue
│ │ ├── HsUser.vue
│ │ └── HsVideo.vue
│ ├── Login
│ └── Login.vue
│ ├── Singer
│ ├── SingerDetail.vue
│ ├── child
│ │ ├── SdAlbum.vue
│ │ ├── SdHome.vue
│ │ ├── SdMv.vue
│ │ └── SdSong.vue
│ └── routes
│ │ ├── SingerAlbum.vue
│ │ └── child
│ │ └── SdBanner.vue
│ ├── Song
│ ├── SongDetail.vue
│ ├── SongSearch.vue
│ └── child
│ │ └── SdBanner.vue
│ ├── Square
│ ├── DjSquare.vue
│ ├── MvSquare.vue
│ ├── SonglistSquare.vue
│ └── child
│ │ ├── DjBanner.vue
│ │ ├── DjRmdBlock.vue
│ │ ├── DjRmdList.vue
│ │ ├── MvChina.vue
│ │ ├── MvEamerica.vue
│ │ ├── MvJapan.vue
│ │ ├── MvKorea.vue
│ │ ├── SonglistBoutique.vue
│ │ ├── SonglistHot.vue
│ │ ├── SonglistPopular.vue
│ │ └── SonglistRmd.vue
│ ├── User
│ ├── UserChatroom.vue
│ ├── UserDetail.vue
│ ├── UserFriend.vue
│ ├── UserNews.vue
│ ├── child
│ │ ├── UdHome.vue
│ │ ├── UdTrend.vue
│ │ ├── UfAartistSub.vue
│ │ ├── UfFolloweds.vue
│ │ ├── UfFollows.vue
│ │ ├── UnComments.vue
│ │ ├── UnForwards.vue
│ │ ├── UnNotices.vue
│ │ └── UnPrivate.vue
│ └── routes
│ │ ├── UserInfo.vue
│ │ ├── UserSonglist.vue
│ │ ├── UsetTrendDetail.vue
│ │ └── child
│ │ ├── UtdChat.vue
│ │ ├── UtdForward.vue
│ │ └── UtdPraise.vue
│ └── Video
│ ├── MvDetail.vue
│ ├── VideoDetail.vue
│ └── child
│ ├── MdComment.vue
│ ├── MdRelated.vue
│ └── VdPopup.vue
└── vue.config.js
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 | pnpm-debug.log*
14 |
15 | # Editor directories and files
16 | .idea
17 | .vscode
18 | *.suo
19 | *.ntvs*
20 | *.njsproj
21 | *.sln
22 | *.sw?
23 |
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Starry 移动端音乐webapp(此项目已停止维护)
2 | 
3 |
4 | ### 前提
5 |
6 | ps:账号使用自己网易云音乐的账号,目前仅支持手机号登录
7 |
8 | ### 特点:
9 |
10 | - 页面切换过渡
11 | - 手势切换操作
12 | - 数据本地储存
13 | - 登录,歌单,专辑,歌手,电台,MV,视频,评论,搜索,用户,动态,粉丝,关注,收藏...等二十几个页面
14 | - 圆形进度条,滚动歌词
15 | - ....
16 |
17 |
18 |
19 | ### 下载 && 运行
20 |
21 | [项目地址](https://github.com/Adicwu/Starry)
22 |
23 | [线上地址](http://music.adicw.cn)
24 |
25 | > 项目当前依赖[NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi),感谢NeteaseCloudMusicApi的作者
26 |
27 | ### 运行截图实例
28 |
29 | 
30 | 
31 | 
32 | 
33 | 
34 | 
35 | 
36 |
37 | ### 技术栈
38 |
39 | #### 前端
40 |
41 | 1. vue-cli4以及其全家桶
42 | 2. Vant/FontAwesome/Animate.css/BetterScroll
43 | 3. Axios/Less
44 |
45 | #### 后端
46 |
47 | 1. NeteaseCloudMusicApi项目
48 |
49 | 2. nginx反向代理配置https以及域名
50 |
51 |
52 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | // 关掉装饰器的错误提示
3 | "compilerOptions": {
4 | "experimentalDecorators": true
5 | }
6 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "m-adic-music",
3 | "version": "0.1.1",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build"
8 | },
9 | "dependencies": {
10 | "axios": "^0.19.2",
11 | "better-scroll": "^1.15.2",
12 | "core-js": "^3.6.5",
13 | "jquery": "^3.5.1",
14 | "less": "^3.11.1",
15 | "less-loader": "^6.1.0",
16 | "vant": "^2.8.4",
17 | "vue": "^2.6.11",
18 | "vue-router": "^3.3.1",
19 | "vuex": "^3.4.0"
20 | },
21 | "devDependencies": {
22 | "@vue/cli-plugin-babel": "~4.4.0",
23 | "@vue/cli-plugin-router": "~4.4.0",
24 | "@vue/cli-plugin-vuex": "~4.4.0",
25 | "@vue/cli-service": "~4.4.0",
26 | "compression-webpack-plugin": "^4.0.0",
27 | "style-resources-loader": "^1.3.3",
28 | "vue-cli-plugin-style-resources-loader": "^0.1.4",
29 | "vue-template-compiler": "^2.6.11"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adicwu/Starry/a9530e3901ed1e967be9feafc9bff863026dc591/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | SkySquare
11 |
12 |
13 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/api/artists.js:
--------------------------------------------------------------------------------
1 | import {
2 | getax
3 | } from './plugins/request.js'
4 |
5 | //歌手信息以及单曲
6 | export function artists(id) {
7 | return getax(`artists?id=${id}`)
8 | }
9 |
--------------------------------------------------------------------------------
/src/api/dj.js:
--------------------------------------------------------------------------------
1 | import {
2 | getax
3 | } from './plugins/request.js'
4 |
5 | //dj轮播
6 | export function djBanner() {
7 | return getax('dj/banner')
8 | }
9 |
10 | //分类dj
11 | export function rmdDj(type) {
12 | return getax(`dj/recommend/type?type=${type}`)
13 | }
14 |
15 | //dj分类列表
16 | export function djTypes() {
17 | return getax('dj/catelist')
18 | }
19 |
20 | //dj节目
21 | export function djProgram(id,limit=30){
22 | return getax(`dj/program?rid=${id}&limit=${limit}`)
23 | }
24 |
25 | //dj详情
26 | export function djDetail(id){
27 | return getax(`dj/detail?rid=${id}`)
28 | }
29 |
30 | //dj节目评论
31 | export function djComment(id){
32 | return getax(`comment/dj?id=${id}`)
33 | }
--------------------------------------------------------------------------------
/src/api/else.js:
--------------------------------------------------------------------------------
1 | import {
2 | getax
3 | } from './plugins/request.js'
4 | import {
5 | songUrl
6 | } from './song.js'
7 | export function getBanner() {
8 | return getax('banner?type=1')
9 | }
10 | export function exclusiveBroadcast() {
11 | return getax('personalized/privatecontent')
12 | }
13 | export function rmdRadiostation() {
14 | return getax('personalized/djprogram')
15 | }
16 | export function mvTop(limit) {
17 | return getax(`top/mv?limit=${limit}`)
18 | }
19 | export function hotComment(id, type, limit = 10, offset = 0) {
20 | // 0: 歌曲 1: mv 2: 歌单 3: 专辑 4: 电台 5: 视频
21 | return getax(`comment/hot?id=${id}&type=${type}&limit=${limit}&offset=${offset}`)
22 | }
23 | //相关列表(电台、歌单)
24 | export function relatedList(id) {
25 | return getax(`related/playlist?id=${id}`)
26 | }
27 | //默认搜索关键词
28 | export function dfSearchTxt() {
29 | return getax(`search/default`)
30 | }
31 | //热搜列表(简略)
32 | export function tinyHotSearch() {
33 | return getax(`search/hot`)
34 | }
35 | //热搜列表(详细)
36 | export function fullHotSearch() {
37 | return getax(`search/hot/detail`)
38 | }
39 |
40 | //混合关键字搜索
41 | //type 1: 单曲, 10: 专辑, 100: 歌手, 1000: 歌单, 1002: 用户, 1004: MV, 1006: 歌词, 1009: 电台, 1014: 视频, 1018:综合
42 | export function mixSearch(key, type = 1, limit = 40, offset = 0) {
43 | if (type === 1) {
44 | return new Promise((resolve, reject) => {
45 | getax(`search?keywords=${key}&limit=${limit}&type=${type}&offset=${offset}`).then(res => {
46 | let songs = res.data.result.songs
47 | let songCount = res.data.result.songCount
48 | let ids = songs.map(item => item.id)
49 | songUrl(ids.toString()).then(respon => {
50 | respon.data.data.forEach(rel => {
51 | let index = songs.findIndex(item => item.id === rel.id)
52 | songs[index].url = rel.url
53 | })
54 | })
55 | let rel = {
56 | songs,
57 | songCount
58 | }
59 | resolve(rel)
60 | }).catch(err => reject(err))
61 | })
62 | } else {
63 | return getax(`search?keywords=${key}&limit=${limit}&type=${type}&offset=${offset}`)
64 | }
65 | }
66 |
67 | //搜索提示
68 | export function searchSuggest(keywords) {
69 | return getax(`search/suggest?keywords= ${keywords}&type=mobile`)
70 | }
--------------------------------------------------------------------------------
/src/api/list.js:
--------------------------------------------------------------------------------
1 | import {
2 | getax
3 | } from './plugins/request.js'
4 |
5 | //精品歌单
6 | export function boutiqueAudioList(cat = '',limit, before = 0) {
7 | // " 华语 "、" 古风 " 、" 欧美 "、" 流行 ", 默认为 "全部"
8 | return before === 0 ?
9 | getax(`/top/playlist/highquality?limit=${limit}&cat=${cat}`) :
10 | getax(`/top/playlist/highquality?limit=${limit}&before=${before}&cat=${cat}`)
11 | }
12 |
13 | //推荐歌单
14 | export function rmdSonglist(limit = 1) {
15 | return getax(`personalized?limit=${limit}`)
16 | }
17 |
18 | //热门歌单
19 | export function hotSonglist() {
20 | return getax('playlist/hot')
21 | }
22 |
23 | //网友精选歌单
24 | export function userHotSonglist(limit, offset = 0, order = '', cat = '') {
25 | return getax(`top/playlist?limit=${limit}&offset=${offset}&order=${order}&cat=${cat}`)
26 | }
27 |
--------------------------------------------------------------------------------
/src/api/mv.js:
--------------------------------------------------------------------------------
1 | import {
2 | getax
3 | } from './plugins/request.js'
4 |
5 | //最新mv
6 | export function newMv(limit) {
7 | return getax(`/mv/first?limit=${limit}`, false)
8 | }
9 |
10 | //推荐mv
11 | export function rmdMv(limit) {
12 | return getax('/personalized/mv')
13 | }
14 |
15 | //排行mv
16 | export function rankMv(limit, area = '') {
17 | return getax(`/top/mv?limit=${limit}&area=${area}`)
18 | }
19 |
20 | //获取mv数据
21 | export function mvDetail(id) {
22 | return Promise.all([
23 | getax(`mv/detail?mvid=${id}`),
24 | getax(`mv/url?id=${id}`),
25 | getax(`mv/detail/info?mvid=${id}`),
26 | ])
27 | }
28 |
29 | //获取mv相关视频数据
30 | export function mvRelated(id) {
31 | return getax(`related/allvideo?id=${id}`)
32 | }
33 |
34 | //获取视频标签/分类下的视频
35 | export function mvGroup(id){
36 | return getax(`video/group?id=${id}`)
37 | }
38 |
39 | //获取mv评论内容
40 | export function mvComment(id,limit=5) {
41 | return getax(`comment/mv?id=${id}&limit=${limit}`)
42 | }
43 |
--------------------------------------------------------------------------------
/src/api/plugins/mixin.js:
--------------------------------------------------------------------------------
1 | import store from '../../store/index.js'
2 | export function getCookie(){
3 | let {
4 | cookie
5 | } = store.state.user;
6 | return cookie;
7 | }
--------------------------------------------------------------------------------
/src/api/plugins/request.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import { Toast } from 'vant'
3 | const dev = false;
4 |
5 | const baseURL = dev ? '/api' : 'https://musicapi.adicw.cn/',
6 | timeout = 6000;
7 | axios.defaults.withCredentials = true
8 | const instance = axios.create({
9 | baseURL,
10 | timeout,
11 | })
12 | instance.interceptors.response.use(response => {
13 | return response
14 | }, error => {
15 | let { status, data } = error.response
16 | switch (status) {
17 | case 404: {
18 | Toast(data.message || '!!!');
19 | break;
20 | }
21 | }
22 | return Promise.reject(error)
23 | })
24 | // instance.interceptors.request.use(config => {
25 | // if (store.state.user.token == null) {
26 | // router.push('/login')
27 | // } else {
28 | // let { cookie } = store.state.user
29 | // config.withCredentials = true
30 | // config.header.cookie = cookie
31 | // }
32 | // return config
33 | // }, err => {
34 | // console.dir(err);
35 | // return Promise.reject(err)
36 | // })
37 |
38 | export function getax(config) {
39 | return instance(config)
40 | }
41 |
42 | export function postax(url, data = {}) {
43 | return instance.post(url, data)
44 | }
45 |
46 | export function putax(url, data = {}) {
47 | return instance.put(url, data)
48 | }
--------------------------------------------------------------------------------
/src/api/singer.js:
--------------------------------------------------------------------------------
1 | import {
2 | getax
3 | } from './plugins/request.js'
4 | //歌手mv
5 | export function singerMv(id, limit = 50) {
6 | return getax(`artist/mv?id=${id}&limit=${limit}`)
7 | }
8 | //歌手专辑
9 | export function singerAlbums(id, limit = 40) {
10 | return getax(`artist/album?id=${id}&limit=${limit}`)
11 | }
12 | //专辑内容
13 | export function singerAlbum(id) {
14 | return getax(`album?id=${id}`)
15 | }
16 | //歌手描述
17 | export function singerDesc(id) {
18 | return getax(`artist/desc?id=${id}`)
19 | }
20 | //歌手热门50单曲
21 | export function singerHotArtists(id) {
22 | return getax(`artist/top/song?id=${id}`)
23 | }
24 | //歌手单曲
25 | export function singerArtists(id) {
26 | return getax(`artists?id=${id}`)
27 | }
28 | //相似歌手
29 | export function singerSimi(id) {
30 | return getax(`/simi/artist?id=${id}`)
31 | }
32 |
--------------------------------------------------------------------------------
/src/api/song.js:
--------------------------------------------------------------------------------
1 | import {
2 | getax
3 | } from './plugins/request.js'
4 |
5 | //推荐新歌
6 | export function rmdNewsSong() {
7 | return getax(`personalized/newsong`)
8 | }
9 |
10 | //歌单内容
11 | export function songlistDetail(id) {
12 | return getax(`playlist/detail?id=${id}`)
13 | }
14 |
15 | //歌曲内容
16 | export function songDetail(id) {
17 | return getax(`song/detail?ids=${id}`, false)
18 | }
19 |
20 | //获取音乐url
21 | export function songUrl(id) {
22 | return getax(`song/url?id=${id}`, false)
23 | }
24 |
25 | //获取音乐歌词
26 | export function songLyric(id) {
27 | return getax(`lyric?id=${id}`, false)
28 | }
29 |
30 | //单曲是否可用
31 | export function songCheck(id) {
32 | return getax(`check/music?id=${id}`, false)
33 | }
34 |
35 | //获取歌曲评论
36 | export function songComment(id, limit = 20, offset = 0, before = 0) {
37 | return getax(`comment/music?id=${id}&limit=${limit}&offset=${offset}`)
38 | }
39 |
--------------------------------------------------------------------------------
/src/api/video.js:
--------------------------------------------------------------------------------
1 | import {
2 | getax,
3 | postax
4 | } from './plugins/request.js'
5 | import {
6 | getCookie
7 | } from './plugins/mixin.js'
8 |
9 | //推荐视频
10 | export function rmdVideo(offset = 0) {
11 | return getax(`video/timeline/recommend?offset=${offset}`)
12 | }
13 |
14 | //全部视频列表
15 | export function videoLists(offset = 0) {
16 | return getax(`video/timeline/all?offset=${offset}`)
17 | }
18 |
19 | //标签/分类视频
20 | export function groupVideo(id, offset = 0) {
21 | return getax(`video/group?id=${id}offset=${offset}`)
22 | }
23 |
24 | //视频分类列表
25 | export function videoCateLists() {
26 | return getax(`video/category/list`)
27 | }
28 |
29 | //视频标签列表
30 | export function videoGroupLists() {
31 | return getax(`video/group/list`)
32 | }
33 |
34 | //视频详情
35 | export function videoDetail(id) {
36 | return getax(`video/detail?id=${id}`)
37 | }
38 |
39 | //视频相关数据
40 | export function videoInfo(id) {
41 | return getax(`video/detail/info?id=${id}`)
42 | }
43 |
44 | //视频播放地址
45 | export function videoUrl(id) {
46 | return getax(`video/url?id=${id}`)
47 | }
48 |
49 | //视频评论
50 | export function videoComment(id, limit = 5, offset = 0) {
51 | return getax(`comment/video?id=${id}&limit=${limit}&offset=${offset}`)
52 | }
53 |
54 | //云盘
55 | export function cloud(limit = 200, offset = 0) {
56 | return getax(`user/cloud?limit=${limit}&offset=${offset}`)
57 | }
--------------------------------------------------------------------------------
/src/assets/css/common/ad_animate.css:
--------------------------------------------------------------------------------
1 | /* fast */
2 | .ft-delay {
3 | animation-delay: 0.3s;
4 | }
5 |
6 | .slide-ftin-up {
7 | animation: slideltinup .5s forwards;
8 | }
9 |
10 | @keyframes slideltinup {
11 | from {
12 | transform: translate3d(0, 60px, 0);
13 | }
14 |
15 | to {
16 | transform: translate3d(0, 0, 0);
17 | }
18 | }
19 |
20 | .slide-ftin-down {
21 | animation: slideltindown .5s forwards;
22 | }
23 |
24 | @keyframes slideltindown {
25 | from {
26 | transform: translate3d(0, -60px, 0);
27 | }
28 |
29 | to {
30 | transform: translate3d(0, 0, 0);
31 | }
32 | }
33 |
34 | .slide-ftin-left {
35 | animation: slideltinleft .5s forwards;
36 | }
37 |
38 | @keyframes slideltinleft {
39 | from {
40 | transform: translate3d(-60px, 0, 0);
41 | }
42 |
43 | to {
44 | transform: translate3d(0, 0, 0);
45 | }
46 | }
47 |
48 | .slide-ftin-right {
49 | animation: slideltinright .5s forwards;
50 | }
51 |
52 | @keyframes slideltinright {
53 | from {
54 | transform: translate3d(60px, 0, 0);
55 | }
56 |
57 | to {
58 | transform: translate3d(0, 0, 0);
59 | }
60 | }
61 |
62 | .fade-ftin {
63 | animation: fadeftin .3s forwards;
64 | }
65 |
66 | @keyframes fadeftin {
67 | from {
68 | opacity: 0;
69 | }
70 |
71 | to {
72 | opacity: 1;
73 | }
74 | }
75 |
76 | .fade-scale-in{
77 | animation: fadeScaleIn .3s forwards;
78 | }
79 |
80 | @keyframes fadeScaleIn{
81 | 0%{
82 | opacity: 0;
83 | transform: scale(.95);
84 | }
85 | 40%{
86 | opacity: .8;
87 | }
88 | 100%{
89 | opacity: 1;
90 | transform: scale(1);
91 | }
92 | }
93 |
94 | .fade-ftin-up {
95 | animation: fadeftinup .3s forwards;
96 | }
97 |
98 | @keyframes fadeftinup {
99 | from {
100 | transform: translate3d(0, 120px, 0);
101 | opacity: 0;
102 | }
103 |
104 | to {
105 | transform: translate3d(0, 0, 0);
106 | opacity: 1;
107 | }
108 | }
109 |
110 | .fade-ftout-down {
111 | animation: fadeftoutdown .3s forwards;
112 | }
113 |
114 | @keyframes fadeftoutdown {
115 | from {
116 | transform: translate3d(0, 0, 0);
117 | opacity: 1;
118 | }
119 |
120 | to {
121 | transform: translate3d(0, 120px, 0);
122 | opacity: 0;
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/assets/css/common/common.less:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | -webkit-overflow-scrolling: touch;
5 | &::selection {
6 | background-color: #28c7b9;
7 | color: white;
8 | }
9 |
10 | &::-moz-selection {
11 | background-color: #28c7b9;
12 | color: white;
13 | }
14 |
15 | &::-webkit-selection {
16 | background-color: #28c7b9;
17 | color: white;
18 | }
19 |
20 | input:-webkit-autofill,
21 | textarea:-webkit-autofill,
22 | select:-webkit-autofill {
23 | -webkit-text-fill-color: #717171 !important;
24 | -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
25 | background-color: transparent;
26 | background-image: none;
27 | transition: background-color 50000s ease-in-out 0s;
28 | }
29 |
30 | img {
31 | object-fit: cover;
32 | width: 100%;
33 | height: 100%;
34 | }
35 |
36 | .img-optimization{
37 | width: 20%;
38 | height: 20%;
39 | transform: scale(5) translate(40%,40%);
40 | }
41 | }
42 |
43 | html {
44 | height: 100%;
45 | h1 {
46 | font-size: 2rem;
47 | }
48 | h2 {
49 | font-size: 1.5rem;
50 | }
51 | h3 {
52 | font-size: 1.125rem;
53 | }
54 | h4 {
55 | font-size: 1rem;
56 | }
57 | h5 {
58 | font-size: 0.8125rem;
59 | }
60 | h6 {
61 | font-size: 0.6875rem;
62 | }
63 | body {
64 | height: 100%;
65 | -webkit-font-smoothing: antialiased;
66 | -moz-osx-font-smoothing: grayscale;
67 |
68 | img {
69 | object-fit: cover;
70 | user-select: none;
71 | pointer-event: none;
72 | }
73 |
74 | /* 取消下列标签点击背景变色 */
75 | a,
76 | button,
77 | input,
78 | img,
79 | div {
80 | -webkit-tap-highlight-color: transparent;
81 | }
82 |
83 | .text-truncate {
84 | display: block;
85 | width: 100%;
86 | overflow: hidden;
87 | text-overflow: ellipsis;
88 | white-space: nowrap;
89 | }
90 |
91 | .paragraph-truncate {
92 | display: -webkit-box !important;
93 | -webkit-box-orient: vertical;
94 | text-overflow: ellipsis;
95 | -webkit-line-clamp: 2;
96 | overflow: hidden;
97 | white-space: pre-wrap;
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/assets/css/common/util.less:
--------------------------------------------------------------------------------
1 | .black-shadow(@x,@y,@z,@deep:0.4){
2 | box-shadow: @x @y @z rgba(0, 0, 0, @deep);
3 | }
4 | .pale-white(@deep:0.8){
5 | color: rgba(255, 255, 255, @deep);
6 | }
7 | .pale-black(@deep:0.8){
8 | color: rgba(0, 0, 0, @deep);
9 | }
10 | .click-bg{
11 | background-color: rgba(0, 0, 0, 0.1);
12 | }
13 | .mask(@index:1,@background:none){
14 | content: '';
15 | position: absolute;
16 | top: 0;
17 | left: 0;
18 | display: block;
19 | width: 100%;
20 | height: 100%;
21 | z-index: @index;
22 | background: @background;
23 | }
24 | .p-truncate(@line:1){
25 | display: -webkit-box !important;
26 | width: 100%;
27 | -webkit-box-orient: vertical;
28 | text-overflow: ellipsis;
29 | -webkit-line-clamp: @line;
30 | overflow: hidden;
31 | white-space: pre-wrap;
32 | }
--------------------------------------------------------------------------------
/src/assets/css/default/app.less:
--------------------------------------------------------------------------------
1 | #app {
2 | position: relative;
3 | width: 100vw;
4 | height: 100%;
5 |
6 | .app-banner {
7 | position: fixed;
8 | width: 100%;
9 | height: 100%;
10 | z-index: 9999;
11 | background: #def;
12 | img{
13 |
14 | }
15 | span {
16 | position: absolute;
17 | bottom: 20px;
18 | right: 20px;
19 | padding: 4px 8px;
20 | border-radius: 28px;
21 | border: 1px solid #fff;
22 | opacity: .4;
23 | color: #fff;
24 | font-size: 10px;
25 | }
26 | }
27 |
28 | .flod-left-enter-active {
29 | animation: flod-left-in 0.3s;
30 | }
31 |
32 | .flod-left-leave-active {
33 | animation: flod-left-out 0.3s;
34 | }
35 |
36 | .flod-right-enter-active {
37 | animation: flod-right-in 0.3s;
38 | }
39 |
40 | .flod-right-leave-active {
41 | animation: flod-right-out 0.3s;
42 | }
43 |
44 | .child-route-in {
45 | animation: child-route-in 0.4s forwards;
46 | }
47 |
48 | .child-route-out {
49 | animation: child-route-out 0.4s forwards;
50 | }
51 |
52 | @keyframes flod-left-in {
53 | from {
54 | transform: translate3d(100%, 0, 0);
55 | }
56 |
57 | to {
58 | transform: translate3d(0, 0, 0);
59 | }
60 | }
61 |
62 | @keyframes flod-left-out {
63 | from {
64 | transform: translate3d(0, 0, 0);
65 | }
66 |
67 | to {
68 | transform: translate3d(-100%, 0, 0);
69 | }
70 | }
71 |
72 | @keyframes flod-right-in {
73 | from {
74 | transform: translate3d(-100%, 0, 0);
75 | }
76 |
77 | to {
78 | transform: translate3d(0, 0, 0);
79 | }
80 | }
81 |
82 | @keyframes flod-right-out {
83 | from {
84 | transform: translate3d(0, 0, 0);
85 | }
86 |
87 | to {
88 | transform: translate3d(100%, 0, 0);
89 | }
90 | }
91 |
92 | @keyframes child-route-in {
93 | from {
94 | transform: translate3d(0, 160px, 0);
95 | opacity: 0;
96 | }
97 |
98 | to {
99 | transform: translate3d(0, 0, 0);
100 | opacity: 1;
101 | }
102 | }
103 |
104 | @keyframes child-route-out {
105 | from {
106 | transform: translate3d(0, 0, 0);
107 | opacity: 1;
108 | }
109 |
110 | to {
111 | transform: translate3d(0, 160px, 0);
112 | opacity: 0;
113 | }
114 | }
115 | }
--------------------------------------------------------------------------------
/src/assets/css/default/dj_detail.less:
--------------------------------------------------------------------------------
1 | .dj-detail {
2 | position: fixed;
3 | top: 0;
4 | width: 100%;
5 | height: 100%;
6 | background: #fff;
7 | overflow-x: hidden;
8 | overflow-y: scroll;
9 | z-index: 800;
10 |
11 | .dj-detail-cover {
12 | position: sticky;
13 | top: -60vw;
14 | width: 100%;
15 | height: 80vw;
16 | img{
17 | position: absolute;
18 | top: 0;
19 | z-index: 1;
20 | }
21 | div{
22 | position: absolute;
23 | width: 80%;
24 | left: 10px;
25 | bottom: 7vw;
26 | z-index: 2;
27 | b{
28 | font-size: 14px;
29 | color: rgba(255, 255, 255, .9);
30 | }
31 | p{
32 | margin-top: 3px;
33 | color: #999;
34 | font-size: 10px;
35 | }
36 | }
37 | &.active {
38 | z-index: 6;
39 | }
40 | }
41 |
42 | .dj-detail-contain {
43 | margin-top: -40px;
44 | margin-bottom: 120px;
45 |
46 | & /deep/ .van-tabs__wrap {
47 | z-index: 6;
48 |
49 | &::after {
50 | border: none;
51 | border-bottom: 1px solid #eee;
52 | }
53 |
54 | .van-tabs__nav {
55 | border-top-left-radius: 26px;
56 | border-top-right-radius: 26px;
57 | background: #fff !important;
58 |
59 | .van-tabs__line {
60 | width: 30px !important;
61 | }
62 | }
63 |
64 | .van-tab__text {
65 | font-size: 12px;
66 | }
67 | }
68 | }
69 | }
--------------------------------------------------------------------------------
/src/assets/css/default/explore.less:
--------------------------------------------------------------------------------
1 | .explore {
2 | width: 100%;
3 | height: 100%;
4 | padding-top: 44px;
5 | box-sizing: border-box;
6 | background: #000;
7 | overflow-y: auto;
8 | /deep/.van-pull-refresh__track>:last-child{
9 | margin-bottom: 100px;
10 | }
11 | }
--------------------------------------------------------------------------------
/src/assets/css/default/home.less:
--------------------------------------------------------------------------------
1 | .home {
2 | position: absolute;
3 | top: 0;
4 | left: 0;
5 | width: 100%;
6 | height: 100%;
7 | overflow: hidden;
8 | .home-contain {
9 | position: relative;
10 | width: 100%;
11 | height: 100%;
12 | overflow: hidden;
13 | .nav-aside {
14 | width: 60px;
15 | height: 44px;
16 | color: #fff;
17 | font-size: 1.4375rem;
18 | display: flex;
19 | box-sizing: border-box;
20 | align-items: center;
21 | &:first-child {
22 | justify-content: flex-start;
23 | padding-left: 12px;
24 | }
25 | &:last-child {
26 | justify-content: flex-end;
27 | padding-right: 12px;
28 | }
29 | }
30 | /deep/.van-tabs__wrap {
31 | position: absolute;
32 | width: 100vw;
33 | z-index: 555;
34 | &.van-hairline--top-bottom::after {
35 | content: unset !important;
36 | }
37 | .van-tab {
38 | transition: all 0.3s;
39 | .van-tab__text {
40 | color: #fff !important;
41 | }
42 | }
43 | .van-tab--active {
44 | font-weight: 600 !important;
45 | font-size: 16px !important;
46 | }
47 | }
48 | /deep/.van-tabs__content {
49 | width: 100vw;
50 | height: 100%;
51 | .van-tab__pane {
52 | position: absolute;
53 | height: 100%;
54 | overflow: hidden;
55 | background: #000;
56 | & > div {
57 | animation: fade-in 0.6s forwards;
58 | }
59 | @keyframes fade-in {
60 | from {
61 | transform: translateZ(0);
62 | opacity: 0.4;
63 | }
64 | to {
65 | transform: translateZ(0);
66 | opacity: 1;
67 | }
68 | }
69 | }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/assets/css/default/login.less:
--------------------------------------------------------------------------------
1 | .login {
2 | position: relative;
3 | width: 100vw;
4 | height: 100%;
5 | background: #fff;
6 | z-index: 999;
7 | .login-banner {
8 | position: relative;
9 | width: 100%;
10 | height: 52vh;
11 | border-radius: 0 0 43px 43px;
12 | overflow: hidden;
13 | &::before {
14 | content: '';
15 | position: absolute;
16 | bottom: 0;
17 | display: block;
18 | width: 100%;
19 | height: 50%;
20 | background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.6));
21 | }
22 | img {
23 | width: 100%;
24 | height: 100%;
25 | }
26 | }
27 | .login-box {
28 | position: fixed;
29 | top: 18vh;
30 | left: 0;
31 | right: 0;
32 | margin: 0 26px;
33 | height: 290px;
34 | background: #fff;
35 | padding: 16px;
36 | box-sizing: border-box;
37 | box-shadow: 0 0 24px rgba(0, 0, 0, 0.2);
38 | border-radius: 20px;
39 | animation-duration: 0.8s;
40 | & > h3 {
41 | margin-top: 8px;
42 | padding-bottom: 10px;
43 | text-align: center;
44 | color: #717171;
45 | }
46 | ._input-group {
47 | width: 100%;
48 | height: 46px;
49 | display: grid;
50 | grid-template-columns: 50px 1fr;
51 | grid-template-rows: 1fr;
52 | background: #fafafc;
53 | border-radius: 16px;
54 | overflow: hidden;
55 | margin: 20px 0;
56 | label {
57 | justify-self: center;
58 | align-self: center;
59 | color: #28c9e0;
60 | font-size: 1.125rem;
61 | }
62 | input[type='text'],
63 | input[type='password'] {
64 | display: block;
65 | border: none;
66 | outline: none;
67 | color: #717171;
68 | background: none;
69 | padding-right: 10px;
70 | box-sizing: border-box;
71 | font-size: 0.875rem;
72 | }
73 | }
74 | p {
75 | text-align: center;
76 | font-size: 0.75rem;
77 | text-decoration: underline;
78 | &:active {
79 | color: crimson;
80 | }
81 | }
82 | ._btn-login {
83 | position: absolute;
84 | left: 0;
85 | right: 0;
86 | bottom: -30px;
87 | margin: 0 auto;
88 | width: 86%;
89 | height: 52px;
90 | border: none;
91 | background: linear-gradient(to right, #28c9e0, #1cd5c6);
92 | color: #fff;
93 | border-radius: 46px;
94 | letter-spacing: 4px;
95 | box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2);
96 | outline: none;
97 | font-size: 0.875rem;
98 | transition: all 0.2s;
99 | &:active {
100 | background: linear-gradient(to right, #2ce2fa, #1ff5e4);
101 | }
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/assets/css/default/mv_detail.less:
--------------------------------------------------------------------------------
1 | .mv-detail {
2 | position: fixed;
3 | top: 0;
4 | width: 100%;
5 | height: 100%;
6 | background: #fff;
7 | overflow-x: hidden;
8 | overflow-y: scroll;
9 | z-index: 800;
10 | ._player {
11 | position: sticky;
12 | top: 0;
13 | width: 100vw;
14 | height: 57vw;
15 | background: #def;
16 | z-index: 2;
17 | ._player-cover {
18 | position: absolute;
19 | top: 0;
20 | width: 100%;
21 | height: 100%;
22 | z-index: 20;
23 | }
24 | }
25 | ._info {
26 | position: relative;
27 | padding: 10px 16px;
28 | color: #313131;
29 | z-index: 1;
30 | ._info-sname,
31 | ._info-singer {
32 | width: 100%;
33 | display: flex;
34 | }
35 | ._info-sname {
36 | max-width: 90%;
37 | font-weight: 800;
38 | }
39 | ._info-singer {
40 | justify-content: flex-end;
41 | span {
42 | font-size: 12px;
43 | }
44 | }
45 | ._summary-switch{
46 | position: absolute;
47 | right: 10px;
48 | top: 10px;
49 | padding: 6px;
50 | color: #717171;
51 | }
52 | }
53 | ._summary{
54 | position: relative;
55 | box-sizing: border-box;
56 | padding: 16px;
57 | padding-top: 0;
58 | width: 100%;
59 | overflow: hidden;
60 | z-index: 1;
61 | ul{
62 | li{
63 | &:first-child{
64 | background: none;
65 | color: #999999;
66 | font-size: 14px;
67 | margin-left: 0;
68 | padding: 4px 0;
69 | }
70 | font-size: 10px;
71 | padding: 3px 12px;
72 | display: inline-flex;
73 | color: #626262;
74 | background: #f3f3f3;
75 | border-radius: 22px;
76 | margin-right: 10px;
77 | margin-bottom: 8px;
78 | }
79 | }
80 | p{
81 | margin-top: 4px;
82 | color: #666666;
83 | font-size: 13px;
84 | }
85 | }
86 | ._tools{
87 | position: relative;
88 | display: grid;
89 | grid-template-columns: repeat(4,1fr);
90 | align-items: center;
91 | justify-items: center;
92 | width: 100vw;
93 | height: 20vw;
94 | border-bottom: 1px solid #e6e6e6;
95 | z-index: 1;
96 | span{
97 | display: flex;
98 | flex-direction: column;
99 | justify-content: center;
100 | align-items: center;
101 | font-size: 0.625rem;
102 | color: #717171;
103 | &::before{
104 | color: #000;
105 | margin-bottom: 3px;
106 | font-size: 1.6rem;
107 | }
108 | }
109 | }
110 | ._related{
111 |
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/assets/css/default/singer_album.less:
--------------------------------------------------------------------------------
1 | .singer-album {
2 | position: fixed;
3 | top: 0;
4 | width: 100%;
5 | height: 100%;
6 | background: #fff;
7 | overflow-x: hidden;
8 | overflow-y: scroll;
9 | z-index: 800;
10 | ._shower {
11 | position: sticky;
12 | top: 46px;
13 | z-index: 10;
14 | margin-top: -80px;
15 | width: 100%;
16 | height: 92px;
17 | border-radius: 22px 22px 0 0;
18 | background: #fff;
19 | ._contain-title {
20 | display: flex;
21 | align-items: center;
22 | padding: 16px;
23 | box-sizing: border-box;
24 | font-size: 1rem;
25 | i {
26 | font-size: 1.5rem;
27 | margin-right: 10px;
28 | color: #717171;
29 | }
30 | span {
31 | color: #999;
32 | font-size: 0.875rem;
33 | }
34 | }
35 | ._contain-tips {
36 | position: relative;
37 | display: grid;
38 | grid-template-columns: 40px 1fr 40px;
39 | grid-template-rows: 1fr;
40 | margin: 0 10px;
41 | height: 36px;
42 | border-radius: 44px;
43 | align-items: center;
44 | box-shadow: 0 0 6px rgba(0, 0, 0, 0.1);
45 | i {
46 | justify-self: center;
47 | font-size: 1.125rem;
48 | &:last-child {
49 | color: #b3b3b3;
50 | }
51 | }
52 | p {
53 | box-sizing: border-box;
54 | font-size: 0.875rem;
55 | a {
56 | color: #b3b3b3;
57 | }
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/assets/css/default/song_detail.less:
--------------------------------------------------------------------------------
1 | .song-detail {
2 | position: fixed;
3 | top: 0;
4 | width: 100%;
5 | height: 100%;
6 | z-index: 800;
7 | background: #fff;
8 | .song-detail-inside{
9 | position: relative;
10 | width: 100%;
11 | height: 100%;
12 | overflow-x: hidden;
13 | overflow-y: scroll;
14 | ._shower {
15 | position: sticky;
16 | top: 46px;
17 | z-index: 10;
18 | margin-top: -80px;
19 | width: 100%;
20 | height: 92px;
21 | border-radius: 22px 22px 0 0;
22 | background: #fff;
23 | ._contain-title {
24 | display: flex;
25 | align-items: center;
26 | padding: 16px;
27 | box-sizing: border-box;
28 | font-size: 1rem;
29 | i {
30 | font-size: 1.5rem;
31 | margin-right: 10px;
32 | color: #717171;
33 | }
34 | span {
35 | color: #999;
36 | font-size: 0.875rem;
37 | }
38 | }
39 | ._contain-tips {
40 | position: relative;
41 | display: grid;
42 | grid-template-columns: 40px 1fr 40px;
43 | grid-template-rows: 1fr;
44 | margin: 0 10px;
45 | height: 36px;
46 | border-radius: 44px;
47 | align-items: center;
48 | box-shadow: 0 0 6px rgba(0, 0, 0, 0.1);
49 | i {
50 | justify-self: center;
51 | font-size: 1.125rem;
52 | &:last-child {
53 | color: #b3b3b3;
54 | }
55 | }
56 | p {
57 | box-sizing: border-box;
58 | font-size: 0.875rem;
59 | a {
60 | color: #b3b3b3;
61 | }
62 | }
63 | }
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/assets/css/default/song_search.less:
--------------------------------------------------------------------------------
1 | .song-search {
2 | position: fixed;
3 | top: 0;
4 | width: 100%;
5 | height: 100%;
6 | background: #fff;
7 | overflow-x: hidden;
8 | overflow-y: scroll;
9 | z-index: 800;
10 | overflow: hidden;
11 | ._header{
12 | position: relative;
13 | width: 100%;
14 | height: 160px;
15 | ._header-control{
16 | position: relative;
17 | padding-left: 20px;
18 | display: grid;
19 | grid-template-columns: 1fr 80px;
20 | height: 38px;
21 | z-index: 3;
22 | transition: all .3s;
23 | transform: translateY(24px);
24 | &._header-control-focus{
25 | transform: translateY(16px);
26 | }
27 | ._header-control-input{
28 | display: grid;
29 | grid-template-columns: 40px 1fr;
30 | border-radius: 12px;
31 | background: #fff;
32 | align-items: center;
33 | justify-items: center;
34 | i{
35 | font-size: 1.125rem;
36 | color: #717171;
37 | }
38 | input[type=text]{
39 | box-sizing: border-box;
40 | padding: 10px;
41 | padding-left: 0;
42 | width: 100%;
43 | height: 100%;
44 | background: none;
45 | border: none;
46 | font-size: 0.875rem;
47 | }
48 | }
49 | &>i{
50 | align-self: center;
51 | justify-self: center;
52 | font-size: 1.875rem;
53 | color: #fff;
54 | }
55 | }
56 | ._header-banner{
57 | position: absolute;
58 | top: 0;
59 | z-index: 1;
60 | width: 100%;
61 | height: 100%;
62 | background: url(../../img/search-bg.jpg) no-repeat center/cover;
63 | transform: scale(1);
64 | transition: all .3s;
65 | &._header-banner-focus{
66 | transform: scale(1.2);
67 | }
68 | }
69 | }
70 | ._contain{
71 | position: absolute;
72 | top: 0;
73 | box-sizing: border-box;
74 | padding-top: 20px;
75 | padding-bottom: 50px;
76 | width: 100%;
77 | height: calc(100vh - 120px);
78 | border-radius: 24px 24px 0 0;
79 | background: #fff;
80 | z-index: 3;
81 | overflow: hidden;
82 | transition: all .3s;
83 | transform: translateY(120px);
84 | &._contain-focus{
85 | transform: translateY(70px);
86 | height: calc(100vh - 50px);
87 | }
88 | }
89 | }
--------------------------------------------------------------------------------
/src/assets/css/default/user_center.less:
--------------------------------------------------------------------------------
1 | .usercenter {
2 | position: relative;
3 | width: 100%;
4 | height: 100%;
5 | background: #000;
6 | color: #fff;
7 | overflow-x: hidden;
8 | overflow-y: auto;
9 | &>:last-child{
10 | margin-bottom: 100px;
11 | }
12 | .usercenter-contain {
13 | width: 100%;
14 | padding-bottom: 20px;
15 | ._userinfo {
16 | margin: 0 26px;
17 | margin-top: 40px;
18 | height: 80px;
19 | display: grid;
20 | grid-template-columns: repeat(3, 1fr);
21 | ._userinfo-item {
22 | display: flex;
23 | flex-direction: column;
24 | justify-content: space-evenly;
25 | align-items: center;
26 | b {
27 | font-size: 1.375rem;
28 | color: #12c770;
29 | }
30 | span {
31 | font-weight: 600;
32 | letter-spacing: 2px;
33 | color: rgba(255,255,255,.8);
34 | font-size: 0.875rem;
35 | }
36 | }
37 | }
38 | ._motto{
39 | text-align: center;
40 | color: #fff;
41 | font-size: 0.75rem;
42 | margin-top: 20px;
43 | line-height: 18px;
44 | }
45 |
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/assets/img/login-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adicwu/Starry/a9530e3901ed1e967be9feafc9bff863026dc591/src/assets/img/login-bg.jpg
--------------------------------------------------------------------------------
/src/assets/img/m-music-banner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adicwu/Starry/a9530e3901ed1e967be9feafc9bff863026dc591/src/assets/img/m-music-banner.jpg
--------------------------------------------------------------------------------
/src/assets/img/search-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adicwu/Starry/a9530e3901ed1e967be9feafc9bff863026dc591/src/assets/img/search-bg.jpg
--------------------------------------------------------------------------------
/src/assets/img/tx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adicwu/Starry/a9530e3901ed1e967be9feafc9bff863026dc591/src/assets/img/tx.jpg
--------------------------------------------------------------------------------
/src/components/Global/BreakHeader.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
38 |
39 |
60 |
--------------------------------------------------------------------------------
/src/components/Global/EmptyBox.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/components/Global/EmptyTextBox.vue:
--------------------------------------------------------------------------------
1 |
2 | {{ text }}
3 |
4 |
5 |
17 |
27 |
--------------------------------------------------------------------------------
/src/components/Global/IconText.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{info.text}}
5 |
6 |
7 |
8 |
16 |
17 |
35 |
--------------------------------------------------------------------------------
/src/components/Global/ImgLoader.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
5 |
6 |
7 |
8 |
26 |
27 |
60 |
--------------------------------------------------------------------------------
/src/components/Global/LoadingBlock.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{text}}
5 |
6 |
7 |
8 |
9 |
30 |
--------------------------------------------------------------------------------
/src/components/block/ScrollXBlock.vue:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
28 |
29 |
59 |
--------------------------------------------------------------------------------
/src/components/block/StrMarquee.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{text}}
4 |
{{text}}
5 |
6 |
7 |
8 |
31 |
32 |
62 |
--------------------------------------------------------------------------------
/src/components/card/AlbumList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
10 |
11 |
18 |
19 |
20 |
21 |
42 |
--------------------------------------------------------------------------------
/src/components/card/AudioCoverList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
10 |
11 |
18 |
19 |
20 |
21 |
22 |
63 |
--------------------------------------------------------------------------------
/src/components/card/AudioItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ detail.name }}
5 |
- {{ fullSinger }}
6 |
7 |
8 |
9 |
35 |
36 |
65 |
--------------------------------------------------------------------------------
/src/components/card/CircleCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
{{ name }}
7 |
{{ msg }}
8 |
9 |
10 |
11 |
26 |
27 |
71 |
--------------------------------------------------------------------------------
/src/components/card/MvRmdCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
10 |
{{ info.artistName }}
11 |
12 |
{{ info.name }}
13 |
14 |
15 |
16 |
38 |
39 |
77 |
--------------------------------------------------------------------------------
/src/components/card/PlaylistSmCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
![]()
12 |
16 |
17 |
18 |
19 |
27 |
28 |
61 |
--------------------------------------------------------------------------------
/src/components/card/SonglistCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
5 |
6 |
{{ title }}
7 |
{{ count | numFormat }}
8 |
9 |
10 |
11 |
34 |
35 |
89 |
--------------------------------------------------------------------------------
/src/components/card/UsPlaylistCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
{{ info.name }}
9 |
10 |
11 |
12 |
13 | {{ info.trackCount }}
14 |
15 |
16 |
17 | {{ info.playCount }}
18 |
19 |
20 |
21 |
22 |
23 |
31 |
32 |
95 |
--------------------------------------------------------------------------------
/src/components/card/VideoList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
9 |
10 |
11 |
{{ info.name }}
12 |
{{ info.publishTime | toPoint }}
13 |
14 |
15 |
16 |
17 |
44 |
--------------------------------------------------------------------------------
/src/components/card/ViewsBlockCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
{{ name }}
6 |
{{ elses | numFormat }}+ 播放量
7 |
8 |
9 |
10 |
11 |
36 |
37 |
92 |
--------------------------------------------------------------------------------
/src/components/carousel/AdCarouselItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
28 |
29 |
61 |
--------------------------------------------------------------------------------
/src/components/common/Fullscreen.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
27 |
--------------------------------------------------------------------------------
/src/components/common/FullscreenScroll.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
75 |
88 |
--------------------------------------------------------------------------------
/src/components/common/LoadingBlock.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{text}}
4 |
5 |
6 |
7 |
22 |
--------------------------------------------------------------------------------
/src/components/common/MovableMask.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 |
14 |
15 |
50 |
51 |
80 |
--------------------------------------------------------------------------------
/src/components/common/RequestLoader.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
15 |
26 |
27 |
77 |
--------------------------------------------------------------------------------
/src/components/form/AreaPickerList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ curText }}
5 |
6 |
14 |
15 |
16 |
17 |
18 |
66 |
67 |
101 |
--------------------------------------------------------------------------------
/src/components/form/AvatarList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
5 |
6 |
7 |
8 |
25 |
58 |
--------------------------------------------------------------------------------
/src/components/form/DatePickerList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ curText }}
5 |
6 |
15 |
16 |
17 |
18 |
19 |
62 |
63 |
97 |
--------------------------------------------------------------------------------
/src/components/form/EditInputList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
37 |
75 |
--------------------------------------------------------------------------------
/src/components/form/RadioItems.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
23 |
24 |
32 |
--------------------------------------------------------------------------------
/src/components/form/RadioList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ curText }}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
57 |
58 |
92 |
--------------------------------------------------------------------------------
/src/components/form/RadioListItems.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 | {{ item }}
5 |
6 |
7 |
8 |
9 |
10 |
27 |
28 |
52 |
--------------------------------------------------------------------------------
/src/components/form/TabBarReply.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
16 |
17 |
18 |
19 | 发送
20 |
21 |
22 |
23 |
24 |
25 |
49 |
--------------------------------------------------------------------------------
/src/components/form/TextAreaBox.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
37 |
38 |
65 |
--------------------------------------------------------------------------------
/src/components/form/TextAreaList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ value }}
5 |
6 |
18 |
19 |
20 |
21 |
22 |
57 |
93 |
--------------------------------------------------------------------------------
/src/components/header/AutoHeader.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
43 |
44 |
53 |
--------------------------------------------------------------------------------
/src/components/item/ArtistItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
34 |
--------------------------------------------------------------------------------
/src/components/item/DjradioItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
{{ info.name }}
11 |
{{ info.dj.nickname }}
12 |
13 |
14 |
15 |
16 |
24 |
25 |
65 |
--------------------------------------------------------------------------------
/src/components/item/SingerRadioItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
30 |
--------------------------------------------------------------------------------
/src/components/item/SonglistItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
{{ title }}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
23 |
24 |
63 |
--------------------------------------------------------------------------------
/src/components/player/child/TpCover.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
![]()
11 |
12 |
13 |
14 |
15 |
46 |
98 |
--------------------------------------------------------------------------------
/src/components/player/child/TpCricleProgress.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
47 |
76 |
--------------------------------------------------------------------------------
/src/components/player/child/TpCurList.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
59 |
89 |
--------------------------------------------------------------------------------
/src/components/player/child/TpHisList.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
62 |
92 |
--------------------------------------------------------------------------------
/src/components/player/child/TpOldList.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
27 |
57 |
--------------------------------------------------------------------------------
/src/components/player/child/TpProgress.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ audio.current | sToMs }}
5 | {{ audio.total | sToMs }}
6 |
7 |
10 |
11 |
12 |
13 |
69 |
--------------------------------------------------------------------------------
/src/components/player/child/TpTools.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 |
61 |
--------------------------------------------------------------------------------
/src/components/player/tabplayer.less:
--------------------------------------------------------------------------------
1 | .tab-player {
2 | position: fixed;
3 | bottom: 0;
4 | left: 0;
5 | width: 100vw;
6 | height: 50px;
7 | background: #fff;
8 | z-index: 888;
9 | box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.05);
10 | transition: all 0.3s;
11 | animation-duration: .3s;
12 | &._active-contain {
13 | height: 100%;
14 | }
15 | ._banner {
16 | position: absolute;
17 | top: 0;
18 | left: 0;
19 | width: 100%;
20 | height: 100%;
21 | // filter: blur(10px);
22 | z-index: -1;
23 | animation-duration: 0.6s;
24 | background-size: cover;
25 | background-position: center;
26 | &::before {
27 | content: '';
28 | position: absolute;
29 | top: 0;
30 | left: 0;
31 | display: block;
32 | width: 100%;
33 | height: 100%;
34 | background: #333;
35 | opacity: 0.8;
36 | z-index: 2;
37 | transform: scale(1.2);
38 | }
39 | & > img {
40 | transform: scale(1.4);
41 | }
42 | }
43 |
44 | ._info {
45 | display: flex;
46 | flex-direction: column;
47 | justify-content: center;
48 | width: calc(100% - 160px);
49 | height: 100%;
50 | overflow: hidden;
51 | padding: 0 16px;
52 | box-sizing: border-box;
53 | &._active-info {
54 | position: absolute;
55 | bottom: 28%;
56 | width: 100%;
57 | height: unset;
58 | overflow: hidden;
59 | align-items: center;
60 | p {
61 | max-width: 90%;
62 | text-align: center;
63 | &:first-child {
64 | font-size: 1.25rem;
65 | line-height: 1.4rem;
66 | color: #fff;
67 | font-weight: 600;
68 | }
69 | &:last-child {
70 | margin-top: 6px;
71 | font-size: 0.875rem;
72 | color: rgba(255, 255, 255, 0.8);
73 | }
74 | }
75 | }
76 | p {
77 | max-width: 100%;
78 | &:first-child {
79 | font-size: 0.875rem;
80 | color: #333;
81 | }
82 | &:last-child {
83 | font-size: 0.625rem;
84 | color: #808080;
85 | }
86 | }
87 | }
88 | ._tools{
89 | position: absolute;
90 | bottom: 16%;
91 | padding: 0 30px;
92 | box-sizing: border-box;
93 | width: 100%;
94 | }
95 | ._num-progress {
96 | position: absolute;
97 | top: 280px;
98 | left: 0;
99 | right: 0;
100 | margin: auto;
101 | color: #fff;
102 | display: flex;
103 | justify-content: space-between;
104 | width: 204px;
105 | font-size: 14px;
106 | }
107 |
108 |
109 | }
110 |
--------------------------------------------------------------------------------
/src/components/tool/AvatarsHandler.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | ![]()
4 |
5 |
6 |
7 |
32 |
33 |
49 |
--------------------------------------------------------------------------------
/src/components/utils/LoadingBlock.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import LoadingBlock from '../common/LoadingBlock.vue'
3 | const Mask = Vue.extend(LoadingBlock)
4 | function insertDom(parent, el, binding) {
5 | el.instance.visible = true;
6 | parent.appendChild(el.mask)
7 | }
8 | function removeDom(rootDom, el, binding) {
9 | if (!binding.value) {
10 | rootDom.removeChild(el.mask)
11 | el.instance && el.instance.$destroy();
12 | }
13 | }
14 | const directive = () => {
15 | Vue.directive('loading', {
16 | bind(el, binding) {
17 | const mask = new Mask({
18 | el: document.createElement('div'),
19 | data: {}
20 | });
21 | el.instance = mask
22 | el.mask = mask.$el
23 | el.oldValue = binding.value
24 | el.isOver = false
25 | if (binding.value) {
26 | Vue.nextTick(() => {
27 | el.oldDisplay = el.style.display
28 | el.style.display = 'none';
29 | el.rootDom = typeof binding.modifiers.child === 'undefined' ? el.parentElement : el;
30 | insertDom(el.rootDom, el, binding)
31 | })
32 | }
33 | },
34 | update(el, binding) {
35 | if (el.oldValue !== binding.value && !el.isOver) {
36 | el.isOver = true
37 | removeDom(el.rootDom, el, binding)
38 | el.style.display = el.oldDisplay;
39 | }
40 | },
41 | unbind(el) {
42 | el.instance && el.instance.$destroy();
43 | }
44 | })
45 | };
46 | export default directive;
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | //default
2 | import Vue from 'vue'
3 | import App from './App.vue'
4 | import router from './router'
5 | import store from './store'
6 | import axios from 'axios'
7 |
8 | //plugins
9 | import '@/plugins/Vant'
10 | import '@/plugins/GlobalComps'
11 | import '@/plugins/ADialog'
12 | import '@/utils/Filters'
13 | import ToolFunc from '@/utils/ToolFunc'
14 | import AdDirect from '@/utils/AdDirect'
15 | import LoadingBlock from '@/components/utils/LoadingBlock'
16 | import Bus from '@/utils/Bus'
17 | Vue.use(AdDirect)
18 | Vue.use(ToolFunc)
19 | Vue.use(Bus)
20 | Vue.use(LoadingBlock)
21 |
22 |
23 | //axios
24 | Vue.prototype.axios = axios
25 | axios.defaults.withCredentials = true
26 | //vuex
27 | Vue.prototype.$store = store
28 | //else
29 | Vue.prototype.baseImg = 'https://api.adicw.cn/uploads/';
30 | Vue.prototype.squareImgSize = '?param=300y300';
31 | Vue.prototype.rectangleImgSize = '?param=533y300';
32 | Vue.prototype.dfImg = 'http://p1.music.126.net/Vxsf58sMyNjqnWVZa9Wbfw==/18991864347187831.jpg';
33 | Vue.config.productionTip = false
34 |
35 | //router
36 | new Vue({
37 | render: h => h(App),
38 | router,
39 | }).$mount('#app')
--------------------------------------------------------------------------------
/src/plugins/ADialog.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Confirm from '@/components/common/ADialog'
3 | const ConfirmBox = Vue.extend(Confirm);
4 | Confirm.install = (content, options) => {
5 | options = Object.assign({
6 | content: content,
7 | }, options);
8 | let instance = new ConfirmBox({
9 | data: options
10 | }).$mount();
11 | document.body.appendChild(instance.$el);
12 | return instance.confirm();
13 | };
14 | Vue.prototype.$aconfirm = Confirm.install;
--------------------------------------------------------------------------------
/src/plugins/GlobalComps.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | const changeStr = str => str.charAt(0).toUpperCase() + str.slice(1)
4 | const requireComponent = require.context('../components/Global', false, /\.vue$/)
5 | requireComponent.keys().forEach(fileName => {
6 | const config = requireComponent(fileName)
7 | const componentName = changeStr(
8 | fileName.replace(/^\.\//, '').replace(/\.\w+$/, '')
9 | )
10 | Vue.component(componentName, config.default || config)
11 | })
12 |
--------------------------------------------------------------------------------
/src/plugins/Vant.js:
--------------------------------------------------------------------------------
1 | import 'vant/lib/index.css';
2 | import Vue from 'vue'
3 | const list = [
4 | Popup,
5 | Overlay,
6 | Icon,
7 | Slider,
8 | Button,
9 | Swipe,
10 | SwipeItem,
11 | Notify,
12 | Toast,
13 | Tab,
14 | Tabs,
15 | Field,
16 | ShareSheet,
17 | ImagePreview,
18 | Loading,
19 | Empty,
20 | PullRefresh,
21 | Circle,
22 | Sticky,
23 | NoticeBar,
24 | DatetimePicker,
25 | Area,
26 | ]
27 | import {
28 | Popup,
29 | Overlay,
30 | Icon,
31 | Slider,
32 | Button,
33 | Swipe,
34 | SwipeItem,
35 | Notify,
36 | Toast,
37 | Tab,
38 | Tabs,
39 | Field,
40 | ShareSheet,
41 | ImagePreview,
42 | Loading,
43 | Empty,
44 | PullRefresh,
45 | Circle,
46 | Sticky,
47 | NoticeBar,
48 | DatetimePicker,
49 | Area,
50 | } from 'vant'
51 | list.forEach(item => {
52 | let no_list = [];
53 | !no_list.includes(item) && Vue.use(item)
54 | })
55 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import VueRouter from 'vue-router'
2 | import Vue from 'vue'
3 |
4 | const routerList = []
5 | function importAll(routerArr) {
6 | routerArr.keys().forEach(key => {
7 | routerList.push(routerArr(key).default)
8 | })
9 | }
10 | importAll(require.context('./route', true, /\.routes\.js/))
11 | Vue.use(VueRouter)
12 |
13 | const routes = [{
14 | path: '/',
15 | component: () => import('../views/Home/Home'),
16 | meta: {
17 | title: 'Starry',
18 | }
19 | },
20 | // {
21 | // path: '*',
22 | // component: ,
23 | // meta: {
24 | // title: 'Starry'
25 | // },
26 | // },
27 | ...routerList
28 | ]
29 | const router = new VueRouter({
30 | mode: 'history',
31 | // mode: 'hash',
32 | routes,
33 | })
34 |
35 | router.beforeEach((to, from, next) => {
36 | next();
37 | })
38 | export default router
39 |
--------------------------------------------------------------------------------
/src/router/route/login.routes.js:
--------------------------------------------------------------------------------
1 | const Login = () => import('@/views/Login/Login')
2 | export default {
3 | path: '/login',
4 | component: Login,
5 | meta: {
6 | title: '登录 - Starry'
7 | },
8 | }
9 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import user from './modules/user'
4 | import music from './modules/music'
5 |
6 | Vue.use(Vuex)
7 |
8 | export default new Vuex.Store({
9 | state: {
10 | loading: true
11 | },
12 | mutations: {},
13 | actions: {},
14 | modules: {
15 | user,
16 | music
17 | }
18 | })
19 |
--------------------------------------------------------------------------------
/src/store/modules/user.js:
--------------------------------------------------------------------------------
1 | import {
2 | logout
3 | } from 'apis/user'
4 | export default {
5 | state: sessionStorage.getItem('state') ? JSON.parse(sessionStorage.getItem('state')) : {
6 | flag: false,
7 | userid: null,
8 | token: null,
9 | cookie: null,
10 | },
11 | mutations: {
12 | setAccessToken(state, auth) {
13 | if (auth.token != state.token) {
14 | state.flag = auth.flag
15 | state.token = auth.token
16 | state.userid = auth.userid
17 | state.cookie = auth.cookie
18 | }
19 | },
20 | clearAccessToken(state) {
21 | sessionStorage.clear()
22 | location.reload()
23 | }
24 | },
25 | getters: {
26 |
27 | },
28 | actions: {
29 | signOut({commit}) {
30 | return new Promise(resolve => {
31 | logout().then(res => {
32 | commit('clearAccessToken')
33 | resolve()
34 | })
35 | })
36 | }
37 | },
38 | }
39 |
--------------------------------------------------------------------------------
/src/utils/Bus.js:
--------------------------------------------------------------------------------
1 | const install = (Vue) => {
2 | const Bus = new Vue({
3 | methods: {
4 | on(event, ...args) {
5 | this.$on(event, ...args);
6 | },
7 | emit(event, callback) {
8 | this.$emit(event, callback);
9 | },
10 | off(event, callback) {
11 | this.$off(event, callback);
12 | }
13 | }
14 | })
15 | Vue.prototype.$bus = Bus;
16 | }
17 | export default install;
18 |
--------------------------------------------------------------------------------
/src/utils/Constellation.js:
--------------------------------------------------------------------------------
1 | export const constellation = [{
2 | date: [312, 419],
3 | text: '白羊座'
4 | },
5 | {
6 | date: [420, 520],
7 | text: '金牛座'
8 | },
9 | {
10 | date: [622, 722],
11 | text: '巨蟹座'
12 | },
13 | {
14 | date: [723, 822],
15 | text: '狮子座'
16 | },
17 | {
18 | date: [823, 922],
19 | text: '处女座'
20 | },
21 | {
22 | date: [923, 1023],
23 | text: '天秤座'
24 | },
25 | {
26 | date: [1024, 1122],
27 | text: '天蝎座',
28 | },
29 | {
30 | date: [1123, 1221],
31 | text: '射手座'
32 | },
33 | {
34 | date: [1222, 119],
35 | text: '摩羯座'
36 | },
37 | {
38 | date: [120, 218],
39 | text: '水瓶座'
40 | },
41 | {
42 | date: [219, 320],
43 | text: '双鱼座'
44 | }
45 | ]
46 |
--------------------------------------------------------------------------------
/src/utils/Decorator.js:
--------------------------------------------------------------------------------
1 | import {
2 | throttle,
3 | debounce
4 | } from 'lodash'
5 | import Vue from 'vue'
6 | export const throttles = function (wait = 300, options = {}) {
7 | return function (target, name, descriptor) {
8 | descriptor.value = throttle(descriptor.value, wait, options)
9 | }
10 | }
11 | export const debounces = function (wait = 300, options = {}) {
12 | return function (target, name, descriptor) {
13 | descriptor.value = debounce(descriptor.value, wait, options)
14 | }
15 | }
16 | export const adConfirm = function (text) {
17 | const {
18 | $aconfirm
19 | } = Vue.prototype;
20 | return function (target, name, descriptor) {
21 | let originFn = descriptor.value;
22 | descriptor.value = function (...args) {
23 | $aconfirm(text)
24 | .then(originFn.bind(this, ...args))
25 | .catch(() => {});
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/src/utils/Filters.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | const filters = {
3 | numFormat(val) {
4 | val = val.toString();
5 | return val.length > 4 ? `${val.substr(0, val.length - 4)}万` : val;
6 | },
7 | msToYmd(val) {
8 | let date = new Date(val)
9 | return `${date.getFullYear()}.${date.getMonth() + 1}.${date.getDate()}`
10 | },
11 | }
12 | Object.keys(filters).forEach(k => Vue.filter(k, filters[k]))
13 |
--------------------------------------------------------------------------------
/src/utils/ToolFunc.js:
--------------------------------------------------------------------------------
1 | export default {
2 | install(Vue, options) {
3 | window.debouncetimer = null
4 | window.throttleflag = true
5 | Object.assign(Vue.prototype, {
6 | getPresentDate() {
7 | let date = new Date();
8 | let year = date.getFullYear();
9 | let month = (date.getMonth() + 1).toString().padStart(2, '0');
10 | let day = (date.getDate()).toString().padStart(2, '0');
11 | let fulldate = year + "-" + month + "-" + day;
12 | return fulldate;
13 | },
14 | getFullPresentDate() {
15 | let date = new Date();
16 | let year = date.getFullYear();
17 | let month = (date.getMonth() + 1).toString().padStart(2, '0');
18 | let day = date
19 | .getDate()
20 | .toString()
21 | .padStart(2, '0');
22 | let hours = date
23 | .getHours()
24 | .toString()
25 | .padStart(2, '0');
26 | let mins = date
27 | .getMinutes()
28 | .toString()
29 | .padStart(2, '0');
30 | return year + '.' + month + '.' + day + ' ' + hours + ':' + mins;
31 | },
32 | toMainPage(path, id) {
33 | if (this.$route.path === path && this.$route.query.id === id) return;
34 | typeof id != 'undefined' ? this.$router.push(`${path}?id=${id}`) : this.$router.push(path)
35 | },
36 | debounce(fn, del = 300) {
37 | if (window.debouncetimer != null) clearTimeout(window.debouncetimer)
38 | window.debouncetimer = setTimeout(fn, del)
39 | },
40 | throttle(fn, del = 300) {
41 | if (!window.throttleflag) return;
42 | window.throttleflag = false
43 | setTimeout(() => {
44 | fn();
45 | window.throttleflag = true
46 | }, del)
47 | }
48 | })
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/views/Dj/child/DjSimilar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
![]()
7 |
8 |
9 |
{{item.name}}
10 |
{{item.desc}}
11 |
节目:{{item.programCount}},订阅:34.1w
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
51 |
52 |
108 |
--------------------------------------------------------------------------------
/src/views/Home/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
17 |
22 |
27 |
28 |
29 |
30 |
31 |
32 |
36 |
37 | -
38 |
39 |
40 |
41 |
88 |
89 |
92 |
--------------------------------------------------------------------------------
/src/views/Home/child/Explore.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
60 |
61 |
64 |
--------------------------------------------------------------------------------
/src/views/Home/child/SkySquare.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
58 |
59 |
69 |
--------------------------------------------------------------------------------
/src/views/Home/child/Village copy.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
52 |
53 |
63 |
--------------------------------------------------------------------------------
/src/views/Home/child/Village.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
14 |
15 |
16 |
17 |
18 |
19 |
66 |
67 |
76 |
--------------------------------------------------------------------------------
/src/views/Home/child/child/ExBoutiqueAudioList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
44 |
45 |
50 |
--------------------------------------------------------------------------------
/src/views/Home/child/child/ExMvTop.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
15 |
53 |
54 |
59 |
--------------------------------------------------------------------------------
/src/views/Home/child/child/ExRmdRadiosStation.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
15 |
48 |
49 |
54 |
--------------------------------------------------------------------------------
/src/views/Home/child/child/SsRmdMv.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 推荐Mv
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
32 |
33 |
50 |
--------------------------------------------------------------------------------
/src/views/Home/routes/child/HsAlbum.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
55 |
--------------------------------------------------------------------------------
/src/views/Home/routes/child/HsDj.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
57 |
--------------------------------------------------------------------------------
/src/views/Home/routes/child/HsMv.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
17 |
18 |
19 |
20 |
21 |
58 |
--------------------------------------------------------------------------------
/src/views/Home/routes/child/HsSinger.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
37 |
--------------------------------------------------------------------------------
/src/views/Home/routes/child/HsSong.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
17 |
18 |
19 |
20 |
21 |
57 |
--------------------------------------------------------------------------------
/src/views/Home/routes/child/HsSonglist.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 | {{item.trackCount}}首 by {{item.creator.nickname}} ,播放{{item.playCount|numFormat}}次
19 |
20 |
21 |
22 |
23 |
63 |
--------------------------------------------------------------------------------
/src/views/Home/routes/child/HsSuggest.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
47 |
--------------------------------------------------------------------------------
/src/views/Home/routes/child/HsUser.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
35 |
--------------------------------------------------------------------------------
/src/views/Home/routes/child/HsVideo.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 | 接口开发中
11 |
12 |
13 |
44 |
--------------------------------------------------------------------------------
/src/views/Login/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

5 |
6 |
7 |
Starry 登录
8 |
9 |
10 |
17 |
18 |
19 |
20 |
27 |
28 |
请使用网易云音乐账号,暂不开放注册
29 |
详情致网易云音乐app
30 |
31 |
32 |
33 |
34 |
35 |
84 |
85 |
88 |
--------------------------------------------------------------------------------
/src/views/Singer/child/SdAlbum.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
57 |
--------------------------------------------------------------------------------
/src/views/Singer/child/SdMv.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
69 |
--------------------------------------------------------------------------------
/src/views/Singer/child/SdSong.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 | 收藏热门50
13 |
14 |
15 | 管理
16 |
17 |
18 |
19 |
20 |
21 |
43 |
--------------------------------------------------------------------------------
/src/views/Song/SongSearch.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
83 |
84 |
87 |
--------------------------------------------------------------------------------
/src/views/Square/DjSquare.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
17 |
18 |
19 |
20 |
21 |
76 |
77 |
92 |
--------------------------------------------------------------------------------
/src/views/Square/MvSquare.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
55 |
56 |
92 |
--------------------------------------------------------------------------------
/src/views/Square/SonglistSquare.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
55 |
56 |
85 |
--------------------------------------------------------------------------------
/src/views/Square/child/DjBanner.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
33 |
34 |
46 |
--------------------------------------------------------------------------------
/src/views/Square/child/MvChina.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
39 |
40 |
50 |
--------------------------------------------------------------------------------
/src/views/Square/child/MvEamerica.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
39 |
40 |
50 |
--------------------------------------------------------------------------------
/src/views/Square/child/MvJapan.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
39 |
40 |
50 |
--------------------------------------------------------------------------------
/src/views/Square/child/MvKorea.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
39 |
40 |
50 |
--------------------------------------------------------------------------------
/src/views/Square/child/SonglistBoutique.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
20 |
21 |
22 |
23 |
24 |
25 |
47 |
48 |
59 |
--------------------------------------------------------------------------------
/src/views/Square/child/SonglistHot.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
14 |
15 |
16 |
17 |
18 |
37 |
38 |
49 |
--------------------------------------------------------------------------------
/src/views/Square/child/SonglistPopular.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
20 |
21 |
22 |
23 |
24 |
25 |
47 |
48 |
59 |
--------------------------------------------------------------------------------
/src/views/Square/child/SonglistRmd.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
14 |
15 |
16 |
17 |
18 |
41 |
42 |
53 |
--------------------------------------------------------------------------------
/src/views/User/UserChatroom.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
25 |
--------------------------------------------------------------------------------
/src/views/User/UserFriend.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
42 |
--------------------------------------------------------------------------------
/src/views/User/UserNews.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
41 |
--------------------------------------------------------------------------------
/src/views/User/child/UdTrend.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 可可爱爱,没有动态 O(∩_∩)O ~
6 |
7 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
63 |
64 |
78 |
--------------------------------------------------------------------------------
/src/views/User/child/UfAartistSub.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
36 |
--------------------------------------------------------------------------------
/src/views/User/child/UfFolloweds.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
36 |
--------------------------------------------------------------------------------
/src/views/User/child/UfFollows.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
36 |
--------------------------------------------------------------------------------
/src/views/User/child/UnComments.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
36 |
--------------------------------------------------------------------------------
/src/views/User/child/UnForwards.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
36 |
--------------------------------------------------------------------------------
/src/views/User/child/UnNotices.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
36 |
--------------------------------------------------------------------------------
/src/views/User/child/UnPrivate.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
38 |
--------------------------------------------------------------------------------
/src/views/User/routes/UsetTrendDetail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
73 |
--------------------------------------------------------------------------------
/src/views/User/routes/child/UtdChat.vue:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
68 |
--------------------------------------------------------------------------------
/src/views/User/routes/child/UtdForward.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
53 |
--------------------------------------------------------------------------------
/src/views/User/routes/child/UtdPraise.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
52 |
--------------------------------------------------------------------------------
/src/views/Video/child/MdComment.vue:
--------------------------------------------------------------------------------
1 |
2 |
22 |
23 |
24 |
67 |
68 |
83 |
--------------------------------------------------------------------------------
/src/views/Video/child/MdRelated.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
37 |
38 |
51 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | const CompressionPlugin = require('compression-webpack-plugin'),
2 | productionGzipExtensions = [
3 | "js",
4 | "css",
5 | "svg",
6 | "woff",
7 | "ttf",
8 | "json",
9 | "html"
10 | ],
11 | path = require('path');
12 |
13 | const resolve = dir => path.join(__dirname, dir);
14 | const devConfig = {
15 | // 跨域
16 | devServer: {
17 | proxy: {
18 | '/api': {
19 | target: "https://musicapi.adicw.cn/",
20 | changeOrigin: true,
21 | ws: true,
22 | pathRewrite: {
23 | '^/api': ''
24 | }
25 | }
26 | }
27 | },
28 | }
29 | const commonConfig = {
30 | pluginOptions: {
31 | 'style-resources-loader': {
32 | preProcessor: 'less',
33 | patterns: [
34 | // 全局变量路径,不能使用路径别名
35 | path.resolve(__dirname, 'src/assets/css/common/util.less')
36 | ]
37 | }
38 | },
39 | //别名配置
40 | //图片转base64
41 | chainWebpack: config => {
42 | config.resolve.alias
43 | .set('styles', resolve('./src/assets/css'))
44 | .set('apis', resolve('./src/api'))
45 | .set('static', resolve('./src/assets'))
46 | .set('comps', resolve('./src/components'));
47 | config.module
48 | .rule('images')
49 | .use('url-loader')
50 | .loader('url-loader')
51 | .tap(options => Object.assign(options, {
52 | limit: 20000
53 | }))
54 | },
55 | }
56 | const defaultConfig = {
57 | configureWebpack: {
58 | plugins: [
59 | // Gzip
60 | new CompressionPlugin({
61 | filename: "[path].gz[query]",
62 | test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"),
63 | threshold: 1024,
64 | minRatio: 0.8, //压缩率大于0.8的才压缩
65 | deleteOriginalAssets: false //是否删除原文件
66 | })
67 | ],
68 | },
69 | productionSourceMap: false, //不输出map文件
70 | // devServer: {},
71 |
72 |
73 | // 跨域
74 | // devServer: {
75 | // proxy: {
76 | // '/api': {
77 | // target: "https://s1.hdslb.com/",
78 | // changeOrigin: true,
79 | // ws: true,
80 | // pathRewrite:{
81 | // '^/api': ''
82 | // }
83 | // }
84 | // }
85 | // },
86 |
87 | // 部署应用时的基本 URL
88 | // publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
89 | }
90 | const appConfig = {
91 | runtimeCompiler: true,
92 | publicPath: './',
93 | }
94 | module.exports = {
95 | ...devConfig,
96 | ...commonConfig,
97 | ...defaultConfig
98 | }
99 |
--------------------------------------------------------------------------------
精彩评论
5 |6 |
7 |
8 |最新评论
11 |12 |
13 |
14 |最新评论
17 |18 |
19 |
20 |