Repository: powerdong/Music-player
Branch: master
Commit: c505e40c41a3
Files: 193
Total size: 616.8 KB
Directory structure:
gitextract_0ydqwdr6/
├── .vscode/
│ └── settings.json
├── README.md
└── musicPlayer/
├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .postcssrc.js
├── README.md
├── build/
│ ├── build.js
│ ├── check-versions.js
│ ├── utils.js
│ ├── vue-loader.conf.js
│ ├── webpack.base.conf.js
│ ├── webpack.dev.conf.js
│ └── webpack.prod.conf.js
├── config/
│ ├── dev.env.js
│ ├── index.js
│ └── prod.env.js
├── index.html
├── package.json
├── src/
│ ├── App.vue
│ ├── api/
│ │ ├── config.js
│ │ └── index.js
│ ├── assets/
│ │ ├── Bus.js
│ │ ├── Mixins.js
│ │ ├── styles/
│ │ │ ├── border.css
│ │ │ ├── global.less
│ │ │ └── reset.css
│ │ └── utils/
│ │ ├── cookie.js
│ │ ├── filters.js
│ │ ├── getAstro.js
│ │ ├── getPhone.js
│ │ ├── getRandomArrayElements.js
│ │ ├── modalScroll.js
│ │ ├── scrollStopVideo.js
│ │ └── setKeyWords.js
│ ├── base/
│ │ ├── albumPage/
│ │ │ ├── index.vue
│ │ │ └── index2.vue
│ │ ├── alert.vue
│ │ ├── audioAllTitle.vue
│ │ ├── button.vue
│ │ ├── circleLoading.vue
│ │ ├── comments.vue
│ │ ├── djDetailPage/
│ │ │ ├── components/
│ │ │ │ └── changeNav.vue
│ │ │ ├── index.vue
│ │ │ └── index2.vue
│ │ ├── djSublistCard.vue
│ │ ├── generalNav.vue
│ │ ├── icon.vue
│ │ ├── idxCard.vue
│ │ ├── imgCard.vue
│ │ ├── interchangeable.vue
│ │ ├── loading.vue
│ │ ├── loginPageIsShow.vue
│ │ ├── pageErrorInfo.vue
│ │ ├── pageLoading.vue
│ │ ├── searchInput.vue
│ │ ├── shouldLogin.vue
│ │ ├── slider.vue
│ │ ├── sliderNav.vue
│ │ ├── song.vue
│ │ ├── songListPage/
│ │ │ └── index.vue
│ │ └── titleFooter.vue
│ ├── components/
│ │ ├── detailPage/
│ │ │ └── index.vue
│ │ └── top-tip/
│ │ └── index.vue
│ ├── getInfos/
│ │ ├── getData.js
│ │ └── icons.js
│ ├── main.js
│ ├── pages/
│ │ ├── audioIndex/
│ │ │ ├── components/
│ │ │ │ ├── audioList.vue
│ │ │ │ ├── bar.vue
│ │ │ │ ├── functionButton.vue
│ │ │ │ ├── lyricPage.vue
│ │ │ │ ├── playIcons.vue
│ │ │ │ ├── playing.vue
│ │ │ │ └── small.vue
│ │ │ └── index.vue
│ │ ├── commentsIndex/
│ │ │ ├── components/
│ │ │ │ ├── albumListInfo.vue
│ │ │ │ └── centerMenu.vue
│ │ │ └── index.vue
│ │ ├── dateRecommend/
│ │ │ └── index.vue
│ │ ├── dj/
│ │ │ ├── childrenPage/
│ │ │ │ ├── class.vue
│ │ │ │ ├── classRecommend.vue
│ │ │ │ ├── djPayGift.vue
│ │ │ │ ├── ranking-anchor.vue
│ │ │ │ ├── ranking-program.vue
│ │ │ │ ├── ranking-radio.vue
│ │ │ │ ├── ranking.vue
│ │ │ │ └── topConDetail.vue
│ │ │ ├── components/
│ │ │ │ ├── boutiqueRecom.vue
│ │ │ │ ├── icons.vue
│ │ │ │ ├── radioRecom.vue
│ │ │ │ └── swiper.vue
│ │ │ ├── index.vue
│ │ │ ├── public.vue
│ │ │ ├── publicClass.vue
│ │ │ ├── publicImgWrap.vue
│ │ │ └── titleAndThree.vue
│ │ ├── djSublist/
│ │ │ └── index.vue
│ │ ├── findIndex/
│ │ │ ├── components/
│ │ │ │ ├── chinese.vue
│ │ │ │ ├── europe.vue
│ │ │ │ ├── icons.vue
│ │ │ │ ├── japan.vue
│ │ │ │ ├── korea.vue
│ │ │ │ ├── moreNewDish.vue
│ │ │ │ ├── moreNewSongs.vue
│ │ │ │ ├── newDish.vue
│ │ │ │ ├── personalizedSongList.vue
│ │ │ │ └── swiper.vue
│ │ │ └── index.vue
│ │ ├── friendIndex/
│ │ │ ├── index.vue
│ │ │ └── public.vue
│ │ ├── homeIndex/
│ │ │ ├── components/
│ │ │ │ ├── addNewPlayList.vue
│ │ │ │ ├── homeList.vue
│ │ │ │ ├── icons.vue
│ │ │ │ └── songList.vue
│ │ │ └── index.vue
│ │ ├── idx/
│ │ │ └── index.vue
│ │ ├── loginIndex/
│ │ │ ├── components/
│ │ │ │ ├── accountLogin.vue
│ │ │ │ ├── phoneAccount.vue
│ │ │ │ ├── phonePwd.vue
│ │ │ │ ├── phoneVerify.vue
│ │ │ │ ├── verifyCode.vue
│ │ │ │ └── verifyInfo.vue
│ │ │ └── index.vue
│ │ ├── myFavorite/
│ │ │ ├── components/
│ │ │ │ ├── albums.vue
│ │ │ │ ├── artists.vue
│ │ │ │ ├── column.vue
│ │ │ │ ├── mlog.vue
│ │ │ │ └── videos.vue
│ │ │ └── index.vue
│ │ ├── nav/
│ │ │ ├── components/
│ │ │ │ ├── login-bottom.vue
│ │ │ │ ├── login-icons-bottom.vue
│ │ │ │ ├── login-icons-top.vue
│ │ │ │ ├── login-icons.vue
│ │ │ │ ├── login-top.vue
│ │ │ │ └── login.vue
│ │ │ └── index.vue
│ │ ├── recentlyPlayed/
│ │ │ └── index.vue
│ │ ├── recommend/
│ │ │ ├── fine/
│ │ │ │ └── index.vue
│ │ │ ├── general/
│ │ │ │ └── index.vue
│ │ │ ├── index.vue
│ │ │ ├── navIndex/
│ │ │ │ └── navList.vue
│ │ │ └── recommended/
│ │ │ └── index.vue
│ │ ├── searchIndex/
│ │ │ ├── components/
│ │ │ │ ├── history.vue
│ │ │ │ └── hotSearch.vue
│ │ │ └── index.vue
│ │ ├── searchResults/
│ │ │ ├── albumIndex/
│ │ │ │ └── album.vue
│ │ │ ├── artistIndex/
│ │ │ │ └── artist.vue
│ │ │ ├── composite/
│ │ │ │ ├── components/
│ │ │ │ │ ├── album.vue
│ │ │ │ │ ├── artist.vue
│ │ │ │ │ ├── djRadio.vue
│ │ │ │ │ ├── playList.vue
│ │ │ │ │ ├── simQuery.vue
│ │ │ │ │ ├── song.vue
│ │ │ │ │ ├── user.vue
│ │ │ │ │ └── video.vue
│ │ │ │ └── composite.vue
│ │ │ ├── djRadioIndex/
│ │ │ │ └── djRadio.vue
│ │ │ ├── index.vue
│ │ │ ├── navIndex/
│ │ │ │ └── index.vue
│ │ │ ├── playListIndex/
│ │ │ │ └── playList.vue
│ │ │ ├── singerIndex/
│ │ │ │ ├── select.vue
│ │ │ │ └── singer.vue
│ │ │ ├── songIndex/
│ │ │ │ └── song.vue
│ │ │ ├── userIndex/
│ │ │ │ └── user.vue
│ │ │ └── videoIndex/
│ │ │ └── video.vue
│ │ ├── userInfoIndex/
│ │ │ ├── components/
│ │ │ │ ├── userDynamic.vue
│ │ │ │ └── userHome.vue
│ │ │ └── index.vue
│ │ └── videoIndex/
│ │ ├── components/
│ │ │ ├── acg.vue
│ │ │ ├── animation.vue
│ │ │ ├── dance.vue
│ │ │ ├── game.vue
│ │ │ ├── listenBGM.vue
│ │ │ ├── musicFestival.vue
│ │ │ ├── rock.vue
│ │ │ ├── scene.vue
│ │ │ └── singing.vue
│ │ ├── index.vue
│ │ ├── public.vue
│ │ └── videoComments/
│ │ ├── components/
│ │ │ ├── video.vue
│ │ │ ├── videoCreator.vue
│ │ │ └── videoInfo.vue
│ │ └── index.vue
│ ├── router/
│ │ └── index.js
│ └── store/
│ ├── actions.js
│ ├── getters.js
│ ├── index.js
│ ├── mutation-types.js
│ ├── mutations.js
│ └── state.js
└── static/
└── .gitkeep
================================================
FILE CONTENTS
================================================
================================================
FILE: .vscode/settings.json
================================================
{
"cSpell.words": [
"RCVD",
"autofocus",
"blogaaa",
"flexbox",
"vmax",
"zhidao"
]
}
================================================
FILE: README.md
================================================
Welcome to Music-player 👋
## :speech_balloon:前言
随着不断的学习 Vue,需要做一个小项目通过在实现项目过程中了解到更多的知识。随着如今人们对于音乐的需求,移动端的使用量愈发增加,项目通过 Vue 编写实现,全面借用**网易云音乐移动端**的 UI 设计、功能实现,努力做到以假乱真的效果。前几天便着手开始弄了,到今天为止也算是勉强能用了。
> 本项目自行构思得出,由个人独立编写程序研究。
**注:此项目纯属个人瞎搞,正常使用请选择[网易云音乐官方](https://music.163.com)客户端。**
## :muscle: 项目目标
全面实现移动端网易云音乐的功能
> **项目还在编写完善中**
## 🚀 如何运行
> node 版本 `[10.15.3]`
### ✨ 开发过程
```
# 克隆
git clone https://github.com/powerdong/Music-player.git
```
```
# 打开项目目录
cd Music-player
cd musicPlayer
```
```
# 安装依赖
npm install
```
```
# 开启本地服务运行项目
npm run dev
```
**欢迎 star,欢迎 issue**
### :eyes: 项目进度
**上一次更新(2020-03-15):** ~~登录功能bug修复~~
**最近一次更新(2020-05-04):** 歌单详情bug修复
> 感谢大家的关注,最近在实习期间未能及时更新,最近发现网易的api返回有变化,回来改了一个问题
### :memo: 版本更新
- **版本信息:** 2.4.8-> 2.8.10
- **时间:** 2019 年 12 月 7 日
- **更新内容:**
- 增加发现页面下拉刷新+轻提示
- 增加电台排行页面主播榜
- 增加电台排行页面节目榜中 24 小时榜
- 增加电台排行页面电台榜中付费精品榜
- 修复登录页面不能返回 Bug
- 修复其他已知问题
- 优化结构
使用中有任何问题或建议,欢迎 Issue!
本项目在不断完善中,请大家拭目以待~
## 技术栈
### :point_right: 主要依赖
- Vue 全家桶(使用 Vue-cli 作为构建工具)
- WebPack4.0
- ES6
- Less
- ESLint
- Vant UI
- [网易云音乐 API](https://binaryify.github.io/NeteaseCloudMusicApi/#/)
### :clap: 项目演示
[demo 地址](http://140.143.128.100:3000)(请用 chrome/firefox 手机模式预览) -- 暂时停止
## :mega: 目标功能
- [x] 手机登录、注册
- [x] 修改密码
- [x] 我的页面歌单信息
- [x] 添加,删除歌单
- [x] 最近播放
- [x] 心动模式
- [x] 我的电台
- [x] 我的收藏
- [x] 发现页面推荐歌单
- [x] 发现页面新碟
- [x] 发现页面新歌
- [x] 发现页面每日推荐
- [x] 发现页面歌单
- [x] 视频页面
- [ ] 朋友页面
- [x] 歌单广场
- [x] 新歌推荐
- [x] 更多新碟
- [x] 发现页面排行榜
- [x] 发现页面电台
- [x] 退出账号
- [x] 发现页面私人 FM
- [x] 搜索功能
- [x] 搜索结果展示
- [x] 热搜榜
- [x] 历史记录
- [x] 搜索推荐
- [x] 歌手分类
- [x] 播放功能(**小播放器进度条**)
- [x] 播放列表
- [x] 添加删除播放列表
- [x] 签到
- [x] 歌曲喜欢与否
- [x] 专辑收藏与否
- [x] 歌单评论
- [x] 专辑评论
- [x] 点赞、发送、删除评论
- [x] 电台节目评论
- [x] 视频评论
- [x] 用户相关
- [ ] 页面滚动加载
- [ ] 左右滑动切换
- [ ] 页面切换动画
- [ ] 登陆情况判断
- [ ] 全面优化&修复
## :computer: 部分截图
侧边账户中心

发现页面&每日推荐

歌单&歌单详情

排行榜&排行榜信息

我的页面&最近播放

我的歌单&播放歌曲

搜索展示

## :page_with_curl: 项目布局
```js
.src
+-- api
| +-- config.js // 存取相关的api地址
| +-- index.js // 请求相关的api方法
+-- assets
| +-- styles
| +-- border.css // 移动端的1px边框
| +-- global.less // 全局应用样式
| +-- reset.css // 重置样式
| +-- resetEleUI.less // 修改elementUI组件样式
| +-- utils // 全局要使用的方法
| +-- getPhone // 获取手机号码
| +-- modalScroll // 处理移动端滚动条
| +-- Bus.js // Bus 总线
| +-- Mixins.js // 混入(mixin)
+-- base // 存取页面公共的小组件
+-- albumPage // 歌单展示页面组件
+-- songListPage // 展示歌曲列表
+-- alert // 提示消息
+-- audioAllTitle // 播放全部标题行
+-- button // 登陆页面按钮
+-- djSublistCard // 类似于我的电台页面的长卡片组件
+-- generalNav // 通用页面顶部的标题行
+-- icon // 图标展示
+-- idxCard // 官方排行榜
+-- imgCard // 歌单的图片卡
+-- interchangeable // 用来展示搜索展示页面除单曲以外的项目
+-- loading // 转圈loading
+-- pageErrorInfo // 出错提醒
+-- pageErrorLoading // 页面加载loading
+-- searchInput // 搜索框
+-- slider // 播放列表滑块
+-- sliderNav // 滑动标题
+-- song // 歌曲项
+-- titleFooter // 搜索展示页综合页面各项通用头和尾
+-- getInfos // 获取一些静态信息
+-- getData // 获取静态信息方法
+-- icon // 存取图标信息
+-- pages // 项目路由页面
+-- router // 路由配置
+-- index
+-- store // vuex 配置使用
+-- action // 根级别的 action
+-- getter // 根级别的 getter
+-- index // 组装模块并导出 store 的地方
+-- mutation-types // 根级别的 mutation-types
+-- mutation // 根级别的 mutation
+-- state // 根级别的 state
```
## 打包日志


> 本项目会长期更新,欢迎大家指出问题,共同学习
## 作者
👤 **Lambda**
================================================
FILE: musicPlayer/.babelrc
================================================
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": [
["import", {
"libraryName": "vant",
"libraryDirectory": "es",
"style": true
}],
"transform-vue-jsx", "transform-runtime", [
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
================================================
FILE: musicPlayer/.editorconfig
================================================
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
================================================
FILE: musicPlayer/.eslintignore
================================================
/build/
/config/
/dist/
/*.js
================================================
FILE: musicPlayer/.eslintrc.js
================================================
// https://eslint.org/docs/user-guide/configuring
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint'
},
env: {
browser: true,
},
extends: [
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
'plugin:vue/essential',
// https://github.com/standard/standard/blob/master/docs/RULES-en.md
'standard'
],
// required to lint *.vue files
plugins: [
'vue'
],
// add your custom rules here
rules: {
// allow async-await
'generator-star-spacing': 'off',
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
// "quotes": [1, "double"]
}
}
================================================
FILE: musicPlayer/.gitignore
================================================
.DS_Store
node_modules/
/dist/
save/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
================================================
FILE: musicPlayer/.postcssrc.js
================================================
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
"plugins": {
"postcss-import": {},
"postcss-url": {},
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {}
}
}
================================================
FILE: musicPlayer/README.md
================================================
# music-player
> 高仿网易云音乐
## Build Setup
``` bash
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
# build for production and view the bundle analyzer report
npm run build --report
```
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
================================================
FILE: musicPlayer/build/build.js
================================================
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'production'
const ora = require('ora')
const rm = require('rimraf')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const config = require('../config')
const webpackConfig = require('./webpack.prod.conf')
const spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, (err, stats) => {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})
================================================
FILE: musicPlayer/build/check-versions.js
================================================
'use strict'
const chalk = require('chalk')
const semver = require('semver')
const packageConfig = require('../package.json')
const shell = require('shelljs')
function exec (cmd) {
return require('child_process').execSync(cmd).toString().trim()
}
const versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version),
versionRequirement: packageConfig.engines.node
}
]
if (shell.which('npm')) {
versionRequirements.push({
name: 'npm',
currentVersion: exec('npm --version'),
versionRequirement: packageConfig.engines.npm
})
}
module.exports = function () {
const warnings = []
for (let i = 0; i < versionRequirements.length; i++) {
const mod = versionRequirements[i]
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
warnings.push(mod.name + ': ' +
chalk.red(mod.currentVersion) + ' should be ' +
chalk.green(mod.versionRequirement)
)
}
}
if (warnings.length) {
console.log('')
console.log(chalk.yellow('To use this template, you must update following to modules:'))
console.log()
for (let i = 0; i < warnings.length; i++) {
const warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}
================================================
FILE: musicPlayer/build/utils.js
================================================
'use strict'
const path = require('path')
const config = require('../config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const packageConfig = require('../package.json')
exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
const cssLoader = {
loader: 'css-loader',
options: {
sourceMap: options.sourceMap
}
}
const postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
const output = []
const loaders = exports.cssLoaders(options)
for (const extension in loaders) {
const loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
exports.createNotifierCallback = () => {
const notifier = require('node-notifier')
return (severity, errors) => {
if (severity !== 'error') return
const error = errors[0]
const filename = error.file && error.file.split('!').pop()
notifier.notify({
title: packageConfig.name,
message: severity + ': ' + error.name,
subtitle: filename || '',
icon: path.join(__dirname, 'logo.png')
})
}
}
================================================
FILE: musicPlayer/build/vue-loader.conf.js
================================================
'use strict'
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
const sourceMapEnabled = isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap
module.exports = {
loaders: utils.cssLoaders({
sourceMap: sourceMapEnabled,
extract: isProduction
}),
cssSourceMap: sourceMapEnabled,
cacheBusting: config.dev.cacheBusting,
transformToRequire: {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
}
}
================================================
FILE: musicPlayer/build/webpack.base.conf.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-07-30 16:42:30
* @Update: 2019-11-18 19:13:26
* @Update log: 更新日志
*/
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath : config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
'styles': resolve('src/assets/styles'),
'mixins': resolve('src/assets'),
'getInfos': resolve('src/getInfos'),
'base': resolve('src/base'),
'api': resolve('src/api'),
'utils': resolve('src/assets/utils')
}
},
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
================================================
FILE: musicPlayer/build/webpack.dev.conf.js
================================================
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool,
// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay
? { warnings: false, errors: true }
: false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll,
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.dev.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
module.exports = new Promise((resolve, reject) => {
portfinder.basePort = process.env.PORT || config.dev.port
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// publish the new Port, necessary for e2e tests
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port
// Add FriendlyErrorsPlugin
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
},
onErrors: config.dev.notifyOnErrors
? utils.createNotifierCallback()
: undefined
}))
resolve(devWebpackConfig)
}
})
})
================================================
FILE: musicPlayer/build/webpack.prod.conf.js
================================================
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const env = require('../config/prod.env')
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
================================================
FILE: musicPlayer/config/dev.env.js
================================================
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})
================================================
FILE: musicPlayer/config/index.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-07-16 19:49:41
* @Update: 2019-08-18 19:16:52
* @Update log: 更新日志
*/
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {// 输入/api 让其去访问http://localhost:3000/api
'/api': {
target: 'http://140.143.128.100:3000', // 设置调用的接口域名和端口号 ( 设置代理目标)
changeOrigin: true,
pathRewrite: {
'^/api': '' // 这是一个通配符,设置完了之后每个接口都要在前面加上/api(特别注意这一点)
}
}
},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
// Use Eslint Loader?
// If true, your code will be linted during bundling and
// linting errors and warnings will be shown in the console.
useEslint: true,
// If true, eslint errors and warnings will also be shown in the error overlay
// in the browser.
showEslintErrorsInOverlay: false,
/**
* Source Maps
*/
// https://webpack.js.org/configuration/devtool/#development
devtool: 'cheap-module-eval-source-map',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
cssSourceMap: true
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
}
}
================================================
FILE: musicPlayer/config/prod.env.js
================================================
'use strict'
module.exports = {
NODE_ENV: '"production"'
}
================================================
FILE: musicPlayer/index.html
================================================
music-player
================================================
FILE: musicPlayer/package.json
================================================
{
"name": "music-player",
"version": "1.0.0",
"description": "高仿网易云音乐",
"author": "powerdong ",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --host 0.0.0.0 --config build/webpack.dev.conf.js",
"start": "npm run dev",
"lint": "eslint --ext .js,.vue src",
"build": "node build/build.js"
},
"dependencies": {
"axios": "^0.19.0",
"core-js": "3",
"fastclick": "^1.0.6",
"less": "^3.9.0",
"less-loader": "^5.0.0",
"qs": "^6.8.0",
"vant": "^2.2.10",
"vue": "^2.5.2",
"vue-lazyload": "^1.3.2",
"vue-router": "^3.0.1",
"vuex": "^3.1.1"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-eslint": "^8.2.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.1",
"babel-plugin-component": "^1.1.1",
"babel-plugin-import": "^1.12.2",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"eslint": "^4.15.0",
"eslint-config-standard": "^10.2.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.2.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-vue": "^4.0.0",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"node-notifier": "^5.1.2",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"url-loader": "^0.5.8",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
}
}
================================================
FILE: musicPlayer/src/App.vue
================================================
================================================
FILE: musicPlayer/src/api/config.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-08-19 13:42:17
* @Update: 2019-12-03 13:37:22
* @Update log: 更新日志
*/
const api = process.env.NODE_ENV === 'development' ? '/api' : ''
// ===================发现页面
export const bannerSwiper = api + '/banner?type=1' // 请求发现页面轮播图
export const recSongList = api + '/top/playlist' // 推荐歌单,歌单广场
export const highquality = api + '/top/playlist/highquality' // 精品歌单
export const catlist = api + '/playlist/catlist' // 获取歌单分类 !!!
export const hot = api + '/playlist/hot' // 获取热门歌单分类 !!!
export const topList = api + '/toplist/detail' // 获取所有榜单内容摘要
export const idxList = api + '/top/list' // 获取排行榜
export const albumDetail = api + '/playlist/detail' // 获取歌单详情
export const recSongs = api + '/recommend/songs' // 每日推荐歌曲
export const dateRecSongList = api + '/recommend/resource' // 每日推荐歌单,发现页展示的那六个
export const newDish = api + '/top/album' // 发现页新碟
export const getDishInfo = api + '/album' // 获取专辑内容
export const newSongs = api + '/top/song' // 发现页新歌
export const personalFm = api + '/personal_fm' // 发现页私人FM
// ======================播放歌曲
export const songUrl = api + '/song/url' // 获取歌曲url
export const checkSong = api + '/check/music' // 查看歌曲是否可用
export const songLyric = api + '/lyric' // 获取歌词
export const heartMode = api + '/playmode/intelligence/list' // 心动模式播放
export const likeMusicList = api + '/likelist' // 喜欢歌曲列表
export const likeMusic = api + '/like' // 喜欢歌曲
// ===================登陆
export const phoneLogin = api + '/login/cellphone' // 手机号登陆
export const phoneRegistered = api + '/cellphone/existence/check' // 手机号是否被注册
export const sendVerify = api + '/captcha/sent' // 发送验证码
export const verify = api + '/captcha/verify' // 验证验证码
export const loginStatus = api + '/login/status' // 登录状态
export const logout = api + '/logout' // 退出登录
export const signIn = api + '/daily_signin' // 签到
export const register = api + '/register/cellphone' // 注册修改密码
// ===================我的页面相关
export const userRecord = api + '/user/record' // 用户播放记录
export const userInfo = api + '/user/subcount' // 用户信息
export const userDetail = api + '/user/detail' // 用户详情
export const userEvent = api + '/user/event' // 用户动态
export const playlist = api + '/user/playlist' // 用户歌单
export const userDj = api + '/user/dj' // 用户电台 申请做主播那一行
export const favoriteAlbums = api + '/album/sublist' // 获取收藏的专辑
export const favoriteArtists = api + '/artist/sublist' // 获取收藏的歌手
export const favoriteVideos = api + '/mv/sublist' // 获取收藏的视频
export const djSublist = api + '/dj/sublist' // 获取订阅的电台
// =================视频页面下相关
export const getVideoTag = api + '/video/group/list' // 获取视频标签导航
export const getVideoGroup = api + '/video/group' // 获取对应标签的视频详情
export const getVideoUrl = api + '/video/url' // 获取视频播放地址
export const getVideoDetail = api + '/video/detail' // 获取视频详情
export const getVideoRelated = api + '/related/allvideo' // 获取相关视频
export const getVideoComments = api + '/comment/video' // 获取视频评论
// ==================搜索页面相关
export const search = api + '/search' // 搜索关键词
export const defaultSearch = api + '/search/default' // 默认搜索关键词
export const suggestSearch = api + '/search/suggest' // 搜索建议
export const hotSearchList = api + '/search/hot/detail' // 热搜列表
export const singerClass = api + '/artist/list' // 歌手分类
// =================朋友页面
export const friend = api + '/event' // 获取朋友页面的动态
// =================歌单事件
export const addOrDeletePlaylist = api + '/playlist/subscribe' // 收藏/取消收藏歌单
export const addPlaylist = api + '/playlist/create' // 添加歌单
export const deletePlaylist = api + '/playlist/delete' // 删除歌单
// ================发现页面的电台页面
export const djBanner = api + '/dj/banner' // 电台页面的轮播图
export const radioRecommendations = api + '/dj/today/perfered' // 电台推荐数据
export const boutiqueRecommendations = api + '/dj/paygift' // 电台精品推荐
export const djClassification = api + '/dj/catelist' // 电台分类
export const djClassificationInfo = api + '/dj/recommend/type' // 电台分类推荐
export const djProgram = api + '/dj/program' // 电台节目
export const djDetail = api + '/dj/detail' // 电台详情
export const djPayGift = api + '/dj/paygift' // 电台付费精选
export const djSub = api + '/dj/sub' // 订阅/取消订阅电台
export const djToplist = api + '/dj/program/toplist' // 获取最热节目
export const djHotToplist = api + '/dj/toplist' // 获取电台榜
export const djProgramTopHours = api + '/dj/program/toplist/hours' // 获取节目榜24小时榜
export const djToplistHours = api + '/dj/toplist/hours' // 获取主播榜24小时榜
export const djToplistNewComers = api + '/dj/toplist/newcomer' // 获取主播榜新人榜
export const djToplistPopulars = api + '/dj/toplist/popular' // 获取主播榜最热主播
export const djToplistPays = api + '/dj/toplist/pay' // 获取电台磅付费精品榜
// ================评论页面相关
export const commentPlaylist = api + '/comment/playlist' // 获取歌单的评论
export const commentAlbum = api + '/comment/album' // 获取专辑的评论
export const commentDj = api + '/comment/dj' // 获取电台节目评论
export const commentLike = api + '/comment/like' // 给评论点赞
export const pushOrDeleteCom = api + '/comment' // 发送删除评论
export const resourceLike = api + '/resource/like' // 资源点赞
================================================
FILE: musicPlayer/src/api/index.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-08-19 13:47:19
* @Update: 2019-12-08 12:02:19
* @Update log: 更新日志
*/
import axios from 'axios'
import {
bannerSwiper,
recSongList,
highquality,
recSongs,
topList,
dateRecSongList,
newDish,
phoneLogin,
albumDetail,
sendVerify,
verify,
phoneRegistered,
loginStatus,
userRecord,
userInfo,
playlist,
userDj,
hotSearchList,
search,
defaultSearch,
suggestSearch,
songUrl,
checkSong,
songLyric,
idxList,
addOrDeletePlaylist,
addPlaylist,
deletePlaylist,
heartMode,
favoriteAlbums,
favoriteArtists,
favoriteVideos,
djSublist,
newSongs,
getDishInfo,
personalFm,
singerClass,
logout,
radioRecommendations,
boutiqueRecommendations,
djClassification,
djClassificationInfo,
djProgram,
djDetail,
djPayGift,
djSub,
djBanner,
djToplist,
djHotToplist,
likeMusicList,
likeMusic,
userDetail,
signIn,
friend,
getVideoTag,
getVideoGroup,
commentPlaylist,
commentLike,
commentAlbum,
userEvent,
pushOrDeleteCom,
getVideoUrl,
register,
commentDj,
getVideoDetail,
getVideoRelated,
getVideoComments,
resourceLike,
djProgramTopHours,
djToplistHours,
djToplistNewComers,
djToplistPopulars,
djToplistPays
} from './config'
// 请求超时时间
axios.defaults.timeout = 30000
// post请求头
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
/**
* 以后可以利用 ES6 的解构赋值进行重构
* function personInfo({ name, age, address, gender }) {
console.log(name, age, address, gender)
}
personInfo({ gender: 'man', address: 'changsha', name: 'william', age: 18 })
function saveInfo({
name = 'william',
age = 18,
address = 'changsha',
gender = 'man'
} = {}) {
console.log(name, age, address, gender)
}
saveInfo()
*/
export default {
/**
* 请求发现页面首页轮播图
*/
bannerSwiperFn () {
return axios.get(bannerSwiper)
},
/**
* 调用此接口 , 可获得每日推荐歌曲 ( 需要登录 )
*/
recSongsFn () {
return axios.get(recSongs)
},
/**
* 调用此接口 , 传入歌单 id, 可 以获取对应歌单内的所有的音乐
* @param {*} id 歌单 id
* @param {*} s 歌单最近的 s 个收藏者,默认5个
*/
albumDetailFn (id, s = 5) {
return axios.get(albumDetail, {
params: {
id,
s
}
})
},
/**
* 调用此接口,可获取所有榜单内容摘要
*/
topListFn () {
return axios.get(topList)
},
/**
* 请求 可获取推荐歌单
* ?limit=10&order=hot
* @param {*} limit 取出数量,默认是30
* @param {*} order 分别对应最新和最热,可选值为 'new' 和 'hot'
* @param {*} cat tag, 比如 " 华语 "、" 古风 " 、" 欧美 "、" 流行 ", 默认为 "全部",
* :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认 为 0
*/
recSongListFn (limit = 30, order = 'hot', cat) {
return axios.get(recSongList, {
params: {
limit,
order,
cat
}
})
},
/**
* 获取精品歌单
* @param {*} limit 取出歌单数量 , 默认为 30
* @param {*} before 分页参数,取上一页最后一个歌单的 updateTime 获取下一页数据
* @param {*} cat cat: tag
*/
highqualityFn (limit = 30, before, cat) {
return axios.get(highquality, {
params: {
limit,
before,
cat
}
})
},
/**
* 调用此接口 , 传入数字 idx, 可获取不同排行榜
* @param {*} idx 排行榜 idx
*/
idxListFn (idx) {
return axios.get(idxList, {
params: {
idx
}
})
},
/**
* 可获得每日推荐歌单 ( 需要登录 )
*/
dateRecSongListFn () {
return axios.get(dateRecSongList)
},
/**
* 调用此接口 , 可获取新碟上架列表
* @param {*} limit 取出数量 , 默认为 50
* @param {*} offset 偏移数量 , 用于分页
* 如 :( 页数 -1)*50, 其中 50 为 limit 的值 , 默认 为 0
*/
newDishFn (limit = 10, offset) {
return axios.get(newDish, {
params: {
limit,
offset
}
})
},
/**
* 调用此接口 , 传入专辑 id, 可获得专辑内容
* @param {*} id 专辑id
*/
getDishInfoFn (id) {
return axios.get(getDishInfo, {
params: {
id
}
})
},
/**
* 检测手机号码是否已注册
* @param {*} phone 手机号
*/
phoneRegisteredFn (phone) {
return axios.get(phoneRegistered, {
params: {
phone
}
})
},
/**
* 调用此接口 ,传入手机号码, 可发送验证码
* @param {number} phone 手机号
*/
sendVerifyFn (phone) {
return axios.get(sendVerify, {
params: {
phone
}
})
},
/**
* 验证验证码
* 调用此接口 ,传入手机号码和验证码, 可校验验证码是否正确
* @param {*} phone 手机号
* @param {*} captcha 验证码
*/
verifyFn (phone, captcha) {
return axios.get(verify, {
params: {
phone,
captcha
}
})
},
/**
* 用户通过手机登录
* @param {number} phone 手机号
* @param {String} password 密码
*/
phoneLoginFn (phone, password) {
return axios.get(phoneLogin, {
params: {
phone: phone || '',
password: password || ''
}
})
},
/**
* 获取当前登录状态
*/
loginStatusFn () {
return axios.get(loginStatus)
},
/**
* 获取用户播放记录
* 登陆后调用此接口 , 传入用户 id, 可获取用户播放记录
* @param {*} uid 用户id
* @param {*} type type=1 时只返回 weekData, type=0 时返回 allData
*/
userRecordFn (uid, type = 1) {
return axios.get(userRecord, {
params: {
uid,
type
}
})
},
/**
* 获取用户信息 , 歌单,收藏,mv, dj 数量
* 登陆后调用此接口 , 可以获取用户信息
* artistCount: 2 我的收藏中的歌手
* code: 200
* createDjRadioCount: 0
* createdPlaylistCount: 2 创建的歌单数
* djRadioCount: 1 我的电台
* mvCount: 0
* newProgramCount: 0
* programCount: 0
* subPlaylistCount: 3 收藏的歌单数
* @param {*} timestamp 时间戳,使得每次请求的URL不同,除掉了默认的2分钟缓存
*/
userInfoFn (timestamp) {
return axios.get(userInfo, {
params: {
timestamp
}
})
},
/**
* 登陆后调用此接口 , 传入用户 id, 可以获取用户详情
* @param {*} uid 用户id
*/
userDetailFn (uid) {
return axios.get(userDetail, {
params: {
uid
}
})
},
/**
* 登陆后调用此接口 , 传入用户 id, 可以获取用户动态
* @param {*} uid 用户 id
* @param {*} limit 返回数量 , 默认为 30
* @param {*} lasttime 返回数据的 lasttime ,默认-1,传入上一次返回结果的 lasttime,将会返回下一页的数据
*/
userEventFn (uid, limit = 20, lasttime) {
return axios.get(userEvent, {
params: {
uid,
limit,
lasttime
}
})
},
/**
* 调用此接口 , 传入签到类型
* @param {*} type 签到类型 , 默认 0, 其中 0 为安卓端签到 ,1 为 web/PC 签到
* 其中安卓端签到可获得 3 点经验 , web/PC 端签到可获得 2 点经验
*/
signInFn (type) {
return axios.get(signIn, {
params: {
type
}
})
},
/**
* 调用此接口 ,传入手机号码和验证码,密码,昵称, 可注册网易云音乐账号(同时可修改密码)
* @param {*} captcha 验证码
* @param {*} phone 手机号码
* @param {*} password 密码
* @param {*} nickname 昵称
*/
registerFn (captcha, phone, password, nickname) {
return axios.get(register, {
params: {
captcha,
phone,
password,
nickname
}
})
},
/**
* 登陆后调用此接口 , 传入用户 id, 可以获取用户歌单
* @param {*} uid 用户id
* @param {*} timestamp 时间戳,使得每次请求的URL不同,除掉了默认的2分钟缓存
*/
playlistFn (uid, timestamp) {
return axios.get(playlist, {
params: {
uid,
timestamp
}
})
},
/**
* 登陆后调用此接口 , 传入用户 id, 可以获取用户电台
* @param {*} uid 用户 id
*/
userDjFn (uid) {
return axios.get(userDj, {
params: {
uid
}
})
},
/**
* 调用此接口,可获取热门搜索列表
*/
hotSearchListFn () {
return axios.get(hotSearchList)
},
/**
* 调用此接口 , 传入搜索关键词可以搜索
* 该音乐 / 专辑 / 歌手 / 歌单 / 用户 , 关键词可以多个 , 以空格隔开
* @param {*} keywords 关键词
* @param {*} limit 返回数量 , 默认为 30
* @param {*} offset 偏移数量,用于分页 默认为 0
* @param {*} type 搜索类型 默认为 1 即单曲 这里设置默认返回综合
* 1: 单曲, 10: 专辑, 100: 歌手, 1000: 歌单
* 1002: 用户, 1004: MV, 1006: 歌词, 1009: 电台, 1014: 视频, 1018:综合
*/
searchFn (keywords, limit = 30, offset = 0, type = 1018) {
return axios.get(search, {
params: {
keywords,
limit,
offset,
type
}
})
},
/**
* 调用此接口 , 可获取默认搜索关键词
*/
defaultSearchFn () {
return axios.get(defaultSearch)
},
/**
* 调用此接口
* 传入搜索关键词可获得搜索建议 ,
* 搜索结果同时包含单曲 , 歌手 , 歌单 ,mv 信息
* @param {*} keywords 关键词
* @param {*} type 默认返回移动端数据
*/
suggestSearchFn (keywords, type = 'mobile') {
return axios.get(suggestSearch, {
params: {
keywords,
type
}
})
},
/**
* 使用歌单详情接口后 , 能得到的音乐的 id, 但不能得到的音乐 url
* 调用此接口 , 传入的音乐 id( 可多个 , 用逗号隔开 )
* 可以获取对应的音乐的 url( 不需要登录 )
* @param {*} id 音乐 id
* @param {*} br 码率,默认设置了 999000 即最大码率,如果要 320k 则可设置为 320000,其他类推
*/
songUrlFn (id, br) {
return axios.get(songUrl, {
params: {
id,
br
}
})
},
/**
* 传入歌曲 id, 可获取音乐是否可用
* @param {*} id 歌曲 id
* @param {*} br 码率,默认设置了 999000 即最大码率,如果要 320k 则可设置为 320000,其他类推
*/
checkSongFn (id, br) {
return axios.get(checkSong, {
params: {
id,
br
}
})
},
/**
* 传入音乐 id 可获得对应音乐的歌词 ( 不需要登录 )
* @param {*} id 歌曲id
*/
songLyricFn (id) {
return axios.get(songLyric, {
params: {
id
}
})
},
/**
* 传入类型和歌单 id 可收藏歌单或者取消收藏歌单
* @param {*} t 1:收藏 2:取消收藏
* @param {*} id 歌单id
*/
addOrDeletePlaylistFn (t, id) {
return axios.get(addOrDeletePlaylist, {
params: {
t,
id
}
})
},
/**
* 调用此接口 , 传入歌单名字可新建歌单
* @param {*} name 歌单名
* @param {*} privacy 是否为隐私歌单 传'10'设置为隐私歌单
*/
addPlaylistFn (name, privacy) {
return axios.get(addPlaylist, {
params: {
name,
privacy
}
})
},
/**
* 调用此接口 , 传入歌单名字可新建歌单
* @param {*} id 歌单id
*/
deletePlaylistFn (id) {
return axios.get(deletePlaylist, {
params: {
id
}
})
},
/**
* 登录后调用此接口 , 可获取心动模式/智能播放列表
* @param {*} id 歌曲 id
* @param {*} pid 歌单id
* @param {*} sid 要开始播放的歌曲id
*/
heartModeFn (id, pid, sid) {
return axios.get(heartMode, {
params: {
id,
pid,
sid
}
})
},
/**
* 调用此接口 , 传入音乐 id, 可喜欢该音乐
* @param {*} id 音乐id
* @param {*} like 布尔值 , 默认为 true 即喜欢 , 若传 false, 则取消喜欢
*/
likeMusicFn (id, like) {
return axios.get(likeMusic, {
params: {
id,
like
}
})
},
/**
* 调用此接口 , 传入用户 id, 可获取已喜欢音乐id列表(id数组)
* @param {*} uid 用户id
*/
likeMusicListFn (uid) {
const timestamp = +new Date()
return axios.get(likeMusicList, {
params: {
uid,
timestamp
}
})
},
/**
* 调用此接口 , 可获得已收藏专辑列表
* @param {*} limit 取出数量 , 默认为 25
* @param {*} offset 偏移数量 , 用于分页 , 如 :( 页数 -1)*25, 其中 25 为 limit 的值 , 默认 为 0
*/
favoriteAlbumsFn (limit, offset) {
return axios.get(favoriteAlbums, {
params: {
limit,
offset
}
})
},
/**
* 调用此接口,可获取收藏的歌手列表
*/
favoriteArtistsFn () {
return axios.get(favoriteArtists)
},
/**
* 调用此接口,可收藏视频
*/
favoriteVideosFn () {
return axios.get(favoriteVideos)
},
/**
* 获取视频详情
* @param {*} id 视频id
*/
getVideoDetailFn (id) {
return axios.get(getVideoDetail, {
params: {
id
}
})
},
/**
* 获取相关视频
* @param {*} id 视频id
*/
getVideoRelatedFn (id) {
return axios.get(getVideoRelated, {
params: {
id
}
})
},
/**
* 调用此接口 , 传入音乐 id 和 limit 参数 , 可获得该 视频 的所有评论 ( 不需要登录 )
* @param {*} id 视频的 id
* @param {*} limit 取出评论数量 , 默认为 20
* @param {*} offset 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*20, 其中 20 为 limit 的值
* @param {*} before 分页参数,取上一页最后一项的 time 获取下一页数据(获取超过5000条评论的时候需要用到)
*/
getVideoCommentsFn (id, limit = 20, offset, before) {
const timestamp = +new Date()
return axios.get(getVideoComments, {
params: {
id,
limit,
offset,
before,
timestamp
}
})
},
/**
* 登陆后调用此接口 , 可获取订阅的电台列表
*/
djSublistFn (timestamp) {
return axios.get(djSublist, {
params: {
timestamp
}
})
},
/**
* 调用此接口 , 可获取新歌速递
* @param {*} type 地区类型 id,对应以下:
* 全部:0 华语:7 欧美:96 日本:8 韩国:16
*/
newSongsFn (type = 0) {
return axios.get(newSongs, {
params: {
type
}
})
},
/**
* 获取私人 FM
* 需要登录
*/
personalFmFn () {
return axios.get(personalFm)
},
/**
* 调用此接口,可获取歌手分类列表
* @param {*} cat 歌手类型, 必选
* 入驻歌手 5001
* 华语男歌手 1001 华语女歌手 1002 华语组合/乐队 1003
* 欧美男歌手 2001 欧美女歌手 2002 欧美组合/乐队 2003
* 日本男歌手 6001 日本女歌手 6002 日本组合/乐队 6003
* 韩国男歌手 7001 韩国女歌手 7002 韩国组合/乐队 7003
* 其他男歌手 4001 其他女歌手 4002 其他组合/乐队 4003
* @param {*} limit 返回数量 , 默认为 30
* @param {*} offset 偏移数量,用于分页,默认为 0
* @param {*} initial 按首字母索引查找参数
* /artist/list?cat=1001&initial=b
* 返回内容将以 name 字段开头为 b 或者拼音开头为 b 为顺序排列
*/
singerClassFn (cat = 1001, limit = 30, offset = 0, initial) {
return axios.get(singerClass, {
params: {
cat,
limit,
offset,
initial
}
})
},
/**
* 退出账号
*/
logoutFn () {
return axios.get(logout)
},
/**
* 调用此接口,可获取电台banner
*/
djBannerFn () {
return axios.get(djBanner)
},
/**
* 获取电台页面的电台推荐数据
*/
radioRecomFn () {
return axios.get(radioRecommendations)
},
/**
* 可以获取付费精选的电台列表
* @param {*} limit 返回数量 , 默认为 30
* @param {*} offset 偏移数量, 默认为 0
*/
boutiqueRecomFn (limit = 3, offset = 0) {
return axios.get(boutiqueRecommendations, {
params: {
limit,
offset
}
})
},
/**
* 登陆后调用此接口 , 可获得电台类型
*/
djClassificationFn () {
return axios.get(djClassification)
},
/**
* 登陆后调用此接口 , 可获得推荐电台
* @param {*} type 电台类型
* 可通过/dj/catelist获取 , 对应关系为 id 对应 此接口的 type, name 对应类型意义
*/
djClassificationInfoFn (type) {
return axios.get(djClassificationInfo, {
params: {
type
}
})
},
/**
* 登陆后调用此接口 , 传入rid, 可查看对应电台的电台节目以及对应的 id
* 需要 注意的是这个接口返回的 mp3Url 已经无效 , 都为 null
* 但是通过调用 /song/url 这 个接口 , 传入节目 id 仍然能获取到节目音频 ,
* 如 /song/url?id=478446370 获取代 码时间的一个节目的音频
* @param {*} rid 电台 的 id
* @param {*} limit 返回数量 , 默认为 30
* @param {*} offset 偏移数量,用于分页
* @param {*} asc 排序方式,默认为 false (新 => 老 ) 设置 true 可改为 老 => 新
*/
djProgramFn (rid, limit = 30, offset = 0, asc) {
return axios.get(djProgram, {
params: {
rid,
limit,
offset,
asc
}
})
},
/**
* 登陆后调用此接口 , 传入rid, 可获得对应电台的详情介绍
* @param {*} rid 电台 的 id
*/
djDetailFn (rid) {
return axios.get(djDetail, {
params: {
rid
}
})
},
/**
* 可以获取付费精选的电台列表 , 传入 limit 和 offset 可以进行分页
* @param {*} limit 返回数量 , 默认为 30
* @param {*} offset 偏移数量,用于分页
*/
djPayGiftFn (limit = 30, offset = 0) {
return axios.get(djPayGift, {
params: {
limit,
offset
}
})
},
/**
* 登陆后调用此接口 , 传入rid, 可订阅 dj
* @param {*} rid 电台 的 id
* @param {*} t t=1 对应关注 t=0 对应取消关注
*/
djSubFn (rid, t) {
return axios.get(djSub, {
params: {
rid,
t
}
})
},
/**
* 登陆后调用此接口 , 可获得电台节目榜
* @param {*} limit 返回数量 , 默认为 100
* @param {*} offset 偏移数量,用于分页
*/
djToplistFn (limit = 100, offset = 0) {
return axios.get(djToplist, {
params: {
limit,
offset
}
})
},
/**
* 登陆后调用此接口 , 可获得新晋电台榜/热门电台榜
* @param {*} limit 返回数量 , 默认为 100
* @param {*} offset 偏移数量,用于分页
* @param {*} type 榜单类型, new 为新晋电台榜, hot为热门电台榜
*/
djHotToplistFn (limit = 100, offset = 0, type = 'hot') {
return axios.get(djHotToplist, {
params: {
limit,
offset,
type
}
})
},
/**
* 调用此接口,可获取24小时节目榜
* @param {*} limit 返回数量 , 默认为 100 (不支持 offset)
*/
djProgramTopHoursFn (limit) {
return axios.get(djProgramTopHours, {
params: {
limit
}
})
},
/**
* 调用此接口,可获取24小时主播榜
* @param {*} limit 返回数量 , 默认为 100 (不支持 offset)
*/
djToplistHoursFn (limit) {
return axios.get(djToplistHours, {
params: {
limit
}
})
},
/**
* 说明 : 调用此接口,可获取主播新人榜
* @param {*} limit 返回数量 , 默认为 100 (不支持 offset)
*/
djToplistNewComersFn (limit) {
return axios.get(djToplistNewComers, {
params: {
limit
}
})
},
/**
* 调用此接口,可获取最热主播榜
* @param {*} limit 返回数量 , 默认为 100 (不支持 offset)
*/
djToplistPopularsFn (limit) {
return axios.get(djToplistPopulars, {
params: {
limit
}
})
},
/**
* 调用此接口,可获取付费精品电台
* @param {*} limit 返回数量 , 默认为 100 (不支持 offset)
*/
djToplistPaysFn (limit) {
return axios.get(djToplistPays, {
params: {
limit
}
})
},
/**
* 调用此接口 , 可获取各种动态
* 对应网页版网易云,朋友界面里的各种动态消息
* 如分享的视频,音乐,照片等!
* @param {*} pagesize 每页数据,默认20
* @param {*} lasttime 返回数据的 lasttime ,默认-1
* 传入上一次返回结果的 lasttime,将会返回下一页的数据
*/
friendFn (pagesize = 20, lasttime = -1) {
return axios.get(friend, {
params: {
pagesize,
lasttime
}
})
},
/**
* 调用此接口 , 可获取视频标签列表
*/
getVideoTagFn () {
return axios.get(getVideoTag)
},
/**
* 调用此接口 , 传入id,可获取到相关的视频
* @param {*} id videoGroup 的 id
*/
getVideoGroupFn (id) {
return axios.get(getVideoGroup, {
params: {
id
}
})
},
/**
* 调用此接口 , 传入视频 id,可获取视频播放地址
* @param {*} id 视频 id
*/
getVideoUrlFn (id) {
return axios.get(getVideoUrl, {
params: {
id
}
})
},
/**
* 调用此接口 , 传入音乐 id 和 limit 参数 , 可获得该歌单的所有评论 ( 不需要 登录 )
* @param {*} id 歌单id
* @param {*} limit 取出评论数量 , 默认为 20
* @param {*} offset 偏移数量 , 用于分页
* @param {*} before 分页参数,取上一页最后一项的 time
* 获取下一页数据(获取超过5000条评论的时候需要用到)
*/
commentPlaylistFn (id, limit = 20, offset, before) {
const timestamp = +new Date()
return axios.get(commentPlaylist, {
params: {
id,
limit,
offset,
before,
timestamp
}
})
},
/**
* 调用此接口 , 传入音乐 id 和 limit 参数 , 可获得该专辑的所有评论 ( 不需要 登录 )
* @param {*} id 专辑id
* @param {*} limit 取出评论数量 , 默认为 20
* @param {*} offset 偏移数量 , 用于分页
* @param {*} before 分页参数,取上一页最后一项的 time
* 获取下一页数据(获取超过5000条评论的时候需要用到)
*/
commentAlbumFn (id, limit = 20, offset, before) {
const timestamp = +new Date()
return axios.get(commentAlbum, {
params: {
id,
limit,
offset,
before,
timestamp
}
})
},
commentDjFn (id, limit = 20, offset, before) {
const timestamp = +new Date()
return axios.get(commentDj, {
params: {
id,
limit,
offset,
before,
timestamp
}
})
},
/**
* 调用此接口 , 传入 type,
* 资源 id, 和评论 id cid
* 是否点赞参数 t 即可给对 应评论点赞 ( 需要登录 )
* @param {*} id 资源 id, 如歌曲 id,mv id
* @param {*} cid 评论 id
* @param {*} t 是否点赞 ,1 为点赞 ,0 为取消点赞
* @param {*} type 数字 , 资源类型 , 对应歌曲 , mv, 专辑 , 歌单 , 电台, 视频对应以下类型
* 0: 歌曲 1: mv 2: 歌单 3: 专辑 4: 电台 5: 视频 6: 动态
*/
commentLikeFn (id, cid, t, type) {
return axios.get(commentLike, {
params: {
id,
cid,
t,
type
}
})
},
/**
* 调用此接口,可发送评论
* @param {*} t 1: 发送评论
* @param {*} type 数字,资源类型,对应歌曲,mv,专辑,歌单,电台,视频对应以下类型
* 0: 歌曲 1: mv 2: 歌单 3: 专辑 4: 电台 5: 视频 6: 动态
* @param {*} id 对应资源 id
* @param {*} content 要发送的内容
* @param {*} commentId 回复的评论id (回复评论时必填)
* @param {*} threadId 如给动态发送评论,则不需要传 id,需要传动态的 threadId
*/
pushComFn (type, id, content, commentId, threadId) {
const t = 1
const timestamp = +new Date()
return axios.post(pushOrDeleteCom, {
t,
type,
id,
content,
commentId,
threadId,
timestamp
})
},
/**
* 调用此接口,可删除评论
* @param {*} t 0: 删除评论
* @param {*} type 数字,资源类型,对应歌曲,mv,专辑,歌单,电台,视频对应以下类型
* 0: 歌曲 1: mv 2: 歌单 3: 专辑 4: 电台 5: 视频 6: 动态
* @param {*} id 对应资源 id
* @param {*} threadId 如给动态删除评论,则不需要传 id,需要传动态的 `threadId`
* @param {*} commentId 回复的评论id (回复评论时必填),删除评论时传入评论的id
*/
delComFn (type, id, commentId, threadId) {
const t = 0
return axios.post(pushOrDeleteCom, {
t,
type,
id,
threadId,
commentId
})
},
/**
* 调用此接口 , 可对 MV,电台,视频点赞
* @param {*} type 资源类型,对应以下类型 1: mv 4: 电台 5: 视频 6: 动态
* @param {*} id 资源 id
*/
resourceLikeInFn (type, id) {
const t = 1
return axios.get(resourceLike, {
params: {
t,
type,
id
}
})
},
/**
* 调用此接口 , 可对 MV,电台,视频取消点赞
* @param {*} type 资源类型,对应以下类型 1: mv 4: 电台 5: 视频 6: 动态
* @param {*} id 资源 id
*/
resourceLikeOutFn (type, id) {
const t = 0
return axios.get(resourceLike, {
params: {
t,
type,
id
}
})
}
}
================================================
FILE: musicPlayer/src/assets/Bus.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-08-29 10:48:10
* @Update: 2019-08-29 10:50:16
* @Update log: 更新日志
*/
import Vue from 'vue'
export default new Vue()
================================================
FILE: musicPlayer/src/assets/Mixins.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-09-21 15:14:40
* @Update: 2019-11-24 12:59:18
* @Update log: 更新日志
*/
import {
mapGetters
} from 'vuex'
import api from 'api'
import isInSport from 'utils/scrollStopVideo'
/**
* 这里包含对于不同模式下的icon展示
* 对于更改mode
* 对播放列表的展示隐藏
*/
export const audio = {
props: {
mode: {
type: Number
}
},
computed: {
modeClass: function () {
switch (this.mode) {
case 0: // 列表循环
return 'audioxunhuan'
case 1: // 单曲循环
return 'audiosingle-loop'
case 2: // 随机播放
return 'audiosuiji'
}
}
},
methods: {
changeMode () {
this.$emit('changeMode')
},
showAudioList () {
this.$emit('showAudioList')
}
}
}
let timer = null
export const videoPage = {
data () {
return {
data: [],
load: true,
isLogin: +localStorage.getItem('loginState') || 0
}
},
created () {
this._getVideoDetail(this.$route.params.id)
},
methods: {
_getVideoDetail (id) {
api.getVideoGroupFn(id)
.then(res => {
const {
data
} = res
if (data.code === 200) {
this.data = data.datas
this.load = false
}
})
.catch(err => {
if (err) {
this.load = false
}
})
},
hideVideo () {
const self = this
if (timer) {
clearTimeout(timer)
timer = null
}
timer = setTimeout(() => {
this.stopVideo(self)
}, 300)
},
stopVideo (self) {
// 父容器
const wra = self.$el
// video集合
const videos = [...wra.querySelectorAll('.video-item')]
// 获取到当前正在播放的video
const ele = videos[this.index]
// 查看当前播放的video是否已经出去!!!
if (!isInSport(ele, wra)) {
// 出去的话调用方法,停止视频播放
self.$refs.public.stopVideoTag()
}
},
getIndex (index) {
this.index = index
}
}
}
/**
* 当页面显示了播放组件,页面整体需要设置paddingBottom
* 大小为迷你播放器的高度
*/
export const paddingBottom = {
computed: {
...mapGetters({
miniAudio: 'FULL_SCREEN'
})
},
mounted () {
console.log(this.miniAudio)
if (!this.miniAudio) {
this.setPagePb()
}
},
watch: {
/**
* 监听当前是否播放
*/
miniAudio: function (val) {
if (!val) {
this.setPagePb()
}
}
},
methods: {
setPagePb () {
this.$refs.wrapper.style.paddingBottom = '1.3rem'
}
}
}
================================================
FILE: musicPlayer/src/assets/styles/border.css
================================================
@charset "utf-8";
.border,
.border-top,
.border-right,
.border-bottom,
.border-left,
.border-topbottom,
.border-rightleft,
.border-topleft,
.border-rightbottom,
.border-topright,
.border-bottomleft {
position: relative;
}
.border::before,
.border-top::before,
.border-right::before,
.border-bottom::before,
.border-left::before,
.border-topbottom::before,
.border-topbottom::after,
.border-rightleft::before,
.border-rightleft::after,
.border-topleft::before,
.border-topleft::after,
.border-rightbottom::before,
.border-rightbottom::after,
.border-topright::before,
.border-topright::after,
.border-bottomleft::before,
.border-bottomleft::after {
content: "\0020";
overflow: hidden;
position: absolute;
}
/* border
* 因,边框是由伪元素区域遮盖在父级
* 故,子级若有交互,需要对子级设置
* 定位 及 z轴
*/
.border::before {
box-sizing: border-box;
top: 0;
left: 0;
height: 100%;
width: 100%;
border: 1px solid #eaeaea;
transform-origin: 0 0;
}
.border-top::before,
.border-bottom::before,
.border-topbottom::before,
.border-topbottom::after,
.border-topleft::before,
.border-rightbottom::after,
.border-topright::before,
.border-bottomleft::before {
left: 0;
width: 100%;
height: 1px;
}
.border-right::before,
.border-left::before,
.border-rightleft::before,
.border-rightleft::after,
.border-topleft::after,
.border-rightbottom::before,
.border-topright::after,
.border-bottomleft::after {
top: 0;
width: 1px;
height: 100%;
}
.border-top::before,
.border-topbottom::before,
.border-topleft::before,
.border-topright::before {
border-top: 1px solid #eaeaea;
transform-origin: 0 0;
}
.border-right::before,
.border-rightbottom::before,
.border-rightleft::before,
.border-topright::after {
border-right: 1px solid #eaeaea;
transform-origin: 100% 0;
}
.border-bottom::before,
.border-topbottom::after,
.border-rightbottom::after,
.border-bottomleft::before {
border-bottom: 1px solid #eaeaea;
transform-origin: 0 100%;
}
.border-left::before,
.border-topleft::after,
.border-rightleft::after,
.border-bottomleft::after {
border-left: 1px solid #eaeaea;
transform-origin: 0 0;
}
.border-top::before,
.border-topbottom::before,
.border-topleft::before,
.border-topright::before {
top: 0;
}
.border-right::before,
.border-rightleft::after,
.border-rightbottom::before,
.border-topright::after {
right: 0;
}
.border-bottom::before,
.border-topbottom::after,
.border-rightbottom::after,
.border-bottomleft::after {
bottom: 0;
}
.border-left::before,
.border-rightleft::before,
.border-topleft::after,
.border-bottomleft::before {
left: 0;
}
@media (max--moz-device-pixel-ratio: 1.49), (-webkit-max-device-pixel-ratio: 1.49), (max-device-pixel-ratio: 1.49), (max-resolution: 143dpi), (max-resolution: 1.49dppx) {
/* 默认值,无需重置 */
}
@media (min--moz-device-pixel-ratio: 1.5) and (max--moz-device-pixel-ratio: 2.49), (-webkit-min-device-pixel-ratio: 1.5) and (-webkit-max-device-pixel-ratio: 2.49), (min-device-pixel-ratio: 1.5) and (max-device-pixel-ratio: 2.49), (min-resolution: 144dpi) and (max-resolution: 239dpi), (min-resolution: 1.5dppx) and (max-resolution: 2.49dppx) {
.border::before {
width: 200%;
height: 200%;
transform: scale(.5);
}
.border-top::before,
.border-bottom::before,
.border-topbottom::before,
.border-topbottom::after,
.border-topleft::before,
.border-rightbottom::after,
.border-topright::before,
.border-bottomleft::before {
transform: scaleY(.5);
}
.border-right::before,
.border-left::before,
.border-rightleft::before,
.border-rightleft::after,
.border-topleft::after,
.border-rightbottom::before,
.border-topright::after,
.border-bottomleft::after {
transform: scaleX(.5);
}
}
@media (min--moz-device-pixel-ratio: 2.5), (-webkit-min-device-pixel-ratio: 2.5), (min-device-pixel-ratio: 2.5), (min-resolution: 240dpi), (min-resolution: 2.5dppx) {
.border::before {
width: 300%;
height: 300%;
transform: scale(.33333);
}
.border-top::before,
.border-bottom::before,
.border-topbottom::before,
.border-topbottom::after,
.border-topleft::before,
.border-rightbottom::after,
.border-topright::before,
.border-bottomleft::before {
transform: scaleY(.33333);
}
.border-right::before,
.border-left::before,
.border-rightleft::before,
.border-rightleft::after,
.border-topleft::after,
.border-rightbottom::before,
.border-topright::after,
.border-bottomleft::after {
transform: scaleX(.33333);
}
}
================================================
FILE: musicPlayer/src/assets/styles/global.less
================================================
// 主题色
@bgcolor: #dd001b;
// 图片圆角
@imgBorderRadius: 0.11rem;
// 图标宽度
@iconWidth: 1rem;
// 图标下方文本大小
@iconText: 0.24rem;
// 定义盒子模型 两边对齐布局
.flex-between {
display: flex;
justify-content: space-between;
}
.titleFixed {
position: sticky;
width: 100vw;
top: 0;
background-color: #fff;
z-index: 99;
}
// 定义盒子模型 分散布局
.flex-around {
display: flex;
justify-content: space-around;
}
.flex-center {
display: flex;
justify-content: center;
align-items: center;
}
// 两行文本溢出打点 ...
.twoLinesEllipsis {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
overflow: hidden;
/*! autoprefixer: off */
-webkit-box-orient: vertical;
}
// 单行文字打点
.ellipsis {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
// 小标签
.smallTag {
box-sizing: border-box;
padding: 0.1rem 0.1rem 0.1rem 0.13rem;
display: flex;
align-items: center;
// justify-content: center;
font-size: 0.2rem;
border-radius: 1rem;
letter-spacing: 0.05rem;
text-align: center;
border: 1px solid #ccc;
}
.tag-group {
box-sizing: border-box;
padding: 0.1rem 0.2rem 0.1rem 0.2rem;
font-size: 0.2rem;
border-radius: 0.2rem;
background-color: #eee;
margin-right: 0.1rem;
}
// 遮罩层
.mask {
position: fixed;
z-index: 10;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.7);
}
// 灰色的数字样式
.num {
font-size: 0.24rem;
color: #999;
}
// 导航栏的访问样式
.ac {
color: #000;
font-size: 0.28rem;
}
// a标签覆盖整个区域
.cover {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 90%;
height: 100%;
}
// 页面灰色分割线样式
.split {
width: 100%;
height: 0.13rem;
background-color: #eee;
margin: 0.3rem 0;
}
// 页面有的左右padding
.pd13 {
box-sizing: border-box;
padding: 0 0.13rem;
}
// 页面有的左右padding
.pd23 {
box-sizing: border-box;
padding: 0 0.23rem;
}
.pb1 {
box-sizing: border-box;
padding-bottom: 1rem;
}
// 点击有波纹效果
.ripple {
position: relative;
overflow: hidden;
user-select: none;
&:after {
position: absolute;
content: '';
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
//设置径向渐变
background-image: radial-gradient(circle, #666 10%, transparent 10.01%);
background-repeat: no-repeat;
background-position: 50%;
transform: scale(10, 10);
opacity: 0;
transition: transform .5s, opacity .6s;
}
&:active:after {
transform: scale(0, 0);
opacity: .3;
//设置初始状态
transition: 0s;
}
}
================================================
FILE: musicPlayer/src/assets/styles/reset.css
================================================
@charset "utf-8";
html {
background-color: #fff;
color: #000
}
body,
ul,
ol,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
figure,
form,
fieldset,
legend,
input,
textarea,
button,
p,
blockquote,
th,
td,
pre,
xmp {
margin: 0;
padding: 0
}
body,
input,
textarea,
button,
select,
pre,
xmp,
tt,
code,
kbd,
samp {
line-height: 1.5;
font-family: tahoma, arial, "Hiragino Sans GB", simsun, sans-serif
}
h1,
h2,
h3,
h4,
h5,
h6,
small,
big,
input,
textarea,
button,
select {
font-size: 100%
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: tahoma, arial, "Hiragino Sans GB", "微软雅黑", simsun, sans-serif
}
h1,
h2,
h3,
h4,
h5,
h6,
b,
strong {
font-weight: normal
}
address,
cite,
dfn,
em,
i,
optgroup,
var {
font-style: normal
}
table {
border-collapse: collapse;
border-spacing: 0;
text-align: left
}
caption,
th {
text-align: inherit
}
ul,
ol,
menu {
list-style: none
}
fieldset,
img {
border: 0
}
img,
object,
input,
textarea,
button,
select {
vertical-align: middle
}
article,
aside,
footer,
header,
section,
nav,
figure,
figcaption,
hgroup,
details,
menu {
display: block
}
audio,
canvas,
video {
display: inline-block;
*display: inline;
*zoom: 1
}
blockquote:before,
blockquote:after,
q:before,
q:after {
content: "\0020"
}
textarea {
overflow: auto;
resize: vertical
}
input,
textarea,
button,
select,
a {
outline: 0 none;
border: none;
}
button::-moz-focus-inner,
input::-moz-focus-inner {
padding: 0;
border: 0
}
mark {
background-color: transparent
}
a,
ins,
s,
u,
del {
text-decoration: none
}
sup,
sub {
vertical-align: baseline
}
html {
height: 100%;
font-size: 14vw;
-webkit-tap-highlight-color: transparent;
}
body {
font-family: Arial, "Microsoft Yahei", "Helvetica Neue", Helvetica, sans-serif;
color: #333;
font-size: .28em;
line-height: 1;
-webkit-text-size-adjust: none;
}
hr {
height: .02rem;
margin: .1rem 0;
border: medium none;
border-top: .02rem solid #cacaca;
}
a {
color: #25a4bb;
text-decoration: none;
}
#audio_pb1 {
box-sizing: border-box ;
padding-bottom: 1rem;
}
================================================
FILE: musicPlayer/src/assets/utils/cookie.js
================================================
/*
* @Author: Lambda
* @Begin: 2019-10-24 11:00:35
* @Update: 2019-10-24 11:03:02
* @Update log: 更新日志
*/
export const getCookie = _name => {
let name = _name + '='
let Cookies = document.cookie.split(';')
for (let i = 0; i < Cookies.length; i++) {
let Cookie = Cookies[i]
while (Cookie.charAt(0) === '') {
Cookie = Cookie.substring(1)
}
if (Cookie.indexOf(name) !== -1) {
return Cookie.substring(name.length, Cookie.length)
}
}
return ''
}
export const setCookie = (name, value, expires, path, domain, secure) => {
let cookieText = encodeURIComponent(name) + '=' + encodeURIComponent(value)
if (expires instanceof Date) {
cookieText += '; expires=' + expires.toGMTString()
}
if (path) {
cookieText += '; path=' + path
}
if (domain) {
cookieText += '; domain=' + domain
}
if (secure) {
cookieText += '; secure'
}
document.cookie = cookieText
}
================================================
FILE: musicPlayer/src/assets/utils/filters.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-10-14 14:08:38
* @Update: 2019-12-10 13:40:19
* @Update log: 更新日志
*/
export const filterSetPlayCount = value => {
if (!value) return ''
if (value > 10000) {
value = parseInt(value / 10000) + '万'
} else if (value > 100000000) {
value = (value / 100000000).toFixed(1) + '亿'
}
return value
}
/**
* 将毫秒转换为 分钟:秒数 的形式
*/
export const filterSetTime = value => {
if (!value) return ''
let min = parseInt(value / (1000 * 60))
if (min < 10) {
min = '0' + min
}
let sec = parseInt(value % (1000 * 60) / 1000)
if (sec < 10) {
sec = '0' + sec
}
value = `${min}:${sec}`
return value
}
/**
* 将毫秒转换为 年.月.日
*/
export const filterSetYear = (value, splitY = '.', splitM = '.', splitD = '') => {
const oDate = new Date(value)
const oYear = oDate.getFullYear()
const oMonth = oDate.getMonth() + 1
const oDay = oDate.getDate()
value = `${oYear}${splitY}${oMonth}${splitM}${oDay}${splitD}`
return value
}
/**
* 将毫秒设置为 月-日 格式
*/
export const filterSetMonth = (value, splitM = '-', splitD = '') => {
const oDate = new Date(value)
let oMonth = oDate.getMonth() + 1
let oDay = oDate.getDate()
if (oMonth < 10) {
oMonth = '0' + oMonth
}
if (oDay < 10) {
oDay = '0' + oDay
}
value = `${oMonth}${splitM}${oDay}${splitD}`
return value
}
export const filterAge = time => {
if (!time) {
// 这里是因为默认值为0的话会返回1970
// 当传入默认值退出
return
}
let year = new Date(time).getFullYear()
const nowYear = new Date().getFullYear()
let age = ''
// 存下从1950年到现在时间每5年一个间隔的数值
let ages = []
for (let i = 1950; i < nowYear; i += 5) {
ages.push(i)
}
// 这里不能使用 forEach 因为forEach无法跳出循环!!!
for (let i = 0; i < ages.length; i++) {
const ele = ages[i]
if (year <= ele + 5) {
// 找到第一个满足条件的年份,拆分成数组,截取最后两位,组合返回
age = ele.toString().split('').splice(-2).join('')
break
}
}
return age
}
export const filterJson = json => {
return JSON.parse(json.toString())
}
================================================
FILE: musicPlayer/src/assets/utils/getAstro.js
================================================
/*
* @Author: Lambda
* @Begin: 2019-10-28 12:05:42
* @Update: 2019-10-28 12:06:27
* @Update log: 更新日志
*/
export const getAstro = (m, d) => {
return '魔羯水瓶双鱼牡羊金牛双子巨蟹狮子处女天秤天蝎射手魔羯'.substr(m * 2 - (d < '102223444433'.charAt(m - 1) - -19) * 2, 2)
}
================================================
FILE: musicPlayer/src/assets/utils/getPhone.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-08-26 13:35:48
* @Update: 2019-08-26 13:47:13
* @Update log: 更新日志
*/
export function getPhone () {
// 创建一个正则表达式
let reg = new RegExp(/\d*$/)
// window.location.hash 返回从 “#” 开始的 url
// 返回一个数组(未匹配到则返回 null)
let phone = reg.exec(window.location.hash)[0]
return phone
}
================================================
FILE: musicPlayer/src/assets/utils/getRandomArrayElements.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-10-11 13:17:17
* @Update: 2019-10-11 13:18:07
* @Update log: 更新日志
*/
/**
* 随机取出数组中的几项
*/
export const getRandomArrayElements = (arr, count) => {
// eslint-disable-next-line one-var
let shuffled = arr.slice(0),
// 克隆一个数组,为了不影响外边的数据
i = arr.length,
min = i - count,
temp,
index
// 存下来数组信息 数组的长度
// 通过改变数组项的位置 输出后边的几位
while (--i > min) {
// 随机生成出一个索引
index = Math.floor((i + 1) * Math.random())
// 将随机索引项暂存
// 将数组后边的项与随机项调换
temp = shuffled[index]
shuffled[index] = shuffled[i]
shuffled[i] = temp
}
return shuffled.slice(min)
}
================================================
FILE: musicPlayer/src/assets/utils/modalScroll.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-07-27 17:08:42
* @Update: 2019-08-10 16:42:32
* @Update log: 更新日志
*/
// 解决遮罩层滚动穿透问题,分别在遮罩层弹出后和关闭前调用
let _scrollTop
class ModalHelper {
// popup 显示时调用
static afterOpen () {
_scrollTop = document.scrollingElement.scrollTop
document.body.style.position = 'fixed'
document.body.style.top = -_scrollTop + 'px'
document.body.style.left = 0
document.body.style.bottom = 0
document.body.style.right = 0
}
// popup 关闭时调用
static beforeClose () {
document.body.style.position = ''
document.body.style.top = ''
document.body.style.left = ''
document.body.style.right = ''
document.body.style.bottom = ''
document.scrollingElement.scrollTop = _scrollTop
}
}
export default ModalHelper
================================================
FILE: musicPlayer/src/assets/utils/scrollStopVideo.js
================================================
/*
* @Author: Lambda
* @Begin: 2019-11-19 12:37:10
* @Update: 2019-11-19 13:48:22
* @Update log: 更新日志
*/
// 判断一个元素是否在视窗内
function isInSport (ele, wra) {
// 判断该图片是否能够加载,判断图片是否在可视区域内
const wraHeight = wra.clientHeight
const rect = ele.getBoundingClientRect()
// 如果超出视窗返回false
if (rect.bottom <= (wraHeight + 100) && rect.bottom >= (wraHeight / 2)) {
return true
}
if (rect.top <= (wraHeight + 100) && rect.top >= 0) {
return true
}
return false
}
export default isInSport
================================================
FILE: musicPlayer/src/assets/utils/setKeyWords.js
================================================
/*
* @Author: Lambda
* @Begin: 2019-11-01 13:07:59
* @Update: 2019-11-04 13:40:35
* @Update log: 更新日志
*/
/**
* 传入关键字和内容,将内容中含有关键字的部分添加对应的高亮样式
* @param {*} keyword
* @param {*} val
*/
export const filterSetKeyWords = (keyword, val, property) => {
let results = []
const _val = val
_val.map((item, index) => {
if (keyword && keyword.length > 0) {
// 匹配关键字正则
let replaceReg = new RegExp(keyword, 'g')
// 高亮替换v-html值
let replaceString =
`${keyword}`
_val[index][property] = item[property].replace(
replaceReg,
replaceString
)
}
})
results = _val
return results
}
================================================
FILE: musicPlayer/src/base/albumPage/index.vue
================================================
================================================
FILE: musicPlayer/src/base/albumPage/index2.vue
================================================
{{playCount | setPlay}}
{{iAlbumTitle}}
{{description}}
播放全部
(共{{trackCount}}首)
+ 收藏({{subscribedCountItem | setCol}})
{{subscribedCountItem | setCol}}
================================================
FILE: musicPlayer/src/base/alert.vue
================================================
================================================
FILE: musicPlayer/src/base/audioAllTitle.vue
================================================
播放全部
(共{{trackCount}}首)
================================================
FILE: musicPlayer/src/base/button.vue
================================================
================================================
FILE: musicPlayer/src/base/circleLoading.vue
================================================
================================================
FILE: musicPlayer/src/base/comments.vue
================================================
{{title}}
{{total}}
{{item.user.nickname}}
{{ item.time | setTime}}
{{item.likedCount}}
================================================
FILE: musicPlayer/src/base/djDetailPage/components/changeNav.vue
================================================
{{firstNav}}
{{secondNav}}
{{count}}
================================================
FILE: musicPlayer/src/base/djDetailPage/index.vue
================================================
{{name}}
{{subscription | setCount}}人已订阅
主播
电台内容简介
分类
{{category}}
{{desc}}
================================================
FILE: musicPlayer/src/base/djDetailPage/index2.vue
================================================
{{iTitle}}
{{name}}
{{subscription}}人已订阅
主播
电台内容简介
分类
{{category}}
{{desc}}
================================================
FILE: musicPlayer/src/base/djSublistCard.vue
================================================
{{title}}
({{count}})
{{item.playTime | numRule}}
{{ item.name }}
by {{item.dj.nickname}}
{{item.lastProgramName}}
{{ item.name }}
{{item.name}}
{{item.size}}首
{{ item.name }}
专辑:{{item.albumSize}}
MV:{{item.mvSize}}
{{ item.title }}
{{item.durationms | setTime}} by
{{item.userName}}
================================================
FILE: musicPlayer/src/base/generalNav.vue
================================================
================================================
FILE: musicPlayer/src/base/icon.vue
================================================
================================================
FILE: musicPlayer/src/base/idxCard.vue
================================================
{{ updateTime }}
{{index + 1 + '.'}}
{{item.first}} -
{{item.second}}
================================================
FILE: musicPlayer/src/base/imgCard.vue
================================================
{{playCount | setPlayCount}}
{{ updateTime }}
{{name}}
{{ dec }}
{{ item.name }}
================================================
FILE: musicPlayer/src/base/interchangeable.vue
================================================
{{playTime | numRule}}
MV
({{alia}})
{{nickname}}
{{nicknames.nickname}}
{{item.name}}
{{durationms | setYear}}
{{durationms | setTime}}
by
{{item.userName}}
{{trackCount}}首
by {{nickname}},
播放{{playCount | numRule}}次
已入驻
================================================
FILE: musicPlayer/src/base/loading.vue
================================================
================================================
FILE: musicPlayer/src/base/loginPageIsShow.vue
================================================
================================================
FILE: musicPlayer/src/base/pageErrorInfo.vue
================================================
未找到与"{{keywords}}"相关的内容
================================================
FILE: musicPlayer/src/base/pageLoading.vue
================================================
================================================
FILE: musicPlayer/src/base/searchInput.vue
================================================
================================================
FILE: musicPlayer/src/base/shouldLogin.vue
================================================
================================================
FILE: musicPlayer/src/base/slider.vue
================================================
================================================
FILE: musicPlayer/src/base/sliderNav.vue
================================================
{{ item.text }}{{item.num | empty}}
================================================
FILE: musicPlayer/src/base/song.vue
================================================
{{ num }}
({{alia}})
{{ item.name }}
{{ albumName }}
{{createTime | setMonth}}
{{listenerCount | setNum}}
{{duration | setTime}}
================================================
FILE: musicPlayer/src/base/songListPage/index.vue
================================================
{{iTitle}}
{{iTitle}}
{{day}}
{{month}}
查收属于您的今日推荐
{{playCount | setPlay}}
{{iAlbumTitle}}
{{description}}
播放全部
(共{{trackCount}}首)
多选
+ 收藏({{subscribedCountItem | setCol}})
{{subscribedCountItem | setCol}}
================================================
FILE: musicPlayer/src/base/titleFooter.vue
================================================
{{title}}
播放全部
{{moreText}}
================================================
FILE: musicPlayer/src/components/detailPage/index.vue
================================================
{{$title}}
这里显示吸顶标签行
下边展示音乐列表
这里是显示下方滑块
================================================
FILE: musicPlayer/src/components/top-tip/index.vue
================================================
================================================
FILE: musicPlayer/src/getInfos/getData.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-07-30 16:42:30
* @Update: 2019-07-30 16:42:30
* @Update log: 更新日志
*/
import Icons from './icons'
/**
* 获取我的页面上边的图标
*/
export const homeIcons = () => {
return Icons.homeIcons
}
/**
* 获取我的页面列表图标
*/
export const homeList = () => {
return Icons.homeList
}
/**
* 获取发现页面上边的图标
*/
export const findIcons = () => {
return Icons.findIcons
}
/**
* 获取登陆页面上边的图标
*/
export const loginIcons = () => {
return Icons.loginIcons
}
/**
* 获取登陆列表上边的图标
*/
export const loginIconsTop = () => {
return Icons.loginIconsTop
}
/**
* 获取登陆列表下边的图标
*/
export const loginIconsBottom = () => {
return Icons.loginIconsBottom
}
/**
* 获取电台页面图标数据
*/
export const djIcons = () => {
return Icons.djIcons
}
================================================
FILE: musicPlayer/src/getInfos/icons.js
================================================
/*
* @Author: Lambda
* @Begin: 2019-07-30 16:42:30
* @Update: 2019-10-18 11:25:41
* @Update log: 更新日志
*/
let homeIcons = [{
text: '私藏推荐',
icon: 'home iconxindian'
}, {
text: '私人FM',
icon: 'home iconshouyinji'
}, {
text: 'Sati空间',
icon: 'home iconyueliang'
}, {
text: '最新电音',
icon: 'home iconduodian'
}, {
text: '因乐交友',
icon: 'home iconjiaoyou'
}, {
text: '亲子频道',
icon: 'home iconertong'
}, {
text: '古典专区',
icon: 'home icongangqin'
}, {
text: '跑步FM',
icon: 'home iconorder-received'
}, {
text: '小冰电台',
icon: 'home iconbingjiling'
}, {
text: '爵士电台',
icon: 'home iconyandou'
}, {
text: '驾驶模式',
icon: 'home iconqiche'
}, {
text: '编辑',
icon: 'home icontoggle'
}]
let findIcons = [{
text: '每日推荐',
icon: 'find rili',
linkTo: 'dateRecommend'
}, {
text: '歌单',
icon: 'find gedan',
linkTo: 'recommend'
}, {
text: '排行榜',
icon: 'find paixingbang',
linkTo: 'idx'
}, {
text: '电台',
icon: 'find diantai',
linkTo: 'dj'
}, {
text: '私人FM',
icon: 'find shouyin',
linkTo: 'personalFm'
}]
let djIcons = [{
text: '电台分类',
icon: 'dj dj-caidan1',
linkTo: 'classification'
}, {
text: '电台排行',
icon: 'dj dj-paixing',
linkTo: 'ranking'
}, {
text: '付费精品',
icon: 'dj dj-gerenzhongxin_wodeguizu',
linkTo: 'pay_fine'
}, {
text: '主播学院',
icon: 'dj dj-shucopy',
linkTo: 'anchor_college'
}]
let homeList = [{
icon: 'iconyinyue',
text: '本地音乐',
num: 0
}, {
icon: 'iconzuijinbofang',
text: '最近播放',
num: 0
}, {
icon: 'iconxiazai',
text: '下载管理',
num: 0
}, {
icon: 'icondiantai',
text: '我的电台',
num: 0
}, {
icon: 'iconicon-31',
text: '我的收藏',
num: 0
}]
let loginIcons = [{
icon: 'login iconwodexiaoxi',
text: '我的消息'
}, {
icon: 'login iconyonghu',
text: '我的好友'
}, {
icon: 'login iconpifu',
text: '个性皮肤'
}, {
icon: 'login icontinggeshiqu40x40',
text: '听歌识曲'
}]
let loginIconsTop = [{
icon: 'iconhuopiaotongxing',
text: '演出'
}, {
icon: 'icongouwuche',
text: '商城'
}, {
icon: 'icondibiao',
text: '附近的人'
}, {
icon: 'iconicon--',
text: '口袋铃声'
}, {
icon: 'icondingdan',
text: '我的订单'
}]
let loginIconsBottom = [{
icon: 'iconicon--2',
text: '定时停止播放'
}, {
icon: 'iconsaoyisao',
text: '扫一扫'
}, {
icon: 'iconicon--1',
text: '音乐闹钟'
}, {
icon: 'iconhezi501',
text: '在线听歌免流量'
}, {
icon: 'iconyouxi',
text: '游戏推荐'
}, {
icon: 'iconCoupon',
text: '优惠券'
}, {
icon: 'iconmaikefeng',
text: '我要直播'
}]
export default {
homeIcons,
findIcons,
homeList,
loginIcons,
loginIconsTop,
loginIconsBottom,
djIcons
}
================================================
FILE: musicPlayer/src/main.js
================================================
/*
* @Author: Lambda
* @Begin: 2019-08-30 19:47:55
* @Update: 2020-03-13 22:29:57
* @Update log: 更新日志
*/
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
import fastclick from 'fastclick'
import VueLazyload from 'vue-lazyload'
import topTip from '@/components/top-tip'
import {
Search,
ActionSheet,
Swipe,
SwipeItem,
Button,
Checkbox,
CheckboxGroup,
PasswordInput,
NumberKeyboard,
PullRefresh
} from 'vant'
import 'styles/reset.css'
import 'styles/border.css'
fastclick.attach(document.body)
// import ""
Vue.use(Search)
Vue.use(Button)
Vue.use(ActionSheet)
Vue.use(PullRefresh)
Vue.use(Swipe).use(SwipeItem)
Vue.use(Checkbox).use(CheckboxGroup)
Vue.use(PasswordInput).use(NumberKeyboard)
Vue.config.productionTip = false
Vue.use(VueLazyload, {
preLoad: 1.3,
error: './assets/load.gif',
loading: 'data:image/png;base64,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',
attempt: 1,
listenEvents: ['scroll', 'wheel', 'mousewheel', 'resize', 'animationend', 'transitionend', 'touchmove']
})
Vue.component('top-tip', topTip)
/* eslint-disable no-new */
// eslint-disable-next-line no-unused-vars
var vm = new Vue({
el: '#app',
router,
store,
components: {
App
},
template: ''
})
window.vm = vm
================================================
FILE: musicPlayer/src/pages/audioIndex/components/audioList.vue
================================================
{{ modeText }}
({{ num }})
收藏全部
================================================
FILE: musicPlayer/src/pages/audioIndex/components/bar.vue
================================================
{{ time }}
{{ allTime | setTime }}
================================================
FILE: musicPlayer/src/pages/audioIndex/components/functionButton.vue
================================================
================================================
FILE: musicPlayer/src/pages/audioIndex/components/lyricPage.vue
================================================
================================================
FILE: musicPlayer/src/pages/audioIndex/components/playIcons.vue
================================================
================================================
FILE: musicPlayer/src/pages/audioIndex/components/playing.vue
================================================
================================================
FILE: musicPlayer/src/pages/audioIndex/components/small.vue
================================================
{{name}}
{{ lyric | emptyCon }}
================================================
FILE: musicPlayer/src/pages/audioIndex/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/commentsIndex/components/albumListInfo.vue
================================================
{{info.title}}
by
{{info.author}}
================================================
FILE: musicPlayer/src/pages/commentsIndex/components/centerMenu.vue
================================================
================================================
FILE: musicPlayer/src/pages/commentsIndex/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/dateRecommend/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/dj/childrenPage/class.vue
================================================
================================================
FILE: musicPlayer/src/pages/dj/childrenPage/classRecommend.vue
================================================
================================================
FILE: musicPlayer/src/pages/dj/childrenPage/djPayGift.vue
================================================
付费精品
{{item.name}}
¥ {{item.originalPrice | price}}
================================================
FILE: musicPlayer/src/pages/dj/childrenPage/ranking-anchor.vue
================================================
================================================
FILE: musicPlayer/src/pages/dj/childrenPage/ranking-program.vue
================================================
================================================
FILE: musicPlayer/src/pages/dj/childrenPage/ranking-radio.vue
================================================
================================================
FILE: musicPlayer/src/pages/dj/childrenPage/ranking.vue
================================================
================================================
FILE: musicPlayer/src/pages/dj/childrenPage/topConDetail.vue
================================================
{{title}}
更新时间: {{updateTime | setTime}}
================================================
FILE: musicPlayer/src/pages/dj/components/boutiqueRecom.vue
================================================
================================================
FILE: musicPlayer/src/pages/dj/components/icons.vue
================================================
================================================
FILE: musicPlayer/src/pages/dj/components/radioRecom.vue
================================================
================================================
FILE: musicPlayer/src/pages/dj/components/swiper.vue
================================================
{{item.typeTitle}}
================================================
FILE: musicPlayer/src/pages/dj/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/dj/public.vue
================================================
================================================
FILE: musicPlayer/src/pages/dj/publicClass.vue
================================================
================================================
FILE: musicPlayer/src/pages/dj/publicImgWrap.vue
================================================
================================================
FILE: musicPlayer/src/pages/dj/titleAndThree.vue
================================================
{{title}}
{{item.program ? item.program.name : item.nickName ? item.nickName : item.name}}
{{ item.score | setCount}}
================================================
FILE: musicPlayer/src/pages/djSublist/index.vue
================================================
我的电台
================================================
FILE: musicPlayer/src/pages/findIndex/components/chinese.vue
================================================
================================================
FILE: musicPlayer/src/pages/findIndex/components/europe.vue
================================================
================================================
FILE: musicPlayer/src/pages/findIndex/components/icons.vue
================================================
{{today}}
================================================
FILE: musicPlayer/src/pages/findIndex/components/japan.vue
================================================
================================================
FILE: musicPlayer/src/pages/findIndex/components/korea.vue
================================================
================================================
FILE: musicPlayer/src/pages/findIndex/components/moreNewDish.vue
================================================
新碟上架
{{prevMonth}}月
/{{prevYear}}
================================================
FILE: musicPlayer/src/pages/findIndex/components/moreNewSongs.vue
================================================
================================================
FILE: musicPlayer/src/pages/findIndex/components/newDish.vue
================================================
================================================
FILE: musicPlayer/src/pages/findIndex/components/personalizedSongList.vue
================================================
================================================
FILE: musicPlayer/src/pages/findIndex/components/swiper.vue
================================================
{{item.typeTitle}}
================================================
FILE: musicPlayer/src/pages/findIndex/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/friendIndex/index.vue
================================================
静待...
欢迎访问我的 GitHub
项目地址
您的 star 是我最大的鼓励
================================================
FILE: musicPlayer/src/pages/friendIndex/public.vue
================================================
{{item.video.creator.nickname}}
发布
{{item.userReason}}
{{item.msg}}
{{item.video.playTime | setCount}}
{{item.video.durationms | setTime}}
================================================
FILE: musicPlayer/src/pages/homeIndex/components/addNewPlayList.vue
================================================
================================================
FILE: musicPlayer/src/pages/homeIndex/components/homeList.vue
================================================
================================================
FILE: musicPlayer/src/pages/homeIndex/components/icons.vue
================================================
================================================
FILE: musicPlayer/src/pages/homeIndex/components/songList.vue
================================================
创建的歌单
({{index.createNum}})
-
心动模式
-
{{ item.name | setName}}
{{item.trackCount}}首
心动模式
-
{{ item.name}}
{{item.trackCount}}首
收藏的歌单
({{index.favoritesNum}})
-
{{ item.name}}
{{item.trackCount}}首
by {{item.creator.nickname}}
================================================
FILE: musicPlayer/src/pages/homeIndex/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/idx/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/loginIndex/components/accountLogin.vue
================================================
{{text}}
================================================
FILE: musicPlayer/src/pages/loginIndex/components/phoneAccount.vue
================================================
================================================
FILE: musicPlayer/src/pages/loginIndex/components/phonePwd.vue
================================================
================================================
FILE: musicPlayer/src/pages/loginIndex/components/phoneVerify.vue
================================================
================================================
FILE: musicPlayer/src/pages/loginIndex/components/verifyCode.vue
================================================
================================================
FILE: musicPlayer/src/pages/loginIndex/components/verifyInfo.vue
================================================
验证码已发送至
+86
{{phone1}}
****
{{phone2}}
重新获取
================================================
FILE: musicPlayer/src/pages/loginIndex/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/myFavorite/components/albums.vue
================================================
================================================
FILE: musicPlayer/src/pages/myFavorite/components/artists.vue
================================================
================================================
FILE: musicPlayer/src/pages/myFavorite/components/column.vue
================================================
专栏页面
================================================
FILE: musicPlayer/src/pages/myFavorite/components/mlog.vue
================================================
Mlog 页面
================================================
FILE: musicPlayer/src/pages/myFavorite/components/videos.vue
================================================
================================================
FILE: musicPlayer/src/pages/myFavorite/index.vue
================================================
我的收藏
================================================
FILE: musicPlayer/src/pages/nav/components/login-bottom.vue
================================================
{{ modeText }}间模式
设置
退出
================================================
FILE: musicPlayer/src/pages/nav/components/login-icons-bottom.vue
================================================
================================================
FILE: musicPlayer/src/pages/nav/components/login-icons-top.vue
================================================
================================================
FILE: musicPlayer/src/pages/nav/components/login-icons.vue
================================================
================================================
FILE: musicPlayer/src/pages/nav/components/login-top.vue
================================================
登陆网易云音乐
手机电脑多端同步,尽享海量高品质音乐
立即登录
{{nickname}}
Lv.{{level}}
签到
已签到
================================================
FILE: musicPlayer/src/pages/nav/components/login.vue
================================================
================================================
FILE: musicPlayer/src/pages/nav/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/recentlyPlayed/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/recommend/fine/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/recommend/general/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/recommend/index.vue
================================================
歌单广场
================================================
FILE: musicPlayer/src/pages/recommend/navIndex/navList.vue
================================================
{{ item.text }}
================================================
FILE: musicPlayer/src/pages/recommend/recommended/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchIndex/components/history.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchIndex/components/hotSearch.vue
================================================
热搜榜
-
{{ index + 1 }}
{{ item.searchWord }}
{{ item.score }}
{{ item.content }}
================================================
FILE: musicPlayer/src/pages/searchIndex/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/albumIndex/album.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/artistIndex/artist.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/composite/components/album.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/composite/components/artist.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/composite/components/djRadio.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/composite/components/playList.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/composite/components/simQuery.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/composite/components/song.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/composite/components/user.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/composite/components/video.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/composite/composite.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/djRadioIndex/djRadio.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/navIndex/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/playListIndex/playList.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/singerIndex/select.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/singerIndex/singer.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/songIndex/song.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/userIndex/user.vue
================================================
================================================
FILE: musicPlayer/src/pages/searchResults/videoIndex/video.vue
================================================
================================================
FILE: musicPlayer/src/pages/userInfoIndex/components/userDynamic.vue
================================================
暂时还没有动态哦
{{item.program.dj.nickname}}
发布
{{item.program.createTime | setTime}}
{{item.msg}}
================================================
FILE: musicPlayer/src/pages/userInfoIndex/components/userHome.vue
================================================
基本信息
个人介绍:
{{signature}}
村龄:
{{age}}年({{year}}年{{month}}月注册)
年龄:
{{ birthday | setAge }}后
{{astro}}座
累计听歌:
{{ listenSongs }}首
================================================
FILE: musicPlayer/src/pages/userInfoIndex/index.vue
================================================
{{iTitle}}
{{nickname}}
关注 {{newFollows}}
|
粉丝 {{followeds}}
{{ birthday | setAge }}后
Lv.{{level}}
基本信息
个人介绍:
{{signature}}
村龄:
{{age}}年({{year}}年{{month}}月注册)
年龄:
{{ birthday | setAge }}后
{{astro}}座
累计听歌:
{{ listenSongs }}首
================================================
FILE: musicPlayer/src/pages/videoIndex/components/acg.vue
================================================
================================================
FILE: musicPlayer/src/pages/videoIndex/components/animation.vue
================================================
================================================
FILE: musicPlayer/src/pages/videoIndex/components/dance.vue
================================================
================================================
FILE: musicPlayer/src/pages/videoIndex/components/game.vue
================================================
================================================
FILE: musicPlayer/src/pages/videoIndex/components/listenBGM.vue
================================================
================================================
FILE: musicPlayer/src/pages/videoIndex/components/musicFestival.vue
================================================
================================================
FILE: musicPlayer/src/pages/videoIndex/components/rock.vue
================================================
================================================
FILE: musicPlayer/src/pages/videoIndex/components/scene.vue
================================================
================================================
FILE: musicPlayer/src/pages/videoIndex/components/singing.vue
================================================
================================================
FILE: musicPlayer/src/pages/videoIndex/index.vue
================================================
================================================
FILE: musicPlayer/src/pages/videoIndex/public.vue
================================================
{{ item.data.videoGroup ? item.data.videoGroup[0].name : ''}}
{{item.data.playTime | setCount}}
{{item.data.durationms | setTime}}
{{item.data.title}}
{{item.data.creator.nickname}}
{{item.data.praisedCount | setCount}}
================================================
FILE: musicPlayer/src/pages/videoIndex/videoComments/components/video.vue
================================================
================================================
FILE: musicPlayer/src/pages/videoIndex/videoComments/components/videoCreator.vue
================================================
================================================
FILE: musicPlayer/src/pages/videoIndex/videoComments/components/videoInfo.vue
================================================
{{title}}
{{playTime | setNum}}次观看
#{{item.name | setName}}#
{{praisedCount | setNum}}
{{subscribeCount | setNum}}
{{commentCount | setNum}}
{{shareCount | setNum}}
================================================
FILE: musicPlayer/src/pages/videoIndex/videoComments/index.vue
================================================
================================================
FILE: musicPlayer/src/router/index.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-07-27 17:08:42
* @Update: 2019-12-07 13:17:07
* @Update log: 更新日志
*/
import Vue from 'vue'
import Router from 'vue-router'
const navIndex = () => import(/* webpackChunkName: "group-nav" */ '@/pages/nav/index')
const findIndex = () => import(/* webpackChunkName: "group-findPage" */ '@/pages/findIndex/index')
const homeIndex = () => import(/* webpackChunkName: "group-homePage" */ '@/pages/homeIndex/index')
const videoIndex = () => import(/* webpackChunkName: "group-homePage" */ '@/pages/videoIndex/index')
const videoComments = () => import(/* webpackChunkName: "group-homePage" */ '@/pages/videoIndex/videoComments/index')
const userInfoIndex = () => import(/* webpackChunkName: "group-homePage" */ '@/pages/userInfoIndex/index')
const musicFestival = () => import(/* webpackChunkName: "group-homePage" */ '@/pages/videoIndex/components/musicFestival')
const scene = () => import(/* webpackChunkName: "group-homePage" */ '@/pages/videoIndex/components/scene')
const listenBGM = () => import(/* webpackChunkName: "group-homePage" */ '@/pages/videoIndex/components/listenBGM')
const singing = () => import(/* webpackChunkName: "group-homePage" */ '@/pages/videoIndex/components/singing')
const dance = () => import(/* webpackChunkName: "group-homePage" */ '@/pages/videoIndex/components/dance')
const acg = () => import(/* webpackChunkName: "group-homePage" */ '@/pages/videoIndex/components/acg')
const rock = () => import(/* webpackChunkName: "group-homePage" */ '@/pages/videoIndex/components/rock')
const game = () => import(/* webpackChunkName: "group-homePage" */ '@/pages/videoIndex/components/game')
const animation = () => import(/* webpackChunkName: "group-homePage" */ '@/pages/videoIndex/components/animation')
const friend = () => import(/* webpackChunkName: "group-homePage" */ '@/pages/friendIndex/index')
const loginIndex = () => import(/* webpackChunkName: "group-loginPage" */ '@/pages/loginIndex/index')
const phoneAccount = () => import(/* webpackChunkName: "group-login-phonePage" */ '@/pages/loginIndex/components/phoneAccount')
const phonePwd = () => import(/* webpackChunkName: "group-login-pwdPage" */ '@/pages/loginIndex/components/phonePwd')
const phoneVerify = () => import(/* webpackChunkName: "group-login-verifyPage" */ '@/pages/loginIndex/components/phoneVerify')
const search = () => import(/* webpackChunkName: "group-searchPage" */ '@/pages/searchIndex/index')
const searchResults = () => import(/* webpackChunkName: "group-resultPage" */ '@/pages/searchResults/index')
const singer = () => import(/* webpackChunkName: "group-resultPage" */ '@/pages/searchResults/singerIndex/singer')
const composite = () => import(/* webpackChunkName: "group-result-comPage" */ '@/pages/searchResults/composite/composite')
const song = () => import(/* webpackChunkName: "group-result-songPage" */ '@/pages/searchResults/songIndex/song')
const video = () => import(/* webpackChunkName: "group-result-videoPage" */ '@/pages/searchResults/videoIndex/video')
const artist = () => import(/* webpackChunkName: "group-result-artistPage" */ '@/pages/searchResults/artistIndex/artist')
const album = () => import(/* webpackChunkName: "group-result-albumPage" */ '@/pages/searchResults/albumIndex/album')
const playList = () => import(/* webpackChunkName: "group-result-playlistPage" */ '@/pages/searchResults/playListIndex/playList')
const djRadio = () => import(/* webpackChunkName: "group-result-djRadioPage" */ '@/pages/searchResults/djRadioIndex/djRadio')
const user = () => import(/* webpackChunkName: "group-result-userPage" */ '@/pages/searchResults/userIndex/user')
const dateRecommend = () => import(/* webpackChunkName: "group-date-recommendPage" */ '@/pages/dateRecommend')
const recommend = () => import(/* webpackChunkName: "group-recommendPage" */ '@/pages/recommend')
const recommended = () => import(/* webpackChunkName: "group-recommendedPage" */ '@/pages/recommend/recommended')
const fine = () => import(/* webpackChunkName: "group-recommendedPage" */ '@/pages/recommend/fine')
const general = () => import(/* webpackChunkName: "group-recommendedPage" */ '@/pages/recommend/general')
const idx = () => import(/* webpackChunkName: "group-idxPage" */ '@/pages/idx')
const dj = () => import(/* webpackChunkName: "group-djPage" */ '@/pages/dj')
const classification = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/dj/childrenPage/class')
const djPayGift = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/dj/childrenPage/djPayGift')
const djRanking = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/dj/childrenPage/ranking')
const djRankingAnchor = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/dj/childrenPage/ranking-anchor')
const djRankingProgram = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/dj/childrenPage/ranking-program')
const djRankingRadio = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/dj/childrenPage/ranking-radio')
const albumPage = () => import(/* webpackChunkName: "group-albumPage" */ 'base/albumPage')
const djDetailPage = () => import(/* webpackChunkName: "group-djDetailPage" */ 'base/djDetailPage')
const djTopConDetailPage = () => import(/* webpackChunkName: "group-djDetailPage" */ '@/pages/dj/childrenPage/topConDetail')
const djClassRecommendDetailPage = () => import(/* webpackChunkName: "group-djDetailPage" */ '@/pages/dj/childrenPage/classRecommend')
const artistDetailPage = () => import(/* webpackChunkName: "group-djDetailPage" */ '@/components/detailPage')
const recentlyPlayed = () => import(/* webpackChunkName: "group-recentlyPlayed" */ '@/pages/recentlyPlayed')
const djSublist = () => import(/* webpackChunkName: "group-djSublist" */ '@/pages/djSublist')
const myFavorite = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/myFavorite')
const albums = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/myFavorite/components/albums')
const artists = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/myFavorite/components/artists')
const column = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/myFavorite/components/column')
const mlog = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/myFavorite/components/mlog')
const videos = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/myFavorite/components/videos')
const moreNewDish = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/findIndex/components/moreNewDish')
const moreNewSongs = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/findIndex/components/moreNewSongs')
const chinese = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/findIndex/components/chinese')
const europe = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/findIndex/components/europe')
const korea = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/findIndex/components/korea')
const japan = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/findIndex/components/japan')
const comments = () => import(/* webpackChunkName: "group-myFavorite" */ '@/pages/commentsIndex/index')
Vue.use(Router)
export default new Router({
/**************************************************
*
* 设置 链接激活时使用的 CSS 类名
* 默认值: "router-link-active"
* 可以通过路由的构造选项 linkActiveClass 来全局配置。
*
* 通过设置 meta: { keepAlive: true },来定义一个页面是否需要做缓存
*
**************************************************/
linkActiveClass: 'ac',
routes: [{
/**
* 设置页面初次加载后默认显示 find 页面
*/
path: '/',
name: 'main',
component: navIndex,
redirect: '/find',
children: [{
path: '/find',
component: findIndex
}, {
path: '/home',
name: 'home',
component: homeIndex
}, {
path: '/friend',
component: friend
}, {
path: '/videoPage',
name: 'videoPage',
component: videoIndex,
redirect: '/videoPage/musicFestival',
children: [{
path: '/videoPage/musicFestival',
component: musicFestival
}, {
path: '/videoPage/scene/:id',
component: scene
}, {
path: '/videoPage/listenBGM/:id',
component: listenBGM
}, {
path: '/videoPage/singing/:id',
component: singing
}, {
path: '/videoPage/dance/:id',
component: dance
}, {
path: '/videoPage/ACG/:id',
component: acg
}, {
path: '/videoPage/rock/:id',
component: rock
}, {
path: '/videoPage/game/:id',
component: game
}, {
path: '/videoPage/animation/:id',
component: animation
}]
}]
}, {
// 视频评论页面
// 使用 this.$router.push({ name: 'videoComments', params: { id } })
// 可以使得地址栏不显示 id 信息,并且可以通过 this.$route.params 获取到值
// 要注意这时候在path中不能再写 /:id
path: '/videoComments',
name: 'videoComments',
component: videoComments
}, {
// 更多新碟
path: '/moreNewDish',
component: moreNewDish
}, {
// 新歌推荐
path: '/moreNewSongs',
component: moreNewSongs,
redirect: '/chinese',
children: [{
path: '/chinese',
component: chinese
}, {
path: '/europe',
component: europe
}, {
path: '/korea',
component: korea
}, {
path: '/japan',
component: japan
}]
}, {
// 最近播放
path: '/recently',
component: recentlyPlayed
}, {
path: '/dj_sublist',
component: djSublist
}, {
path: '/favorite',
component: myFavorite,
redirect: '/albums',
children: [{
path: '/albums',
component: albums
}, {
path: '/artists',
component: artists
}, {
path: '/videos',
component: videos
}, {
path: '/column',
component: column
}, {
path: '/mlog',
component: mlog
}]
}, {
path: '/login',
name: 'login',
component: loginIndex
}, {
// 登录的一系列路由
path: '/phone',
component: phoneAccount
}, {
path: '/pwd',
name: 'phonePwd',
component: phonePwd
}, {
path: '/verify',
name: 'phoneVerify',
component: phoneVerify
},
{
// 搜索页
path: '/search',
component: search
},
{
// 搜索展示页面
path: '/searchResults/:id',
component: searchResults,
redirect: '/composite/:id',
children: [{
// 综合页面
path: '/composite/:id',
component: composite
}, {
// 单曲页面
path: '/song/:id',
component: song
}, {
// 视频页面
path: '/video/:id',
component: video
}, {
// 歌手页面
path: '/artist/:id',
component: artist
}, {
// 专辑页面
path: '/album/:id',
component: album
}, {
// 歌单页面
path: '/playList/:id',
component: playList
}, {
// 主播电台页面
path: '/djRadio/:id',
component: djRadio
}, {
// 用户页面
path: '/user/:id',
component: user
}]
},
{
// 歌手分类页面
path: '/singer',
component: singer
},
{
// 用户信息展示页面
path: '/user_info',
name: 'user_info',
component: userInfoIndex
},
{
// 每日推荐页面
path: '/dateRecommend',
component: dateRecommend
},
{
// 歌单广场页面
path: '/recommend',
component: recommend,
redirect: '/recommended',
children: [{
// 推荐歌单
path: '/recommended',
component: recommended
}, {
// 精品歌单
path: '/fine',
component: fine
}, {
// 通用歌单
path: '/general/:id',
component: general
}]
},
{
// 排行榜页面
path: '/idx',
component: idx
},
{
// 电台页面
path: '/dj',
component: dj
},
{
path: '/conDetail',
name: 'conDetail',
component: djTopConDetailPage
},
{
// 电台分类
path: '/classification',
component: classification
},
{
// 电台分类详情
path: '/classDetail',
name: 'classDetail',
component: djClassRecommendDetailPage
},
{
path: '/pay_fine',
component: djPayGift
},
{
path: '/ranking',
component: djRanking,
redirect: '/program',
children: [{
path: '/anchor',
component: djRankingAnchor
}, {
path: '/program',
component: djRankingProgram
}, {
path: '/radio',
component: djRankingRadio
}]
},
{
// 通用专辑展示页面
path: '/albumPage',
name: 'albumPage',
component: albumPage
},
{
// 通用电台详情展示页面
path: '/djDetailPage',
name: 'djDetailPage',
component: djDetailPage
},
{
// 通用歌手展示页面
path: '/artistDetailPage',
name: 'artistDetailPage',
component: artistDetailPage
},
{
// 通用评论展示页面
path: '/comments',
name: 'comments',
component: comments
}
]
})
================================================
FILE: musicPlayer/src/store/actions.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-09-12 14:11:33
* @Update: 2019-09-22 12:15:54
* @Update log: 更新日志
*/
import {
SET_PLAY_SATE,
SET_FULL_SCREEN,
SET_AUDIO_LIST,
SET_AUDIO_INDEX,
SET_AUDIO_MODE,
SET_PLAY_LIST
} from './mutation-types'
/**
* 获取随机值
*/
function getRandomIndex (min, max) {
return Math.floor(Math.random() * (max - min + 1) + min)
}
/**
* 打乱一个数组
*/
function shuffle (arr) {
const _arr = arr.slice()
for (let i = 0; i < _arr.length; i++) {
const j = getRandomIndex(0, i)
const t = _arr[i]
_arr[i] = _arr[j]
_arr[j] = t
}
return _arr
}
function findIndex (list, song) {
return list.findIndex(item => {
return item.id === song.id
})
}
export default {
/**
* 点击歌曲项进行播放
*/
selectPlay ({
commit,
state
}, {
list,
index
}) {
commit(SET_AUDIO_LIST, list)
if (state.mode === 2) {
const randomList = shuffle(list)
commit(SET_PLAY_LIST, randomList)
index = findIndex(randomList, state.audioList[index])
} else {
commit(SET_PLAY_LIST, list)
}
commit(SET_AUDIO_INDEX, index)
commit(SET_PLAY_SATE, true)
commit(SET_FULL_SCREEN, true)
},
/**
* 播放全部
* 传入播放列表
*/
startPlayAll ({
commit
}, {
list
}) {
commit(SET_AUDIO_LIST, list)
commit(SET_AUDIO_INDEX, 0)
commit(SET_PLAY_LIST, list)
commit(SET_PLAY_SATE, true)
commit(SET_FULL_SCREEN, true)
commit(SET_AUDIO_MODE, 0)
},
/**
* 向播放列表添加歌曲
* 当播放列表为空时添加后开始播放
*/
addToAudioList ({
commit,
state
}, song) {
let audioList = state.audioList
let playList = state.playList
let currentIndex = state.audioIngIndex
// 记录当前歌曲
let audioIng = audioList[currentIndex]
// 查找当前列表中是否有要插入的歌曲,并返回它的索引
let findAudioIndex = findIndex(audioList, song)
// 因为是插入歌曲,所以索引要+1
currentIndex++
// 插入这首歌到当前索引位置
audioList.splice(currentIndex, 0, song)
// 如果已经有了这首歌
if (findAudioIndex > -1) {
// 如果当前插入序号大于列表中的序号
if (currentIndex > findAudioIndex) {
audioList.splice(findAudioIndex, 1)
currentIndex--
} else {
audioList.splice(currentIndex + 1, 1)
}
}
let currentPlayIndex = findIndex(playList, audioIng) + 1
let findPlayIndex = findIndex(playList, song)
playList.splice(currentPlayIndex, 0, song)
if (findPlayIndex > -1) {
if (currentPlayIndex > findPlayIndex) {
playList.splice(findPlayIndex, 1)
} else {
playList.splice(findPlayIndex + 1, 1)
}
}
commit(SET_AUDIO_INDEX, currentIndex)
commit(SET_PLAY_SATE, true)
},
deleteSong ({
commit,
state
}, song) {
let audioList = state.audioList.slice()
let playList = state.playList.slice()
let currentIndex = state.audioIngIndex
// 删除的歌曲是当前播放歌曲之前
let pIndex = findIndex(audioList, song)
audioList.splice(pIndex, 1)
// 删除的歌曲是当前歌曲之后
let sIndex = findIndex(playList, song)
playList.splice(sIndex, 1)
if (currentIndex > pIndex || currentIndex === audioList.length) {
currentIndex--
}
commit(SET_AUDIO_LIST, audioList)
commit(SET_PLAY_LIST, playList)
commit(SET_AUDIO_INDEX, currentIndex)
if (!audioList.length) {
commit(SET_PLAY_SATE, false)
}
}
}
================================================
FILE: musicPlayer/src/store/getters.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-08-24 11:44:49
* @Update: 2019-09-15 12:29:49
* @Update log: 更新日志
*/
const getters = {
LOGIN_PAGE: state => state.loginPage,
ICON_SUN: state => state.icontaiyang,
ICON_NIGHT: state => state.iconyueliang1,
MODE_TEXT: state => state.modeText,
LOGIN_STATE: state => state.loginState,
LEVEL: state => state.level,
ACCOUNT_UID: state => state.accountUid,
LOAD: state => state.load,
LINK_PAGE: state => state.linkPage,
PLAY_STATE: state => state.playState,
FULL_SCREEN: state => state.fullScreen,
AUDIO_LIST: state => state.audioList,
AUDIO_ING_INDEX: state => state.audioIngIndex,
PLAY_LIST: state => state.playList,
MODE: state => state.mode,
OFFSET_LYRIC: state => state.offsetLyric,
PLAYING_SHOW: state => state.playingShow,
AUDIO_ING_SONG: state => {
// 返回当前播放歌曲对象的信息
return state.playList[state.audioIngIndex] || {}
}
}
export default getters
================================================
FILE: musicPlayer/src/store/index.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-07-30 16:42:30
* @Update: 2019-09-12 14:23:38
* @Update log: 更新日志
*/
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'
import getters from './getters'
import actions from './actions'
Vue.use(Vuex)
const store = new Vuex.Store({
state,
mutations,
getters,
actions
})
export default store
================================================
FILE: musicPlayer/src/store/mutation-types.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-07-30 16:42:30
* @Update: 2019-08-11 18:00:46
* @Update log: 更新日志
*/
export const SHOW_LOGIN = 'SHOW_LOGIN' // 显示侧边栏
export const HIDE_LOGIN = 'HIDE_LOGIN' // 隐藏侧边栏
export const TOGGLE_MODE = 'TOGGLE_MODE' // 日夜模式切换
export const TOGGLE_MODE_TEXT = 'TOGGLE_MODE_TEXT' // 日夜文字切换
export const TO_SUN = 'TO_SUN' // 由夜转换到日
export const TO_YUE = 'TO_YUE' // 由日转换到夜
export const LOGIN_STATE = 'LOGIN_STATE' // 登陆状态
export const SET_LEVEL = 'SET_LEVEL' // 设置用户等级
export const ACCOUNT_UID = 'ACCOUNT_UID' // 存取用户id
export const SET_LOAD = 'SET_LOAD' // 设置当前已经返回数据,显示界面
export const RETURN_LOAD = 'RETURN_LOAD' // 将load返回默认的true
export const SET_LINK_PAGE = 'SET_LINK_PAGE' // 将load返回默认的true
export const SET_PLAY_SATE = 'SET_PLAY_SATE' // 设置当前的播放状态
export const SET_FULL_SCREEN = 'SET_FULL_SCREEN' // 设置当前的播放器的状态,是大还是小
export const SET_AUDIO_LIST = 'SET_AUDIO_LIST' // 设置当前的播放列表的展示
export const SET_PLAY_LIST = 'SET_PLAY_LIST' // 设置当前的播放列表
export const SET_AUDIO_INDEX = 'SET_AUDIO_INDEX' // 设置当前的播放歌曲是第几个,索引值
export const SET_AUDIO_MODE = 'SET_AUDIO_MODE' // 设置当前的播放模式
export const SET_PLAYING_SHOW = 'SET_PLAYING_SHOW' // 设置当前是否显示转盘播放页面
================================================
FILE: musicPlayer/src/store/mutations.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-07-30 16:42:30
* @Update: 2019-09-12 13:48:12
* @Update log: 更新日志
*/
import {
SHOW_LOGIN,
HIDE_LOGIN,
TOGGLE_MODE,
TOGGLE_MODE_TEXT,
TO_SUN,
TO_YUE,
LOGIN_STATE,
ACCOUNT_UID,
SET_LOAD,
RETURN_LOAD,
SET_LINK_PAGE,
SET_PLAY_SATE,
SET_FULL_SCREEN,
SET_AUDIO_LIST,
SET_AUDIO_INDEX,
SET_PLAY_LIST,
SET_AUDIO_MODE,
SET_PLAYING_SHOW,
SET_LEVEL
} from './mutation-types'
// 实现侧边栏显示时底部不跟随滚动
import ModalHelper from 'utils/modalScroll'
export default {
// 显示左侧侧边栏页面
[SHOW_LOGIN] (state) {
state.loginPage = true
ModalHelper.afterOpen()
},
// 隐藏左侧侧边栏页面
[HIDE_LOGIN] (state) {
state.loginPage = false
ModalHelper.beforeClose()
},
// 从日间模式切换到夜间模式
[TO_YUE] (state) {
console.log('切换到夜间')
state.iconyueliang1 = false
state.icontaiyang = true
this._mutations.TOGGLE_MODE_TEXT[0](state)
},
// 从夜间模式切换到日间模式
[TO_SUN] (state) {
console.log('切换到日间')
state.iconyueliang1 = true
state.icontaiyang = false
this._mutations.TOGGLE_MODE_TEXT[0](state)
},
// 切换夜间 日间模式
[TOGGLE_MODE] (state) {
if (state.iconyueliang1) {
this._mutations.TO_YUE[0](state)
} else if (state.icontaiyang) {
this._mutations.TO_SUN[0](state)
}
},
// 切换夜间 日间模式文本
[TOGGLE_MODE_TEXT] (state) {
if (state.icontaiyang) {
state.modeText = '日'
} else {
state.modeText = '夜'
}
},
// 设置用户登陆状态
[LOGIN_STATE] (state, num) {
state.loginState = num
},
[SET_LEVEL] (state, num) {
state.level = num
},
// 存取用户 uid
[ACCOUNT_UID] (state, id) {
state.accountUid = id
},
// 设置搜索展示页面的loading图标
[SET_LOAD] (state) {
state.load = false
},
[RETURN_LOAD] (state) {
state.load = true
},
/**
* 设置搜索展示页标签导航条
*/
[SET_LINK_PAGE] (state, page) {
state.linkPage = page
},
/**
* 设置播放状态
* @param {*} state state 数据
* @param {*} flag 播放状态
*/
[SET_PLAY_SATE] (state, flag) {
state.playState = flag
},
/**
* 设置播放器是大还是小
*/
[SET_FULL_SCREEN] (state, flag) {
if (flag) {
ModalHelper.afterOpen()
} else {
ModalHelper.beforeClose()
}
state.fullScreen = flag
},
/**
* 设置播放列表信息
*/
[SET_AUDIO_LIST] (state, list) {
state.audioList = list
},
/**
* 设置索引
*/
[SET_AUDIO_INDEX] (state, index) {
state.audioIngIndex = index
},
/**
* 设置当前播放列表
*/
[SET_PLAY_LIST] (state, list) {
state.playList = list
},
/**
* 设置当前播放模式
* @param {*} state state数据
* @param {*} mode 模式索引
*/
[SET_AUDIO_MODE] (state, mode) {
state.mode = mode
},
/**
* 设置当前是否显示转盘播放页面
*/
[SET_PLAYING_SHOW] (state, boolean) {
state.playingShow = boolean
}
}
================================================
FILE: musicPlayer/src/store/state.js
================================================
/*
* @Author: 李浩栋
* @Begin: 2019-07-30 16:42:30
* @Update: 2019-10-09 12:15:26
* @Update log: 更新日志
*/
export default {
loginPage: false, // 侧边栏显示与否
icontaiyang: false, // 日间模式
iconyueliang1: true, // 夜间模式
modeText: '夜', // 日夜模式文字信息
loginState: 0, // 登陆状态,初始值为 0 未登录,登陆成功设置为 1
accountUid: 0, // 存取用户 uid
load: true, // 定义搜索展示界面 loading 图标的展示与否
linkPage: 'composite', // 定义搜索展示页的标签导航条应该根据路由信息进行滚动
playState: false, // 是否正在播放,
fullScreen: false, // 是否是全屏展示播放页
audioList: [], // 用来展示播放列表项
playList: [], // 用来存储各种播放模式的列表
mode: 0, // 用来记录当前播放模式 0:列表循环,1:单曲循环 2:随机播放
audioIngIndex: -1, // 正在播放的这一首歌曲索引
playingShow: true, // 是否显示转盘播放页面
offsetLyric: 0, // 设置歌词偏移
level: 0 // 用户等级
}
================================================
FILE: musicPlayer/static/.gitkeep
================================================