├── .babelrc ├── .editorconfig ├── .gitignore ├── README.md ├── build ├── build.js ├── check-versions.js ├── dev-client.js ├── dev-server.js ├── utils.js ├── webpack.base.conf.js ├── webpack.dev.conf.js └── webpack.prod.conf.js ├── config ├── dev.env.js ├── index.js └── prod.env.js ├── index.html ├── less ├── colors.less ├── mixins.less ├── theme-vars.less ├── theme.less └── vars.less ├── npm-debug.log.2541962448 ├── package-lock.json ├── package.json ├── src ├── App.vue ├── assets │ └── logo.png ├── components │ ├── AppSide.vue │ ├── Controls.vue │ ├── Lyric.vue │ └── SongList.vue ├── main.js ├── router.js ├── store │ ├── TencentMusicAPI.php │ ├── api.js │ └── index.js ├── styles │ ├── base.less │ ├── colors.less │ ├── import.less │ ├── mixins.less │ ├── normalize.css │ ├── themes │ │ ├── carbon.less │ │ ├── dark.less │ │ ├── default.less │ │ └── teal.less │ ├── vars.less │ └── zIndex.less └── views │ ├── index.vue │ └── player.vue └── static ├── .gitkeep ├── hot_all.js ├── playlist.js └── vue-animated-list.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-2"], 3 | "plugins": ["transform-runtime"], 4 | "comments": false, 5 | "env": { 6 | "test": { 7 | "plugins": [ "istanbul" ] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-music-qq 2 | 3 | > A Vue.js project for music 4 | ### Use 5 | * vuejs-2.1.7 6 | * vue-cli 7 | * vue-router 8 | * vuex 9 | * muse-ui 10 | 11 | 12 | ## Support 13 | * Chrome 14 | * Firefox 15 | * Mobile browser 16 | 17 | ## Build Setup 18 | 19 | ``` bash 20 | # install dependencies 21 | npm install 22 | 23 | # serve with hot reload at localhost:8080 24 | npm run dev 25 | 26 | # build for production with minification 27 | npm run build 28 | ``` 29 | ## Demo site 30 | 31 | http://weixin.nmict.cn/vue-music-qq/ 32 | 33 | # Conatct 34 | 35 | - Tencent QQ: 342878509 36 | - E-mail: xiongmao1114@163.com 37 | - Github: https://github.com/pluto1114/vue-music-qq 38 | -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | // https://github.com/shelljs/shelljs 2 | require('./check-versions')() 3 | require('shelljs/global') 4 | env.NODE_ENV = 'production' 5 | 6 | var path = require('path') 7 | var config = require('../config') 8 | var ora = require('ora') 9 | var webpack = require('webpack') 10 | var webpackConfig = require('./webpack.prod.conf') 11 | 12 | console.log( 13 | ' Tip:\n' + 14 | ' Built files are meant to be served over an HTTP server.\n' + 15 | ' Opening index.html over file:// won\'t work.\n' 16 | ) 17 | 18 | var spinner = ora('building for production...') 19 | spinner.start() 20 | 21 | var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory) 22 | rm('-rf', assetsPath) 23 | mkdir('-p', assetsPath) 24 | cp('-R', 'static/*', assetsPath) 25 | 26 | webpack(webpackConfig, function (err, stats) { 27 | spinner.stop() 28 | if (err) throw err 29 | process.stdout.write(stats.toString({ 30 | colors: true, 31 | modules: false, 32 | children: false, 33 | chunks: false, 34 | chunkModules: false 35 | }) + '\n') 36 | }) 37 | -------------------------------------------------------------------------------- /build/check-versions.js: -------------------------------------------------------------------------------- 1 | var semver = require('semver') 2 | var chalk = require('chalk') 3 | var packageConfig = require('../package.json') 4 | var exec = function (cmd) { 5 | return require('child_process') 6 | .execSync(cmd).toString().trim() 7 | } 8 | 9 | var versionRequirements = [ 10 | { 11 | name: 'node', 12 | currentVersion: semver.clean(process.version), 13 | versionRequirement: packageConfig.engines.node 14 | }, 15 | { 16 | name: 'npm', 17 | currentVersion: exec('npm --version'), 18 | versionRequirement: packageConfig.engines.npm 19 | } 20 | ] 21 | 22 | module.exports = function () { 23 | var warnings = [] 24 | for (var i = 0; i < versionRequirements.length; i++) { 25 | var mod = versionRequirements[i] 26 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 27 | warnings.push(mod.name + ': ' + 28 | chalk.red(mod.currentVersion) + ' should be ' + 29 | chalk.green(mod.versionRequirement) 30 | ) 31 | } 32 | } 33 | 34 | if (warnings.length) { 35 | console.log('') 36 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 37 | console.log() 38 | for (var i = 0; i < warnings.length; i++) { 39 | var warning = warnings[i] 40 | console.log(' ' + warning) 41 | } 42 | console.log() 43 | process.exit(1) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /build/dev-server.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | var config = require('../config') 3 | if (!process.env.NODE_ENV) process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) 4 | var path = require('path') 5 | var express = require('express') 6 | var webpack = require('webpack') 7 | var opn = require('opn') 8 | var proxyMiddleware = require('http-proxy-middleware') 9 | var webpackConfig = require('./webpack.dev.conf') 10 | 11 | // default port where dev server listens for incoming traffic 12 | var port = process.env.PORT || config.dev.port 13 | // Define HTTP proxies to your custom API backend 14 | // https://github.com/chimurai/http-proxy-middleware 15 | var proxyTable = config.dev.proxyTable 16 | 17 | var app = express() 18 | var compiler = webpack(webpackConfig) 19 | 20 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 21 | publicPath: webpackConfig.output.publicPath, 22 | quiet: true 23 | }) 24 | 25 | var hotMiddleware = require('webpack-hot-middleware')(compiler, { 26 | log: () => {} 27 | }) 28 | // force page reload when html-webpack-plugin template changes 29 | compiler.plugin('compilation', function (compilation) { 30 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { 31 | hotMiddleware.publish({ action: 'reload' }) 32 | cb() 33 | }) 34 | }) 35 | 36 | // proxy api requests 37 | Object.keys(proxyTable).forEach(function (context) { 38 | var options = proxyTable[context] 39 | if (typeof options === 'string') { 40 | options = { target: options } 41 | } 42 | app.use(proxyMiddleware(context, options)) 43 | }) 44 | 45 | // handle fallback for HTML5 history API 46 | app.use(require('connect-history-api-fallback')()) 47 | 48 | // serve webpack bundle output 49 | app.use(devMiddleware) 50 | 51 | // enable hot-reload and state-preserving 52 | // compilation error display 53 | app.use(hotMiddleware) 54 | 55 | // serve pure static assets 56 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 57 | app.use(staticPath, express.static('./static')) 58 | 59 | var uri = 'http://localhost:' + port 60 | 61 | devMiddleware.waitUntilValid(function () { 62 | console.log('> Listening at ' + uri + '\n') 63 | }) 64 | 65 | module.exports = app.listen(port, function (err) { 66 | if (err) { 67 | console.log(err) 68 | return 69 | } 70 | 71 | // when env is testing, don't need open it 72 | if (process.env.NODE_ENV !== 'testing') { 73 | opn(uri) 74 | } 75 | }) 76 | -------------------------------------------------------------------------------- /build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | var assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | // generate loader string to be used with extract text plugin 15 | function generateLoaders (loaders) { 16 | var sourceLoader = loaders.map(function (loader) { 17 | var extraParamChar 18 | if (/\?/.test(loader)) { 19 | loader = loader.replace(/\?/, '-loader?') 20 | extraParamChar = '&' 21 | } else { 22 | loader = loader + '-loader' 23 | extraParamChar = '?' 24 | } 25 | return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '') 26 | }).join('!') 27 | 28 | // Extract CSS when that option is specified 29 | // (which is the case during production build) 30 | if (options.extract) { 31 | return ExtractTextPlugin.extract('vue-style-loader', sourceLoader) 32 | } else { 33 | return ['vue-style-loader', sourceLoader].join('!') 34 | } 35 | } 36 | 37 | // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html 38 | return { 39 | css: generateLoaders(['css']), 40 | postcss: generateLoaders(['css']), 41 | less: generateLoaders(['css', 'less']), 42 | sass: generateLoaders(['css', 'sass?indentedSyntax']), 43 | scss: generateLoaders(['css', 'sass']), 44 | stylus: generateLoaders(['css', 'stylus']), 45 | styl: generateLoaders(['css', 'stylus']) 46 | } 47 | } 48 | 49 | // Generate loaders for standalone style files (outside of .vue) 50 | exports.styleLoaders = function (options) { 51 | var output = [] 52 | var loaders = exports.cssLoaders(options) 53 | for (var extension in loaders) { 54 | var loader = loaders[extension] 55 | output.push({ 56 | test: new RegExp('\\.' + extension + '$'), 57 | loader: loader 58 | }) 59 | } 60 | return output 61 | } 62 | -------------------------------------------------------------------------------- /build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var utils = require('./utils') 4 | var projectRoot = path.resolve(__dirname, '../') 5 | 6 | var env = process.env.NODE_ENV 7 | // check env & config/index.js to decide whether to enable CSS source maps for the 8 | // various preprocessor loaders added to vue-loader at the end of this file 9 | var cssSourceMapDev = (env === 'development' && config.dev.cssSourceMap) 10 | var cssSourceMapProd = (env === 'production' && config.build.productionSourceMap) 11 | var useCssSourceMap = cssSourceMapDev || cssSourceMapProd 12 | 13 | module.exports = { 14 | entry: { 15 | app: './src/main.js' 16 | }, 17 | output: { 18 | path: config.build.assetsRoot, 19 | publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath, 20 | filename: '[name].js' 21 | }, 22 | resolve: { 23 | extensions: ['', '.js', '.vue', '.json'], 24 | fallback: [path.join(__dirname, '../node_modules')], 25 | alias: { 26 | 'vue$': 'vue/dist/vue.common.js', 27 | 'src': path.resolve(__dirname, '../src'), 28 | 'assets': path.resolve(__dirname, '../src/assets'), 29 | 'components': path.resolve(__dirname, '../src/components') 30 | } 31 | }, 32 | resolveLoader: { 33 | fallback: [path.join(__dirname, '../node_modules')] 34 | }, 35 | module: { 36 | loaders: [ 37 | { 38 | test: /\.vue$/, 39 | loader: 'vue' 40 | }, 41 | { 42 | test: /\.js$/, 43 | loader: 'babel', 44 | include: [ 45 | path.join(projectRoot, 'src') 46 | ], 47 | exclude: /node_modules/ 48 | }, 49 | { 50 | test: /\.json$/, 51 | loader: 'json' 52 | }, 53 | { 54 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 55 | loader: 'url', 56 | query: { 57 | limit: 10000, 58 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 59 | } 60 | }, 61 | { 62 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 63 | loader: 'url', 64 | query: { 65 | limit: 10000, 66 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 67 | } 68 | } 69 | ] 70 | }, 71 | vue: { 72 | loaders: utils.cssLoaders({ sourceMap: useCssSourceMap }), 73 | postcss: [ 74 | require('autoprefixer')({ 75 | browsers: ['last 20 versions'] 76 | }) 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var config = require('../config') 2 | var webpack = require('webpack') 3 | var merge = require('webpack-merge') 4 | var utils = require('./utils') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | var FriendlyErrors = require('friendly-errors-webpack-plugin') 8 | 9 | // add hot-reload related code to entry chunks 10 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 11 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 12 | }) 13 | 14 | module.exports = merge(baseWebpackConfig, { 15 | module: { 16 | loaders: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 17 | }, 18 | // eval-source-map is faster for development 19 | devtool: '#eval-source-map', 20 | plugins: [ 21 | new webpack.DefinePlugin({ 22 | 'process.env': config.dev.env 23 | }), 24 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 25 | new webpack.optimize.OccurrenceOrderPlugin(), 26 | new webpack.HotModuleReplacementPlugin(), 27 | new webpack.NoErrorsPlugin(), 28 | // https://github.com/ampedandwired/html-webpack-plugin 29 | new HtmlWebpackPlugin({ 30 | filename: 'index.html', 31 | template: 'index.html', 32 | inject: true 33 | }), 34 | new FriendlyErrors() 35 | ] 36 | }) 37 | -------------------------------------------------------------------------------- /build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseWebpackConfig = require('./webpack.base.conf') 7 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 8 | var HtmlWebpackPlugin = require('html-webpack-plugin') 9 | var env = config.build.env 10 | 11 | var webpackConfig = merge(baseWebpackConfig, { 12 | module: { 13 | loaders: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true }) 14 | }, 15 | devtool: config.build.productionSourceMap ? '#source-map' : false, 16 | output: { 17 | path: config.build.assetsRoot, 18 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 19 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 20 | }, 21 | vue: { 22 | loaders: utils.cssLoaders({ 23 | sourceMap: config.build.productionSourceMap, 24 | extract: true 25 | }) 26 | }, 27 | plugins: [ 28 | // http://vuejs.github.io/vue-loader/en/workflow/production.html 29 | new webpack.DefinePlugin({ 30 | 'process.env': env 31 | }), 32 | new webpack.optimize.UglifyJsPlugin({ 33 | compress: { 34 | warnings: false 35 | } 36 | }), 37 | new webpack.optimize.OccurrenceOrderPlugin(), 38 | // extract css into its own file 39 | new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash].css')), 40 | // generate dist index.html with correct asset hash for caching. 41 | // you can customize output by editing /index.html 42 | // see https://github.com/ampedandwired/html-webpack-plugin 43 | new HtmlWebpackPlugin({ 44 | filename: config.build.index, 45 | template: 'index.html', 46 | inject: true, 47 | minify: { 48 | removeComments: true, 49 | collapseWhitespace: true, 50 | removeAttributeQuotes: true 51 | // more options: 52 | // https://github.com/kangax/html-minifier#options-quick-reference 53 | }, 54 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 55 | chunksSortMode: 'dependency' 56 | }), 57 | // split vendor js into its own file 58 | new webpack.optimize.CommonsChunkPlugin({ 59 | name: 'vendor', 60 | minChunks: function (module, count) { 61 | // any required modules inside node_modules are extracted to vendor 62 | return ( 63 | module.resource && 64 | /\.js$/.test(module.resource) && 65 | module.resource.indexOf( 66 | path.join(__dirname, '../node_modules') 67 | ) === 0 68 | ) 69 | } 70 | }), 71 | // extract webpack runtime and module manifest to its own file in order to 72 | // prevent vendor hash from being updated whenever app bundle is updated 73 | new webpack.optimize.CommonsChunkPlugin({ 74 | name: 'manifest', 75 | chunks: ['vendor'] 76 | }) 77 | ] 78 | }) 79 | 80 | if (config.build.productionGzip) { 81 | var CompressionWebpackPlugin = require('compression-webpack-plugin') 82 | 83 | webpackConfig.plugins.push( 84 | new CompressionWebpackPlugin({ 85 | asset: '[path].gz[query]', 86 | algorithm: 'gzip', 87 | test: new RegExp( 88 | '\\.(' + 89 | config.build.productionGzipExtensions.join('|') + 90 | ')$' 91 | ), 92 | threshold: 10240, 93 | minRatio: 0.8 94 | }) 95 | ) 96 | } 97 | 98 | module.exports = webpackConfig 99 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: './', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'] 18 | }, 19 | dev: { 20 | env: require('./dev.env'), 21 | port: 8080, 22 | assetsSubDirectory: 'static', 23 | assetsPublicPath: '/', 24 | proxyTable: { 25 | '/qq-m-api':{ 26 | target:'http://c.y.qq.com/', 27 | changeOrigin:true, 28 | pathRewrite:{ 29 | '^/qq-m-api':'' 30 | } 31 | } 32 | }, 33 | // CSS Sourcemaps off by default because relative paths are "buggy" 34 | // with this option, according to the CSS-Loader README 35 | // (https://github.com/webpack/css-loader#sourcemaps) 36 | // In our experience, they generally work as expected, 37 | // just be aware of this issue when enabling this option. 38 | cssSourceMap: false 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | vue-music-qq 7 | 8 | 9 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /less/colors.less: -------------------------------------------------------------------------------- 1 | @red50: #ffebee; 2 | @red100: #ffcdd2; 3 | @red200: #ef9a9a; 4 | @red300: #e57373; 5 | @red400: #ef5350; 6 | @red500: #f44336; 7 | @red600: #e53935; 8 | @red700: #d32f2f; 9 | @red800: #c62828; 10 | @red900: #b71c1c; 11 | @redA100: #ff8a80; 12 | @redA200: #ff5252; 13 | @redA400: #ff1744; 14 | @redA700: #d50000; 15 | @red: @red500; 16 | 17 | @pink50: #fce4ec; 18 | @pink100: #f8bbd0; 19 | @pink200: #f48fb1; 20 | @pink300: #f06292; 21 | @pink400: #ec407a; 22 | @pink500: #e91e63; 23 | @pink600: #d81b60; 24 | @pink700: #c2185b; 25 | @pink800: #ad1457; 26 | @pink900: #880e4f; 27 | @pinkA100: #ff80ab; 28 | @pinkA200: #ff4081; 29 | @pinkA400: #f50057; 30 | @pinkA700: #c51162; 31 | @pink: @pink500; 32 | 33 | @purple50: #f3e5f5; 34 | @purple100: #e1bee7; 35 | @purple200: #ce93d8; 36 | @purple300: #ba68c8; 37 | @purple400: #ab47bc; 38 | @purple500: #9c27b0; 39 | @purple600: #8e24aa; 40 | @purple700: #7b1fa2; 41 | @purple800: #6a1b9a; 42 | @purple900: #4a148c; 43 | @purpleA100: #ea80fc; 44 | @purpleA200: #e040fb; 45 | @purpleA400: #d500f9; 46 | @purpleA700: #aa00ff; 47 | @purple: @purple500; 48 | 49 | @deepPurple50: #ede7f6; 50 | @deepPurple100: #d1c4e9; 51 | @deepPurple200: #b39ddb; 52 | @deepPurple300: #9575cd; 53 | @deepPurple400: #7e57c2; 54 | @deepPurple500: #673ab7; 55 | @deepPurple600: #5e35b1; 56 | @deepPurple700: #512da8; 57 | @deepPurple800: #4527a0; 58 | @deepPurple900: #311b92; 59 | @deepPurpleA100: #b388ff; 60 | @deepPurpleA200: #7c4dff; 61 | @deepPurpleA400: #651fff; 62 | @deepPurpleA700: #6200ea; 63 | @deepPurple: @deepPurple500; 64 | 65 | @indigo50: #e8eaf6; 66 | @indigo100: #c5cae9; 67 | @indigo200: #9fa8da; 68 | @indigo300: #7986cb; 69 | @indigo400: #5c6bc0; 70 | @indigo500: #3f51b5; 71 | @indigo600: #3949ab; 72 | @indigo700: #303f9f; 73 | @indigo800: #283593; 74 | @indigo900: #1a237e; 75 | @indigoA100: #8c9eff; 76 | @indigoA200: #536dfe; 77 | @indigoA400: #3d5afe; 78 | @indigoA700: #304ffe; 79 | @indigo: @indigo500; 80 | 81 | @blue50: #e3f2fd; 82 | @blue100: #bbdefb; 83 | @blue200: #90caf9; 84 | @blue300: #64b5f6; 85 | @blue400: #42a5f5; 86 | @blue500: #2196f3; 87 | @blue600: #1e88e5; 88 | @blue700: #1976d2; 89 | @blue800: #1565c0; 90 | @blue900: #0d47a1; 91 | @blueA100: #82b1ff; 92 | @blueA200: #448aff; 93 | @blueA400: #2979ff; 94 | @blueA700: #2962ff; 95 | @blue: @blue500; 96 | 97 | @lightBlue50: #e1f5fe; 98 | @lightBlue100: #b3e5fc; 99 | @lightBlue200: #81d4fa; 100 | @lightBlue300: #4fc3f7; 101 | @lightBlue400: #29b6f6; 102 | @lightBlue500: #03a9f4; 103 | @lightBlue600: #039be5; 104 | @lightBlue700: #0288d1; 105 | @lightBlue800: #0277bd; 106 | @lightBlue900: #01579b; 107 | @lightBlueA100: #80d8ff; 108 | @lightBlueA200: #40c4ff; 109 | @lightBlueA400: #00b0ff; 110 | @lightBlueA700: #0091ea; 111 | @lightBlue: @lightBlue500; 112 | 113 | @cyan50: #e0f7fa; 114 | @cyan100: #b2ebf2; 115 | @cyan200: #80deea; 116 | @cyan300: #4dd0e1; 117 | @cyan400: #26c6da; 118 | @cyan500: #00bcd4; 119 | @cyan600: #00acc1; 120 | @cyan700: #0097a7; 121 | @cyan800: #00838f; 122 | @cyan900: #006064; 123 | @cyanA100: #84ffff; 124 | @cyanA200: #18ffff; 125 | @cyanA400: #00e5ff; 126 | @cyanA700: #00b8d4; 127 | @cyan: @cyan500; 128 | 129 | @teal50: #e0f2f1; 130 | @teal100: #b2dfdb; 131 | @teal200: #80cbc4; 132 | @teal300: #4db6ac; 133 | @teal400: #26a69a; 134 | @teal500: #009688; 135 | @teal600: #00897b; 136 | @teal700: #00796b; 137 | @teal800: #00695c; 138 | @teal900: #004d40; 139 | @tealA100: #a7ffeb; 140 | @tealA200: #64ffda; 141 | @tealA400: #1de9b6; 142 | @tealA700: #00bfa5; 143 | @teal: @teal500; 144 | 145 | @green50: #e8f5e9; 146 | @green100: #c8e6c9; 147 | @green200: #a5d6a7; 148 | @green300: #81c784; 149 | @green400: #66bb6a; 150 | @green500: #4caf50; 151 | @green600: #43a047; 152 | @green700: #388e3c; 153 | @green800: #2e7d32; 154 | @green900: #1b5e20; 155 | @greenA100: #b9f6ca; 156 | @greenA200: #69f0ae; 157 | @greenA400: #00e676; 158 | @greenA700: #00c853; 159 | @green: @green500; 160 | 161 | @lightGreen50: #f1f8e9; 162 | @lightGreen100: #dcedc8; 163 | @lightGreen200: #c5e1a5; 164 | @lightGreen300: #aed581; 165 | @lightGreen400: #9ccc65; 166 | @lightGreen500: #8bc34a; 167 | @lightGreen600: #7cb342; 168 | @lightGreen700: #689f38; 169 | @lightGreen800: #558b2f; 170 | @lightGreen900: #33691e; 171 | @lightGreenA100: #ccff90; 172 | @lightGreenA200: #b2ff59; 173 | @lightGreenA400: #76ff03; 174 | @lightGreenA700: #64dd17; 175 | @lightGreen: @lightGreen500; 176 | 177 | @lime50: #f9fbe7; 178 | @lime100: #f0f4c3; 179 | @lime200: #e6ee9c; 180 | @lime300: #dce775; 181 | @lime400: #d4e157; 182 | @lime500: #cddc39; 183 | @lime600: #c0ca33; 184 | @lime700: #afb42b; 185 | @lime800: #9e9d24; 186 | @lime900: #827717; 187 | @limeA100: #f4ff81; 188 | @limeA200: #eeff41; 189 | @limeA400: #c6ff00; 190 | @limeA700: #aeea00; 191 | @lime: @lime500; 192 | 193 | @yellow50: #fffde7; 194 | @yellow100: #fff9c4; 195 | @yellow200: #fff59d; 196 | @yellow300: #fff176; 197 | @yellow400: #ffee58; 198 | @yellow500: #ffeb3b; 199 | @yellow600: #fdd835; 200 | @yellow700: #fbc02d; 201 | @yellow800: #f9a825; 202 | @yellow900: #f57f17; 203 | @yellowA100: #ffff8d; 204 | @yellowA200: #ffff00; 205 | @yellowA400: #ffea00; 206 | @yellowA700: #ffd600; 207 | @yellow: @yellow500; 208 | 209 | @amber50: #fff8e1; 210 | @amber100: #ffecb3; 211 | @amber200: #ffe082; 212 | @amber300: #ffd54f; 213 | @amber400: #ffca28; 214 | @amber500: #ffc107; 215 | @amber600: #ffb300; 216 | @amber700: #ffa000; 217 | @amber800: #ff8f00; 218 | @amber900: #ff6f00; 219 | @amberA100: #ffe57f; 220 | @amberA200: #ffd740; 221 | @amberA400: #ffc400; 222 | @amberA700: #ffab00; 223 | @amber: @amber500; 224 | 225 | @orange50: #fff3e0; 226 | @orange100: #ffe0b2; 227 | @orange200: #ffcc80; 228 | @orange300: #ffb74d; 229 | @orange400: #ffa726; 230 | @orange500: #ff9800; 231 | @orange600: #fb8c00; 232 | @orange700: #f57c00; 233 | @orange800: #ef6c00; 234 | @orange900: #e65100; 235 | @orangeA100: #ffd180; 236 | @orangeA200: #ffab40; 237 | @orangeA400: #ff9100; 238 | @orangeA700: #ff6d00; 239 | @orange: @orange500; 240 | 241 | @deepOrange50: #fbe9e7; 242 | @deepOrange100: #ffccbc; 243 | @deepOrange200: #ffab91; 244 | @deepOrange300: #ff8a65; 245 | @deepOrange400: #ff7043; 246 | @deepOrange500: #ff5722; 247 | @deepOrange600: #f4511e; 248 | @deepOrange700: #e64a19; 249 | @deepOrange800: #d84315; 250 | @deepOrange900: #bf360c; 251 | @deepOrangeA100: #ff9e80; 252 | @deepOrangeA200: #ff6e40; 253 | @deepOrangeA400: #ff3d00; 254 | @deepOrangeA700: #dd2c00; 255 | @deepOrange: @deepOrange500; 256 | 257 | @brown50: #efebe9; 258 | @brown100: #d7ccc8; 259 | @brown200: #bcaaa4; 260 | @brown300: #a1887f; 261 | @brown400: #8d6e63; 262 | @brown500: #795548; 263 | @brown600: #6d4c41; 264 | @brown700: #5d4037; 265 | @brown800: #4e342e; 266 | @brown900: #3e2723; 267 | @brown: @brown500; 268 | 269 | @blueGrey50: #eceff1; 270 | @blueGrey100: #cfd8dc; 271 | @blueGrey200: #b0bec5; 272 | @blueGrey300: #90a4ae; 273 | @blueGrey400: #78909c; 274 | @blueGrey500: #607d8b; 275 | @blueGrey600: #546e7a; 276 | @blueGrey700: #455a64; 277 | @blueGrey800: #37474f; 278 | @blueGrey900: #263238; 279 | @blueGrey: @blueGrey500; 280 | 281 | @grey50: #fafafa; 282 | @grey100: #f5f5f5; 283 | @grey200: #eeeeee; 284 | @grey300: #e0e0e0; 285 | @grey400: #bdbdbd; 286 | @grey500: #9e9e9e; 287 | @grey600: #757575; 288 | @grey700: #616161; 289 | @grey800: #424242; 290 | @grey900: #212121; 291 | @grey: @grey500; 292 | 293 | @black: #000000; 294 | @white: #ffffff; 295 | 296 | @transparent: rgba(0, 0, 0, 0); 297 | @fullBlack: rgba(0, 0, 0, 1); 298 | @darkBlack: rgba(0, 0, 0, 0.87); 299 | @lightBlack: rgba(0, 0, 0, 0.54); 300 | @minBlack: rgba(0, 0, 0, 0.26); 301 | @faintBlack: rgba(0, 0, 0, 0.12); 302 | @fullWhite: rgba(255, 255, 255, 1); 303 | @darkWhite: rgba(255, 255, 255, 0.87); 304 | @lightWhite: rgba(255, 255, 255, 0.54); 305 | -------------------------------------------------------------------------------- /less/mixins.less: -------------------------------------------------------------------------------- 1 | .transition(@d) { 2 | -webkit-transition-duration: @d; 3 | transition-duration: @d; 4 | } 5 | .delay(@d) { 6 | -webkit-transition-delay: @d; 7 | transition-delay: @d; 8 | } 9 | .transform(@t) { 10 | -webkit-transform: @t; 11 | transform: @t; 12 | } 13 | .transform-origin(@to) { 14 | -webkit-transform-origin: @to; 15 | transform-origin: @to; 16 | } 17 | .translate3d(@x:0, @y:0, @z:0) { 18 | -webkit-transform: translate3d(@x,@y,@z); 19 | transform: translate3d(@x,@y,@z); 20 | } 21 | .animation (@a) { 22 | -webkit-animation: @a; 23 | animation: @a; 24 | } 25 | .scrollable() { 26 | overflow: auto; 27 | -webkit-overflow-scrolling: touch; 28 | } 29 | .flex-shrink(@fs) { 30 | -webkit-box-flex: @fs; 31 | -webkit-flex-shrink: @fs; 32 | -ms-flex: 0 @fs auto; 33 | flex-shrink: @fs; 34 | } 35 | .clearfix() { 36 | &:after, 37 | &:before { 38 | content: " "; 39 | display: table; 40 | } 41 | &:after { 42 | clear: both; 43 | } 44 | } 45 | .hairline(@position, @color) when (@position = top) { 46 | &:before { 47 | content: ''; 48 | position: absolute; 49 | left: 0; 50 | top: 0; 51 | bottom: auto; 52 | right: auto; 53 | height: 1px; 54 | width: 100%; 55 | background-color: @color; 56 | display: block; 57 | z-index: 15; 58 | // .transform-origin(50% 0%); 59 | html.pixel-ratio-2 & { 60 | .transform(scaleY(0.5)); 61 | } 62 | html.pixel-ratio-3 & { 63 | .transform(scaleY(0.33)); 64 | } 65 | } 66 | } 67 | .hairline(@position, @color) when (@position = left) { 68 | &:before { 69 | content: ''; 70 | position: absolute; 71 | left: 0; 72 | top: 0; 73 | bottom: auto; 74 | right: auto; 75 | width: 1px; 76 | height: 100%; 77 | background-color: @color; 78 | display: block; 79 | z-index: 15; 80 | // .transform-origin(0% 50%); 81 | html.pixel-ratio-2 & { 82 | .transform(scaleX(0.5)); 83 | } 84 | html.pixel-ratio-3 & { 85 | .transform(scaleX(0.33)); 86 | } 87 | } 88 | 89 | } 90 | .hairline(@position, @color) when (@position = bottom) { 91 | &:after { 92 | content: ''; 93 | position: absolute; 94 | left: 0; 95 | bottom: 0; 96 | right: auto; 97 | top: auto; 98 | height: 1px; 99 | width: 100%; 100 | background-color: @color; 101 | display: block; 102 | z-index: 15; 103 | html.pixel-ratio-2 & { 104 | .transform(scaleY(0.5)); 105 | } 106 | html.pixel-ratio-3 & { 107 | .transform(scaleY(0.33)); 108 | } 109 | } 110 | } 111 | .hairline(@position, @color) when (@position = right) { 112 | &:after { 113 | content: ''; 114 | position: absolute; 115 | right: 0; 116 | top: 0; 117 | left: auto; 118 | bottom: auto; 119 | width: 1px; 120 | height: 100%; 121 | background-color: @color; 122 | display: block; 123 | z-index: 15; 124 | // .transform-origin(100% 50%); 125 | html.pixel-ratio-2 & { 126 | .transform(scaleX(0.5)); 127 | } 128 | html.pixel-ratio-3 & { 129 | .transform(scaleX(0.33)); 130 | } 131 | } 132 | } 133 | // For right and bottom 134 | .hairline-remove(@position) when not (@position = left) and not (@position = top) { 135 | &:after { 136 | display: none; 137 | } 138 | } 139 | // For left and top 140 | .hairline-remove(@position) when not (@position = right) and not (@position = bottom) { 141 | &:before { 142 | display: none; 143 | } 144 | } 145 | // For right and bottom 146 | .hairline-color(@position, @color) when not (@position = left) and not (@position = top) { 147 | &:after { 148 | background-color: @color; 149 | } 150 | } 151 | // For left and top 152 | .hairline-color(@position, @color) when not (@position = right) and not (@position = bottom) { 153 | &:before { 154 | background-color: @color; 155 | } 156 | } 157 | // Encoded SVG Background 158 | .encoded-svg-background(@svg) { 159 | @url: `encodeURIComponent(@{svg})`; 160 | background-image: url("data:image/svg+xml;charset=utf-8,@{url}"); 161 | } 162 | // Preserve3D 163 | .preserve3d() { 164 | -webkit-transform-style: preserve-3d; 165 | -moz-transform-style: preserve-3d; 166 | -ms-transform-style: preserve-3d; 167 | transform-style: preserve-3d; 168 | } 169 | // Shadow 170 | .depth(@level:1) { 171 | & when (@level = 1) { 172 | box-shadow: rgba(0, 0, 0, 0.117647) 0px 1px 6px, rgba(0, 0, 0, 0.117647) 0px 1px 4px; 173 | } 174 | & when (@level = 2) { 175 | box-shadow: rgba(0, 0, 0, 0.156863) 0px 3px 10px, rgba(0, 0, 0, 0.227451) 0px 3px 10px; 176 | } 177 | & when (@level = 3) { 178 | box-shadow: rgba(0, 0, 0, 0.188235) 0px 10px 30px, rgba(0, 0, 0, 0.227451) 0px 6px 10px; 179 | } 180 | & when (@level = 4) { 181 | box-shadow: rgba(0, 0, 0, 0.247059) 0px 14px 45px, rgba(0, 0, 0, 0.219608) 0px 10px 18px; 182 | } 183 | & when (@level = 5) { 184 | box-shadow: rgba(0, 0, 0, 0.298039) 0px 19px 60px, rgba(0, 0, 0, 0.219608) 0px 15px 20px; 185 | } 186 | } 187 | // Highlighted Links 188 | .active-highlight(@color:rgba(255, 255, 255, 0.15)){ 189 | &:before { 190 | content: ''; 191 | width: 100%; 192 | height: 100%; 193 | position: absolute; 194 | left: 0; 195 | top: 0; 196 | background-color: @color; 197 | background-repeat: no-repeat; 198 | background-position: center; 199 | background-size: 100% 100%; 200 | opacity: 0; 201 | pointer-events: none; 202 | .transition(600ms); 203 | } 204 | &.active-state:before, 205 | html:not(.watch-active-state) &:active:before { 206 | opacity: 1; 207 | .transition(150ms); 208 | } 209 | } 210 | .active-highlight-color(@color) { 211 | &:before { 212 | background-image: -webkit-radial-gradient(center, circle cover, @color 66%, rgba(red(@color),green(@color),blue(@color),0) 66%); 213 | background-image: radial-gradient(circle at center, @color 66%, rgba(red(@color),green(@color),blue(@color),0) 66%); 214 | } 215 | } 216 | // No Scrollbar 217 | .no-scrollbar() { 218 | &::-webkit-scrollbar { 219 | display: none !important; 220 | width: 0 !important; 221 | height: 0 !important; 222 | -webkit-appearance: none; 223 | opacity: 0 !important; 224 | } 225 | } 226 | 227 | 228 | .ellipsis() { 229 | white-space:nowrap; 230 | text-overflow:ellipsis; 231 | overflow:hidden; 232 | word-wrap: break-word; 233 | } 234 | -------------------------------------------------------------------------------- /less/theme-vars.less: -------------------------------------------------------------------------------- 1 | @appbarColor: @primaryColor; 2 | @appbarTextColor: @alternateTextColor; 3 | 4 | @avatarColor: @alternateTextColor; 5 | @avatarBackgroundColor: darken(@alternateTextColor, 26%); 6 | 7 | @badgeColor: @lighterPrimaryColor; 8 | @badgeTextColor: @alternateTextColor; 9 | @badgePrimaryColor: @primaryColor; 10 | @badgePrimaryTextColor: @alternateTextColor; 11 | @badgeSecondaryColor: @accentColor; 12 | @badgeSecondaryTextColor: @alternateTextColor; 13 | 14 | @baseFontFamily: @fontFamily; 15 | @baseTextColor: @textColor; 16 | @baseBackgroundColor: @backgroundColor; 17 | @baseLinkColor: @accentColor; 18 | 19 | @bottomNavBackgroundColor: @dialogBackgroundColor; 20 | @bottomNavShiftBackgroundColor: @primaryColor; 21 | @bottomNavUnselectedColor: @secondaryTextColor; 22 | @bottomNavShiftUnselectedColor: fade(@alternateTextColor, 70%); 23 | @bottomNavSelectedColor: @primaryColor; 24 | @bottomNavShiftSelectedColor: @alternateTextColor; 25 | 26 | @bottomSheetColor: @dialogBackgroundColor; 27 | 28 | @cardBackgroudColor: @backgroundColor; 29 | @cardTitleColor: fade(@textColor, 87%); 30 | @cardSubtitleColor: fade(@textColor, 54%); 31 | @cardMediaColor: @darkWhite; 32 | @cardMediaOverlayContentBackground: @lightBlack; 33 | @cardMediaTitleColor: @darkWhite; 34 | @cardMediaSubtitleColor: @lightWhite; 35 | @cardTextColor: @textColor; 36 | 37 | @checkboxColor: @textColor; 38 | @checkboxTextColor: @textColor; 39 | @checkboxDisabledColor: @disabledColor; 40 | @checkboxCheckedColor: @primaryColor; 41 | 42 | @chipColor: darken(@alternateTextColor, 12%); 43 | @chipHoverColor: rgb(206, 206, 206); 44 | @chipTextColor: fade(@textColor, 87%); 45 | @chipDeleteColor: fade(@textColor, 26%); 46 | @chipHoverDeleteColor: fade(fade(@textColor, 26%), 40%); 47 | 48 | @circularProgressColor: @primaryColor; 49 | 50 | @datePickerColor: @primaryColor; 51 | @datePickerTextColor: @alternateTextColor; 52 | @datePickerCalendarTextColor: @textColor; 53 | @datePickerSelectColor: @primaryColor; 54 | @datePickerSelectTextColor: @alternateTextColor; 55 | @datePickerCalendarYearBackgroundColor: @dialogBackgroundColor; 56 | @datePickerHeaderColor: @primaryColor; 57 | 58 | @dialogBorderColor: @borderColor; 59 | @dialogTitleColor: @textColor; 60 | @dialogBodyColor: fade(@textColor, 60%);; 61 | @dialogColor: @dialogBackgroundColor; 62 | 63 | @dropDownMenuTextColor: @textColor; 64 | @dropDownMenuIconColor: @borderColor; 65 | @dropDownMenuLineColor: @borderColor; 66 | 67 | // flatButton 68 | @flatButtonColor: transparent; 69 | @flatButtonTextColor: @textColor; 70 | @flatButtonPrimaryTextColor: @primaryColor; 71 | @flatButtonSecondaryTextColor: @accentColor; 72 | 73 | // floatButton 74 | @floatButtonColor: @primaryColor; 75 | @floatButtonIconColor: @alternateTextColor; 76 | @floatButtonSecondaryColor: @accentColor; 77 | @floatButtonSecondaryIconColor: @alternateTextColor; 78 | @floatButtonDisabledColor: darken(@alternateTextColor, 12%); 79 | @floatButtonDisabledIconColor: fade(@textColor, 30%); 80 | 81 | @gridListTextColor: @white; 82 | @gridListTitlebarColor: rgba(0, 0, 0, 0.4); 83 | 84 | // circle 85 | @circleColor: @primaryColor; 86 | @circleSecondaryColor: @accentColor; 87 | 88 | @linearProgressColor: @lighterPrimaryColor; 89 | @linearProgressFillColor: @primaryColor; 90 | 91 | // listItem 92 | @listTextColor: @textColor; 93 | @listHoverColor: fade(@listTextColor, 10%); 94 | @listSecondaryTextColor: @secondaryTextColor; 95 | @listLeftIconColor: @grey600; 96 | @listRightIconColor: @grey600; 97 | @listSelectedColor: @primaryColor; 98 | 99 | @menuTextColor: @textColor; 100 | @menuSelectColor: @accentColor; 101 | @menuHoverColor: rgba(0, 0, 0, .1); 102 | @menuDisabledColor: @disabledColor; 103 | @menuLeftIconColor: @grey600; 104 | @menuRightIconColor: @grey600; 105 | 106 | @paginationTextColor: @textColor; 107 | @paginationHoverBackgroundColor: rgba(0, 0, 0, .1); 108 | @paginationActiveBackgroundColor: @primaryColor; 109 | @paginationActiveColor: @white; 110 | @paginationDisabledColor: @disabledColor; 111 | 112 | @paperColor: @textColor; 113 | @paperBackgroundColor: @dialogBackgroundColor; 114 | 115 | @pickerColor: @dialogBackgroundColor; 116 | @pickerTextColor: @secondaryTextColor; 117 | @pickerSelectedTextColor: @textColor; 118 | @pickerBorderColor: @borderColor; 119 | 120 | @popoverColor: @dialogBackgroundColor; 121 | 122 | @popupColor: @dialogBackgroundColor; 123 | 124 | @radioColor: @textColor; 125 | @radioTextColor: @textColor; 126 | @radioDisabledColor: @disabledColor; 127 | @radioCheckedColor: @primaryColor; 128 | 129 | // raisedButton 130 | @raisedButtonColor: @alternateTextColor; 131 | @raisedButtonTextColor: @textColor; 132 | @raisedButtonPrimaryColor: @primaryColor; 133 | @raisedButtonSecondaryColor: @accentColor; 134 | @raisedButtonDisabledColor: darken(@alternateTextColor, 10%); 135 | @raisedButtonDisabledTextColor: fade(@textColor, 30%); 136 | 137 | @refreshControlColor: @primaryColor; 138 | 139 | @sliderTrackColor: @lighterPrimaryColor; 140 | @sliderSelectionColor: @primaryColor; 141 | @sliderDisabledColor: @lighterPrimaryColor; 142 | @sliderZeroColor: @alternateTextColor; 143 | 144 | @snackbarColor: @textColor; 145 | @snackbarTextColor: @alternateTextColor; 146 | 147 | @stepperBackgroundColor: transparent; 148 | @stepperHoverBackgroundColor: fade(@textColor, 6%); 149 | @stepperIconColor: @primaryColor; 150 | @stepperHoveredIconColor: @grey700; 151 | @stepperInactiveIconColor: @grey500; 152 | @stepperTextColor: @textColor; 153 | @stepperNumTextColor: @alternateTextColor; 154 | @stepperDisabledTextColor: @disabledColor; 155 | @stepperConnectorLineColor: @grey400; 156 | 157 | // subHeader 158 | @subHeaderColor: @secondaryTextColor; 159 | 160 | @switchThumbOnColor: @primaryColor; 161 | @switchThumbOffColor: @darkerAccentColor; 162 | @switchThumbDisabledColor: @grey300; 163 | @switchTrackOnColor: fade(@primaryColor, 50%); 164 | @switchTrackOffColor: @lighterPrimaryColor; 165 | @switchTrackDisabledColor: @lighterPrimaryColor; 166 | @switchTextColor: @textColor; 167 | @switchTextDisabledColor: @disabledColor; 168 | 169 | @tableBackgroundColor: @alternateTextColor; 170 | @tableBorderColor: @borderColor; 171 | @tableTextColor: @textColor; 172 | @tableRowSelectedBackgroundColor: @grey100; 173 | @tableRowHoverBackgroundColor: @grey200; 174 | @tableRowStripeBackgroundColor: fade(lighten(@primaryColor, 50%), 40%); 175 | @tableTheadTextColor: @secondaryTextColor; 176 | 177 | @tabsBackgroundColor: @primaryColor; 178 | @tabsLineColor: @accentColor; 179 | @tabsTextColor: fade(@alternateTextColor, 70%); 180 | @tabsSelectedTextColor: @alternateTextColor; 181 | 182 | @textFieldTextColor: @secondaryTextColor; 183 | @textFieldInputColor: @textColor; 184 | @textFieldHintColor: @disabledColor; 185 | @textFieldFocusTextColor: @primaryColor; 186 | @textFieldDisabledTextColor: @disabledColor; 187 | @textFieldErrorTextColor: @red; 188 | @textFieldLineColor: @borderColor; 189 | @textFieldFocusLineColor: @primaryColor; 190 | @textFieldErrorLineColor: @red; 191 | @textFieldDisabledLineColor: @disabledColor; 192 | 193 | @timePickerColor: @alternateTextColor; 194 | @timePickerClockColor: @textColor; 195 | @timePickerClockCircleColor: fade(@darkBlack, 7%); 196 | @timePickerSelectColor: @primaryColor; 197 | @timePickerSelectTextColor: @alternateTextColor; 198 | @timePickerHeaderColor: @primaryColor; 199 | 200 | @toastTextColor: @alternateTextColor; 201 | @toastColor: @textColor; 202 | 203 | @tooltipTextColor: @alternateTextColor; 204 | @tooltipRippleColor: @grey700; 205 | -------------------------------------------------------------------------------- /less/theme.less: -------------------------------------------------------------------------------- 1 | .mu-appbar{ 2 | background-color: @appbarColor; 3 | color: @appbarTextColor; 4 | } 5 | 6 | .mu-avatar { 7 | color: @avatarColor; 8 | background-color: @avatarBackgroundColor; 9 | } 10 | 11 | .mu-badge { 12 | background-color: @badgeColor; 13 | color: @badgeTextColor; 14 | } 15 | 16 | .mu-badge-primary { 17 | background-color: @badgePrimaryColor; 18 | color: @badgePrimaryTextColor; 19 | } 20 | 21 | .mu-badge-secondary { 22 | background-color: @badgeSecondaryColor; 23 | color: @badgeSecondaryTextColor; 24 | } 25 | 26 | body { 27 | background-color: @baseBackgroundColor; 28 | color: @baseTextColor; 29 | font-family: @baseFontFamily; 30 | } 31 | 32 | a { 33 | color: @baseLinkColor; 34 | } 35 | 36 | .mu-bottom-nav { 37 | background-color: @bottomNavBackgroundColor; 38 | } 39 | 40 | .mu-bottom-nav-shift{ 41 | background-color: @bottomNavShiftBackgroundColor; 42 | } 43 | 44 | .mu-buttom-item { 45 | color: @bottomNavUnselectedColor; 46 | .mu-bottom-nav-shift & { 47 | color: @bottomNavShiftUnselectedColor; 48 | } 49 | } 50 | 51 | .mu-bottom-item-active{ 52 | .mu-bottom-item-text { 53 | color: @bottomNavSelectedColor; 54 | .mu-bottom-nav-shift & { 55 | color: @bottomNavShiftSelectedColor; 56 | } 57 | } 58 | .mu-bottom-item-icon { 59 | color: @bottomNavSelectedColor; 60 | .mu-bottom-nav-shift & { 61 | color: @bottomNavShiftSelectedColor; 62 | } 63 | } 64 | } 65 | 66 | .mu-bottom-sheet { 67 | background-color: @bottomSheetColor; 68 | } 69 | 70 | .mu-card { 71 | background-color: @cardBackgroudColor; 72 | } 73 | 74 | .mu-card-header-title{ 75 | .mu-card-title{ 76 | color: @cardTitleColor; 77 | } 78 | .mu-card-sub-title{ 79 | color: @cardSubtitleColor; 80 | } 81 | } 82 | 83 | 84 | .mu-card-media-title { 85 | background-color: @cardMediaOverlayContentBackground; 86 | .mu-card-title { 87 | color: @cardMediaTitleColor; 88 | } 89 | .mu-card-sub-title { 90 | color: @cardMediaSubtitleColor; 91 | } 92 | } 93 | 94 | .mu-card-title-container{ 95 | .mu-card-title{ 96 | color: @cardTitleColor; 97 | } 98 | .mu-card-sub-title{ 99 | color: @cardSubtitleColor; 100 | } 101 | } 102 | 103 | .mu-card-text{ 104 | color: @cardTextColor; 105 | } 106 | 107 | .mu-checkbox { 108 | input[type="checkbox"] { 109 | &:checked { 110 | + .mu-checkbox-wrapper { 111 | .mu-checkbox-icon-uncheck{ 112 | color: @checkboxCheckedColor; 113 | } 114 | .mu-checkbox-ripple-wrapper{ 115 | color: @checkboxCheckedColor; 116 | } 117 | } 118 | 119 | } 120 | } 121 | } 122 | 123 | .mu-checkbox-label { 124 | color: @checkboxTextColor; 125 | .mu-checkbox.disabled & { 126 | color: @checkboxDisabledColor; 127 | } 128 | } 129 | 130 | .mu-checkbox-icon-uncheck { 131 | color: @checkboxColor; 132 | .mu-checkbox.disabled & { 133 | color: @checkboxDisabledColor; 134 | } 135 | } 136 | 137 | .mu-checkbox-icon-checked { 138 | color: @checkboxCheckedColor; 139 | .mu-checkbox.disabled & { 140 | color: @checkboxDisabledColor; 141 | } 142 | } 143 | 144 | .mu-chip { 145 | background-color: @chipColor; 146 | color: @chipTextColor; 147 | &.hover{ 148 | .mu-chip-delete-icon{ 149 | color: @chipHoverDeleteColor; 150 | } 151 | background-color: @chipHoverColor; 152 | cursor: pointer; 153 | } 154 | } 155 | 156 | .mu-chip-delete-icon{ 157 | color: @chipDeleteColor; 158 | } 159 | 160 | .mu-circular-progress-determinate-path{ 161 | stroke: @circularProgressColor; 162 | } 163 | 164 | .mu-calendar { 165 | color: @datePickerCalendarTextColor; 166 | } 167 | 168 | .mu-calendar-year { 169 | background-color: @datePickerCalendarYearBackgroundColor; 170 | } 171 | 172 | 173 | .mu-date-display{ 174 | background-color: @datePickerHeaderColor; 175 | color: @datePickerTextColor; 176 | } 177 | 178 | 179 | .mu-day-button-bg { 180 | background-color: @datePickerSelectColor; 181 | } 182 | 183 | .mu-day-button-text{ 184 | font-weight: 400; 185 | position: relative; 186 | color: @datePickerCalendarTextColor; 187 | .mu-day-button.now & { 188 | color: @datePickerSelectColor; 189 | } 190 | .mu-day-button.hover &, 191 | .mu-day-button.selected &{ 192 | color: @datePickerSelectTextColor; 193 | } 194 | } 195 | 196 | .mu-year-button-text { 197 | color: @datePickerCalendarTextColor; 198 | .mu-year-button.selected &{ 199 | color: @datePickerSelectColor; 200 | } 201 | .mu-year-button.hover &{ 202 | color: @datePickerSelectColor; 203 | } 204 | } 205 | 206 | .mu-dialog { 207 | background-color: @dialogColor; 208 | } 209 | 210 | .mu-dialog-footer, 211 | .mu-dialog-header { 212 | &.scrollable{ 213 | border-bottom-color: @dialogBorderColor; 214 | } 215 | } 216 | 217 | .mu-dialog-title{ 218 | color: @dialogTitleColor; 219 | } 220 | 221 | .mu-dialog-body { 222 | color: @dialogBodyColor 223 | } 224 | 225 | .mu-dropDown-menu-text { 226 | color: @dropDownMenuTextColor; 227 | } 228 | 229 | .mu-dropDown-menu-icon { 230 | color: @dropDownMenuIconColor; 231 | } 232 | 233 | .mu-dropDown-menu-line { 234 | background-color: @dropDownMenuLineColor; 235 | } 236 | 237 | // flatbutton 238 | .mu-flat-button { 239 | color: @flatButtonTextColor; 240 | background-color: @flatButtonColor; 241 | .mu-circle-ripple { 242 | color: @flatButtonTextColor; 243 | } 244 | } 245 | 246 | .mu-flat-button-primary{ 247 | color: @flatButtonPrimaryTextColor; 248 | } 249 | 250 | .mu-flat-button-secondary{ 251 | color: @flatButtonSecondaryTextColor; 252 | } 253 | 254 | .mu-float-button { 255 | background-color: @floatButtonColor; 256 | color: @floatButtonIconColor; 257 | &.disabled{ 258 | color: @floatButtonDisabledIconColor; 259 | cursor: default; 260 | background-color: @floatButtonDisabledColor; 261 | } 262 | &.hover, 263 | &:active{ 264 | .mu-float-button-wrapper { 265 | background-color: fade(@floatButtonIconColor, 30%); 266 | } 267 | } 268 | } 269 | 270 | .mu-float-button-secondary { 271 | background-color: @floatButtonSecondaryColor; 272 | color: @floatButtonSecondaryIconColor; 273 | } 274 | 275 | .mu-grid-tile-titlebar{ 276 | background-color: @gridListTitlebarColor; 277 | } 278 | 279 | .mu-grid-tile-title-container{ 280 | color: @gridListTextColor; 281 | } 282 | 283 | .mu-grid-tile-action { 284 | .mu-icon { 285 | color: @gridListTextColor; 286 | } 287 | } 288 | 289 | 290 | // circle 291 | .mu-circle-spinner{ 292 | border-color: @circleColor; 293 | } 294 | 295 | .mu-circle-secondary { 296 | border-color: @circleSecondaryColor; 297 | } 298 | 299 | .mu-linear-progress{ 300 | background-color: @linearProgressColor; 301 | } 302 | 303 | .mu-linear-progress-indeterminate{ 304 | background-color: @linearProgressFillColor; 305 | } 306 | 307 | .mu-linear-progress-determinate{ 308 | background-color: @linearProgressFillColor; 309 | } 310 | 311 | 312 | // list 313 | .mu-item-wrapper{ 314 | &.hover { 315 | background-color: @listHoverColor; 316 | } 317 | } 318 | .mu-item { 319 | color: @listTextColor; 320 | &.selected { 321 | color: @listSelectedColor; 322 | } 323 | } 324 | 325 | .mu-item-link-icon{ 326 | color: @listRightIconColor; 327 | } 328 | 329 | .mu-item-left{ 330 | color: @listLeftIconColor; 331 | } 332 | 333 | .mu-item-right{ 334 | color: @listRightIconColor; 335 | } 336 | 337 | .mu-item-after{ 338 | color: @listSecondaryTextColor; 339 | } 340 | 341 | .mu-item-text{ 342 | color: @listSecondaryTextColor; 343 | } 344 | 345 | .mu-menu-item-wrapper{ 346 | color: @menuTextColor; 347 | &.active { 348 | color: @menuSelectColor; 349 | } 350 | &.hover { 351 | background-color: @menuHoverColor; 352 | } 353 | &.disabled { 354 | color: @menuDisabledColor; 355 | } 356 | } 357 | 358 | .mu-menu-item-left-icon{ 359 | color: @menuLeftIconColor; 360 | } 361 | 362 | .mu-menu-item-right-icon { 363 | color: @menuRightIconColor; 364 | } 365 | 366 | .mu-pagination-item{ 367 | color: @paginationTextColor; 368 | &.hover { 369 | background-color: @paginationHoverBackgroundColor; 370 | } 371 | &.active { 372 | color: @paginationActiveColor; 373 | background-color: @paginationActiveBackgroundColor; 374 | } 375 | &.disabled { 376 | color: @paginationDisabledColor; 377 | } 378 | } 379 | 380 | .mu-paper { 381 | background-color: @paperBackgroundColor; 382 | color: @paperColor; 383 | } 384 | 385 | .mu-picker{ 386 | background-color: @pickerColor; 387 | } 388 | 389 | .mu-picker-center-highlight { 390 | &::before, 391 | &::after { 392 | background-color: @pickerBorderColor; 393 | } 394 | } 395 | 396 | 397 | .mu-picker-slot.mu-picker-slot-divider { 398 | color: @pickerSelectedTextColor; 399 | } 400 | 401 | .mu-picker-item{ 402 | color: @pickerTextColor; 403 | &.selected { 404 | color: @pickerSelectedTextColor; 405 | } 406 | } 407 | 408 | .mu-popover { 409 | background-color: @popoverColor; 410 | } 411 | 412 | .mu-popup { 413 | background-color: @popupColor; 414 | } 415 | 416 | .mu-radio { 417 | input[type="radio"] { 418 | &:checked { 419 | + .mu-radio-wrapper { 420 | .mu-radio-icon-uncheck{ 421 | color: @radioCheckedColor; 422 | } 423 | .mu-radio-ripple-wrapper{ 424 | color: @radioCheckedColor; 425 | } 426 | } 427 | 428 | } 429 | } 430 | } 431 | 432 | .mu-radio-label { 433 | color: @radioTextColor; 434 | .mu-radio.disabled & { 435 | color: @radioDisabledColor; 436 | } 437 | } 438 | 439 | .mu-radio-icon-uncheck { 440 | color: @radioColor; 441 | .mu-radio.disabled & { 442 | color: @radioDisabledColor; 443 | } 444 | } 445 | 446 | .mu-radio-icon-checked { 447 | color: @radioCheckedColor; 448 | .mu-radio.disabled & { 449 | color: @radioDisabledColor; 450 | } 451 | } 452 | 453 | 454 | 455 | // raisedButton 456 | .mu-raised-button{ 457 | background-color: @raisedButtonColor; 458 | color: @raisedButtonTextColor; 459 | &.hover { 460 | .mu-raised-button-wrapper { 461 | background-color: fade(@raisedButtonTextColor, 10%); 462 | } 463 | } 464 | &.disabled{ 465 | color: @raisedButtonDisabledTextColor; 466 | background-color: @raisedButtonDisabledColor; 467 | } 468 | } 469 | 470 | .mu-raised-button-primary{ 471 | background-color: @raisedButtonPrimaryColor; 472 | } 473 | 474 | .mu-raised-button-secondary{ 475 | background-color: @raisedButtonSecondaryColor; 476 | } 477 | 478 | .mu-refresh-control { 479 | color: @refreshControlColor; 480 | } 481 | 482 | .mu-slider-track { 483 | background-color: @sliderTrackColor; 484 | } 485 | 486 | 487 | .mu-slider-fill{ 488 | background-color: @sliderSelectionColor; 489 | &.disabled { 490 | background-color: @sliderDisabledColor; 491 | } 492 | } 493 | 494 | .mu-slider-thumb{ 495 | background-color: @sliderSelectionColor; 496 | color: @sliderSelectionColor; 497 | .mu-slider.zero &, 498 | .mu-slider.disabled &{ 499 | border-color: @sliderDisabledColor; 500 | color: @sliderDisabledColor; 501 | background-color: @sliderZeroColor; 502 | } 503 | } 504 | 505 | .mu-snackbar { 506 | color: @snackbarTextColor; 507 | background-color: @snackbarColor; 508 | } 509 | 510 | .mu-step-button { 511 | background-color: @stepperBackgroundColor; 512 | &.hover { 513 | background-color: @stepperHoverBackgroundColor 514 | } 515 | } 516 | 517 | .mu-step-connector-line { 518 | border-color: @stepperConnectorLineColor; 519 | } 520 | 521 | .mu-step-content{ 522 | .mu-stepper-vertical & { 523 | border-left: 1px solid @stepperConnectorLineColor; 524 | } 525 | } 526 | 527 | 528 | .mu-step-label{ 529 | color: @stepperTextColor; 530 | &.disabled { 531 | color: @stepperDisabledTextColor; 532 | } 533 | } 534 | 535 | 536 | .mu-step-label-icon { 537 | color: @stepperInactiveIconColor; 538 | .mu-step-label.disabled &{ 539 | color: @stepperInactiveIconColor; 540 | } 541 | .mu-step-label.completed &, 542 | .mu-step-label.active & { 543 | color: @stepperIconColor; 544 | } 545 | } 546 | 547 | .mu-step-label-circle{ 548 | background-color: @stepperInactiveIconColor; 549 | color: @stepperNumTextColor; 550 | .mu-step-label.disabled &{ 551 | background-color: @stepperInactiveIconColor; 552 | } 553 | .mu-step-label.completed &, 554 | .mu-step-label.active & { 555 | background-color: @stepperIconColor; 556 | } 557 | } 558 | 559 | // subheader 560 | .mu-sub-header{ 561 | color: @subHeaderColor; 562 | } 563 | 564 | .mu-switch { 565 | input[type="checkbox"] { 566 | &:checked { 567 | + .mu-switch-wrapper { 568 | .mu-switch-track{ 569 | background-color: @switchTrackOnColor; 570 | } 571 | .mu-switch-thumb{ 572 | background-color: @switchThumbOnColor; 573 | color: @switchThumbOnColor; 574 | } 575 | } 576 | 577 | } 578 | } 579 | &.disabled { 580 | input[type="checkbox"]:checked{ 581 | + .mu-switch-wrapper { 582 | .mu-switch-track{ 583 | background-color: @switchTrackDisabledColor; 584 | } 585 | .mu-switch-thumb{ 586 | background-color: @switchThumbDisabledColor; 587 | } 588 | } 589 | } 590 | } 591 | } 592 | 593 | 594 | .mu-switch-label { 595 | color: @switchTextColor; 596 | .mu-switch.disabled & { 597 | color: @switchTextDisabledColor; 598 | } 599 | } 600 | 601 | .mu-switch-track { 602 | background-color: @switchTrackOffColor; 603 | .mu-switch.disabled & { 604 | background-color: @switchTrackDisabledColor; 605 | } 606 | } 607 | 608 | .mu-switch-thumb { 609 | color: @switchTextColor; 610 | background-color: @switchThumbOffColor; 611 | .mu-switch.disabled & { 612 | background-color: @switchThumbDisabledColor; 613 | } 614 | } 615 | 616 | .mu-table { 617 | background-color: @tableBackgroundColor; 618 | } 619 | 620 | .mu-thead { 621 | border-bottom-color: @tableBorderColor; 622 | } 623 | 624 | .mu-th { 625 | color: @tableTheadTextColor; 626 | } 627 | 628 | .mu-tr { 629 | border-bottom-color: @tableBorderColor; 630 | color: @tableTextColor; 631 | &.selected { 632 | background-color: @tableRowSelectedBackgroundColor; 633 | } 634 | &.hover { 635 | background-color: @tableRowHoverBackgroundColor; 636 | } 637 | &.stripe { 638 | background-color: @tableRowStripeBackgroundColor; 639 | } 640 | 641 | .mu-tfoot & { 642 | border-top-color: @tableBorderColor; 643 | } 644 | } 645 | 646 | .mu-tabs{ 647 | background-color: @tabsBackgroundColor; 648 | } 649 | .mu-tab-link-highlight { 650 | background-color: @tabsLineColor; 651 | } 652 | .mu-tab-link{ 653 | color: @tabsTextColor; 654 | } 655 | .mu-tab-active { 656 | color: @tabsSelectedTextColor; 657 | } 658 | 659 | .mu-text-field{ 660 | color: @textFieldTextColor; 661 | &.focus-state { 662 | color: @textFieldFocusTextColor; 663 | &.error{ 664 | color: @textFieldErrorTextColor; 665 | } 666 | } 667 | &.disabled { 668 | color: @textFieldDisabledTextColor; 669 | } 670 | } 671 | 672 | .mu-text-field-input { 673 | color: @textFieldInputColor; 674 | } 675 | 676 | 677 | .mu-text-field-help { 678 | .mu-text-field.error &{ 679 | color: @textFieldErrorTextColor; 680 | } 681 | } 682 | 683 | .mu-text-field-line { 684 | background-color: @textFieldLineColor; 685 | &.disabled { 686 | border-color: @textFieldDisabledLineColor; 687 | } 688 | } 689 | 690 | .mu-text-field-focus-line{ 691 | background-color: @textFieldFocusLineColor; 692 | &.error { 693 | background-color: @textFieldErrorLineColor; 694 | } 695 | } 696 | 697 | 698 | .mu-text-field-hint { 699 | color: @textFieldHintColor; 700 | } 701 | .mu-text-field-label { 702 | .mu-text-field.has-label &.float { 703 | color: @textFieldHintColor 704 | } 705 | } 706 | 707 | .mu-clock-circle { 708 | background-color: @timePickerClockCircleColor; 709 | } 710 | 711 | .mu-time-display { 712 | background-color: @timePickerHeaderColor; 713 | color: @timePickerColor; 714 | } 715 | 716 | .mu-clock-number{ 717 | &.selected { 718 | background-color: @timePickerSelectColor; 719 | color: @timePickerSelectTextColor; 720 | } 721 | } 722 | 723 | .mu-clock-pointer { 724 | background-color: @timePickerSelectColor; 725 | 726 | } 727 | 728 | .mu-clock-pointer-mark { 729 | background-color: @timePickerSelectTextColor; 730 | border-color: @timePickerSelectColor; 731 | } 732 | 733 | .mu-toast { 734 | background-color: @toastColor; 735 | color: @toastTextColor; 736 | } 737 | 738 | .mu-tooltip{ 739 | color: @tooltipTextColor; 740 | } 741 | 742 | .mu-tooltip-ripple.when-shown { 743 | background-color: @tooltipRippleColor; 744 | } 745 | -------------------------------------------------------------------------------- /less/vars.less: -------------------------------------------------------------------------------- 1 | @import "./colors.less"; 2 | @fontFamily: Roboto, Lato, sans-serif; 3 | 4 | // primary and accent 5 | @primaryColor: @lightBlue; // 主色 6 | @darkerPrimaryColor: @lightBlue700; 7 | @lighterPrimaryColor: @grey400; 8 | @accentColor: @pinkA200; 9 | @darkerAccentColor: @grey100; 10 | @lighterAccentColor: @grey500; 11 | 12 | // textColor or borderColor 13 | @textColor: @darkBlack; 14 | @secondaryTextColor: fade(@fullBlack, 54%); 15 | @alternateTextColor: @white; 16 | @borderColor: fade(@fullBlack, 12%); 17 | @disabledColor: fade(@fullBlack, 38%); 18 | 19 | // background 20 | @backgroundColor: @white; 21 | @statusBarBackgroundColor: @grey300; 22 | @appbarBackgroundColor: @grey100; 23 | @dialogBackgroundColor: @white; // dialogs or cards 24 | 25 | // icon color 26 | @activeIconColor: fade(@fullBlack, 54%); 27 | @inActiveIconColor: fade(@fullBlack, 38%); 28 | 29 | // spaceing 30 | @iconSize: 24px; 31 | @desktopGutter: 24px; 32 | @desktopGutterMore: 32px; 33 | @desktopGutterLess: 16px; 34 | @desktopGutterMini: 8px; 35 | @desktopKeylineIncrement: 64px; 36 | @desktopDropDownMenuItemHeight: 32px; 37 | @desktopDropDownMenuFontSize: 15px; 38 | @desktopDrawerMenuItemHeight: 48px; 39 | @desktopSubheaderHeight: 48px; 40 | @desktopToolbarHeight: 56px; 41 | 42 | // animate 43 | @easeOutFunction: cubic-bezier(0.23, 1, 0.32, 1); 44 | @easeInOutFunction: cubic-bezier(0.445, 0.05, 0.55, 0.95); 45 | -------------------------------------------------------------------------------- /npm-debug.log.2541962448: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pluto1114/vue-music-qq/d95f93cfe0c4fbb7c42540dfffead952f8c1fa57/npm-debug.log.2541962448 -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-music-qq", 3 | "version": "1.0.0", 4 | "description": "A Vue.js project", 5 | "author": "xiongmao1114@163.com ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "node build/dev-server.js", 9 | "build": "node build/build.js" 10 | }, 11 | "dependencies": { 12 | "base64-decode-utils": "0.0.2", 13 | "js-base64": "^2.1.9", 14 | "keycode": "^2.1.7", 15 | "muse-ui": "^2.0.0-rc.5", 16 | "text-encoding": "^0.6.4", 17 | "vue": "^2.1.7", 18 | "vue-resource": "^1.2.0", 19 | "vue-router": "^2.2.0", 20 | "vuex": "^2.1.1" 21 | }, 22 | "devDependencies": { 23 | "autoprefixer": "^6.4.0", 24 | "babel-core": "^6.0.0", 25 | "babel-loader": "^6.0.0", 26 | "babel-plugin-transform-runtime": "^6.0.0", 27 | "babel-preset-es2015": "^6.0.0", 28 | "babel-preset-stage-2": "^6.0.0", 29 | "babel-register": "^6.0.0", 30 | "chalk": "^1.1.3", 31 | "connect-history-api-fallback": "^1.1.0", 32 | "css-loader": "^0.25.0", 33 | "eventsource-polyfill": "^0.9.6", 34 | "express": "^4.13.3", 35 | "extract-text-webpack-plugin": "^1.0.1", 36 | "fastclick": "^1.0.6", 37 | "file-loader": "^0.9.0", 38 | "friendly-errors-webpack-plugin": "^1.1.2", 39 | "function-bind": "^1.0.2", 40 | "html-webpack-plugin": "^2.8.1", 41 | "http-proxy-middleware": "^0.17.2", 42 | "json-loader": "^0.5.4", 43 | "semver": "^5.3.0", 44 | "opn": "^4.0.2", 45 | "ora": "^0.3.0", 46 | "shelljs": "^0.7.4", 47 | "lodash": "^4.15.0", 48 | "postcss-loader": "^1.1.1", 49 | "less": "^2.7.1", 50 | "less-loader": "^2.2.3", 51 | "url-loader": "^0.5.7", 52 | "vue-loader": "^10.0.0", 53 | "vue-style-loader": "^1.0.0", 54 | "vue-template-compiler": "^2.1.0", 55 | "webpack": "^1.13.2", 56 | "webpack-dev-middleware": "^1.8.3", 57 | "webpack-hot-middleware": "^2.12.2", 58 | "webpack-merge": "^0.14.1" 59 | }, 60 | "engines": { 61 | "node": ">= 4.0.0", 62 | "npm": ">= 3.0.0" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 94 | 95 | 148 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pluto1114/vue-music-qq/d95f93cfe0c4fbb7c42540dfffead952f8c1fa57/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/AppSide.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/components/Controls.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /src/components/Lyric.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /src/components/SongList.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import App from './App' 5 | import MuseUI from 'muse-ui' 6 | import 'muse-ui/dist/muse-ui.css' 7 | 8 | import FastClick from 'fastclick' 9 | import router from './router' 10 | import store from './store' 11 | import VueResource from 'vue-resource' 12 | 13 | Vue.use(VueResource) 14 | Vue.use(MuseUI) 15 | 16 | 17 | FastClick.attach(document.body) 18 | /* eslint-disable no-new */ 19 | 20 | new Vue({ 21 | el: '#app', 22 | template: '', 23 | components: { App }, 24 | router, 25 | store 26 | }) 27 | -------------------------------------------------------------------------------- /src/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | 4 | Vue.use(VueRouter) 5 | const router = new VueRouter({ 6 | mode: 'hash', 7 | base: __dirname, 8 | routes: [ 9 | //{ path: '/' }, 10 | { path: '/index',component:require('./views/index')}, 11 | { path: '/player/:albumid/:songid/:songmid', component: require('./views/player') }, 12 | // { path: '/song/:id', component:require('./views/Song') }, 13 | { path: '*', redirect: '/index' } 14 | ] 15 | }) 16 | 17 | export default router 18 | -------------------------------------------------------------------------------- /src/store/TencentMusicAPI.php: -------------------------------------------------------------------------------- 1 | _REFERER); 27 | curl_setopt($curl,CURLOPT_COOKIE,$this->_COOKIE); 28 | curl_setopt($curl,CURLOPT_USERAGENT,$this->_USERAGENT); 29 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 30 | $result=curl_exec($curl); 31 | curl_close($curl); 32 | return $result; 33 | } 34 | // main function 35 | public function search($s,$limit=30,$offset=0,$type=1){ 36 | $url='http://c.y.qq.com/soso/fcgi-bin/search_cp?'; 37 | $data=array( 38 | 'p'=>$offset+1, 39 | 'n'=>$limit, 40 | 'w'=>$s, 41 | 'aggr'=>1, 42 | 'lossless'=>1, 43 | 'cr'=>1, 44 | ); 45 | return substr($this->curl($url.http_build_query($data)),9,-1); 46 | } 47 | public function artist($artist_mid){ 48 | $url='http://c.y.qq.com/v8/fcg-bin/fcg_v8_singer_track_cp.fcg?'; 49 | $data=array( 50 | 'singermid'=>$artist_mid, 51 | 'order'=>'listen', 52 | 'begin'=>0, 53 | 'num'=>30, 54 | ); 55 | return substr($this->curl($url.http_build_query($data)),0,-1); 56 | } 57 | public function album($album_mid){ 58 | $url='http://c.y.qq.com/v8/fcg-bin/fcg_v8_album_info_cp.fcg?'; 59 | $data=array( 60 | 'albummid'=>$album_mid, 61 | ); 62 | return substr($this->curl($url.http_build_query($data)),1); 63 | } 64 | public function detail($song_mid){ 65 | $url='http://c.y.qq.com/v8/fcg-bin/fcg_play_single_song.fcg?'; 66 | $data=array( 67 | 'songmid'=>$song_mid, 68 | 'format'=>'json', 69 | ); 70 | return $this->curl($url.http_build_query($data)); 71 | } 72 | private function genkey(){ 73 | $this->_GUID=rand(1,2147483647)*(microtime())%10000000000; 74 | $data=$this->curl('https://c.y.qq.com/base/fcgi-bin/fcg_musicexpress.fcg?json=3&guid='.$this->_GUID); 75 | $this->_KEY=json_decode(substr($data,13,-2),1)['key']; 76 | //$this->_CDN=json_decode(substr($data,13,-2),1)['sip'][0]; 77 | $this->_CDN='http://dl.stream.qqmusic.qq.com/'; 78 | } 79 | public function url($song_mid){ 80 | self::genkey(); 81 | 82 | $url='http://c.y.qq.com/v8/fcg-bin/fcg_play_single_song.fcg?'; 83 | $data=array( 84 | 'songmid'=>$song_mid, 85 | 'format'=>'json', 86 | ); 87 | $data=$this->curl($url.http_build_query($data)); 88 | $data=json_decode($data,1)['data'][0]['file']; 89 | $type=array( 90 | 'size_320mp3'=>array('M800','mp3'), 91 | 'size_128mp3'=>array('M500','mp3'), 92 | 'size_96aac'=>array('C400','m4a'), 93 | 'size_48aac'=>array('C200','m4a'), 94 | ); 95 | $url=array(); 96 | foreach($type as $key=>$vo){ 97 | if($data[$key])$url[substr($key,5)]=$this->_CDN.$vo[0].$data['media_mid'].'.'.$vo[1]. 98 | '?vkey='.$this->_KEY.'&guid='.$this->_GUID.'&fromtag=30'; 99 | } 100 | return json_encode($url); 101 | } 102 | public function playlist($playlist_id){ 103 | $url='http://c.y.qq.com/qzone/fcg-bin/fcg_ucc_getcdinfo_byids_cp.fcg?'; 104 | $data=array( 105 | 'disstid'=>$playlist_id, 106 | 'utf8'=>1, 107 | 'type'=>1, 108 | ); 109 | return substr($this->curl($url.http_build_query($data)),13,-1); 110 | } 111 | public function lyric($song_mid){ 112 | $url='http://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric.fcg?'; 113 | $data=array( 114 | 'songmid'=>$song_mid, 115 | 'nobase64'=>'1', 116 | ); 117 | return substr($this->curl($url.http_build_query($data)),18,-1); 118 | } 119 | } 120 | 121 | $api = new TencentMusicAPI(); 122 | 123 | # Get data 124 | // $result = $api->search('hello'); 125 | // $result = $api->artist('003CoxJh1zFPpx'); 126 | // $result = $api->detail('001icUif3vTGcO'); 127 | // $result = $api->album('002rBshp4WPAut'); 128 | // $result = $api->playlist('801491460'); 129 | // $result = $api->url('001icUif3vTGcO'); 130 | $result = $api->lyric('001icUif3vTGcO'); 131 | 132 | # return JSON, just use it 133 | var_dump(json_decode($result)); 134 | -------------------------------------------------------------------------------- /src/store/api.js: -------------------------------------------------------------------------------- 1 | 2 | import Vue from 'vue' 3 | import VueResource from 'vue-resource' 4 | var querystring = require('querystring'); 5 | 6 | Vue.use(VueResource) 7 | 8 | //Vue.http.options.emulateJSON = true; 9 | var qqAPI={ 10 | 11 | 12 | album: { 13 | url: 'https://c.y.qq.com/v8/fcg-bin/fcg_v8_album_info_cp.fcg', 14 | params: (id) => { 15 | return { 16 | albummid: id, 17 | g_tk: 5381, 18 | loginUin: 0, 19 | hostUin: 0, 20 | format: 'jsonp', 21 | inCharset: 'utf8', 22 | outCharset: 'utf-8', 23 | notice: 0, 24 | platform: 'yqq', 25 | needNewCode: 0 26 | } 27 | }, 28 | 29 | }, 30 | song_info: { 31 | url: '/qq-m-api/v8/fcg-bin/fcg_play_single_song.fcg', 32 | params: (mid) => { 33 | return { 34 | 'songmid':mid, 35 | 'format':'json', 36 | } 37 | }, 38 | 39 | }, 40 | search: { 41 | url: 'http://c.y.qq.com/soso/fcgi-bin/search_cp?', 42 | params: (key) => { 43 | return { 44 | 'p':1, 45 | 'n':15, 46 | 'w':key, 47 | 'aggr':1, 48 | 'lossless':1, 49 | 'cr':1, 50 | } 51 | } 52 | 53 | }, 54 | hotkey: { 55 | url: 'https://c.y.qq.com/splcloud/fcgi-bin/gethotkey.fcg', 56 | params: () => { 57 | return { 58 | g_tk: 5381, 59 | loginUin: 0, 60 | hostUin: 0, 61 | format: 'jsonp', 62 | jsonp: 'jsonpCallback', 63 | inCharset: 'utf8', 64 | outCharset: 'utf-8', 65 | notice: 0, 66 | platform: 'yqq', 67 | needNewCode: 0 68 | } 69 | }, 70 | 71 | }, 72 | 73 | lyric: { 74 | url: 'https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric.fcg', 75 | params: (id) => { 76 | return { 77 | nobase64:1, 78 | musicid:id, 79 | songtype:0 80 | } 81 | }, 82 | 83 | }, 84 | 85 | 86 | 87 | } 88 | 89 | export function search (word) { 90 | var p=Vue.http.jsonp(qqAPI.search.url,{params:qqAPI.search.params(word),jsonp: 'jsonpCallback'}); 91 | console.log(qqAPI.search.url+querystring.stringify(qqAPI.search.params(word))) 92 | p.then(resp => { 93 | console.log(resp.data); 94 | }, resp => { 95 | console.log("request error"); 96 | }); 97 | return p; 98 | } 99 | 100 | export function fetchSongInfo (song_mid) { 101 | var p=Vue.http.get(qqAPI.song_info.url,{params:qqAPI.song_info.params(song_mid)}); 102 | //var p=Vue.http.get("/qq-m-api/v8/fcg-bin/fcg_play_single_song.fcg?songmid=001Ud2bQ0u61uC&format=json"); 103 | console.log(qqAPI.song_info.url+'?'+querystring.stringify(qqAPI.song_info.params(song_mid))) 104 | p.then(resp => { 105 | console.log(resp.data); 106 | }, resp => { 107 | console.log("request error"); 108 | }); 109 | return p; 110 | } 111 | 112 | export function fetchHotkey () { 113 | var p=Vue.http.jsonp(qqAPI.hotkey.url,qqAPI.hotkey.params()); 114 | p.then(resp => { 115 | console.log(resp.data); 116 | }, resp => { 117 | console.log("request error"); 118 | }); 119 | return p; 120 | } 121 | export function fetchAlbum (albummid) { 122 | var p=Vue.http.jsonp(qqAPI.album.url,{params:qqAPI.album.params(albummid),jsonp: 'jsonpCallback',}); 123 | p.then(resp => { 124 | console.log(resp.data); 125 | }, resp => { 126 | console.log("request error"); 127 | }); 128 | return p; 129 | } 130 | 131 | export function fetchLyric (songid) { 132 | var p=Vue.http.jsonp('https://api.darlin.me/music/lyric/'+songid+'/',{params:qqAPI.lyric.params(songid),jsonp:'callback'}); 133 | p.then(resp => { 134 | console.log(resp); 135 | }, resp => { 136 | console.log(resp); 137 | console.log("request error"); 138 | }); 139 | return p; 140 | } 141 | export function fetchHitAll () { 142 | var p=Vue.http.jsonp(baseListUrl+'/musicbox/shop/v3/data/hit/hit_all.js'); 143 | p.then(resp=>{ 144 | console.log(resp.data); 145 | },resp=>{ 146 | console.log("request error"); 147 | }); 148 | return p; 149 | } 150 | 151 | export function fetchHitNewSong () { 152 | var p=Vue.http.jsonp(baseListUrl+'/musicbox/shop/v3/data/hit/hit_newsong.js'); 153 | p.then(resp=>{ 154 | console.log(resp.data); 155 | },resp=>{ 156 | console.log("request error"); 157 | }); 158 | return p; 159 | } -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import {fetchSongInfo,fetchAlbum,fetchLyric,search} from '../store/api' 4 | import _ from 'lodash' 5 | Vue.use(Vuex) 6 | const store = new Vuex.Store({ 7 | state: { 8 | hisSongArr: localStorage.hisSongArr ? JSON.parse(localStorage.hisSongArr) : [], 9 | lyricArr: [], 10 | lrcTimeArr: [], 11 | playing:false, 12 | audio:new Audio(), 13 | currentTime:0, 14 | lrcCurIndex:0 15 | }, 16 | getters: { 17 | 18 | }, 19 | actions: { 20 | FETCH_SONG_LIST(context, word) { 21 | let p = search(word); 22 | return p; 23 | }, 24 | FETCH_SONG_INFO(context, song_mid) { 25 | let p = fetchSongInfo(song_mid); 26 | console.log("p",p) 27 | return p; 28 | }, 29 | FETCH_LYRIC(context, music_id) { 30 | let p = fetchLyric(music_id); 31 | return p; 32 | }, 33 | 34 | }, 35 | mutations: { 36 | 37 | addHisSong(state, payload) { 38 | 39 | state.hisSongArr.unshift(payload.song); 40 | 41 | if (state.hisSongArr.length > 10) { 42 | state.hisSongArr = state.hisSongArr.slice(0, 10); 43 | } 44 | 45 | localStorage.hisSongArr = JSON.stringify(state.hisSongArr); 46 | }, 47 | 48 | loadLyric(state, payload) { 49 | state.lyricArr = payload.lyricArr; 50 | state.lrcTimeArr=_.map(state.lyricArr,'time'); 51 | }, 52 | play(state){ 53 | state.playing=true; 54 | state.audio.play(); 55 | }, 56 | pause(state){ 57 | state.playing=false; 58 | state.audio.pause(); 59 | }, 60 | changePlayPos(state,time){ 61 | state.audio.currentTime=time; 62 | }, 63 | changeCurrentTime(state,currentTime){ 64 | state.currentTime=currentTime; 65 | state.lrcCurIndex=_.sortedIndex(state.lrcTimeArr, currentTime); 66 | for (var i = 0; i < state.lyricArr.length; i++) { 67 | state.lyricArr[i].selected = false; 68 | } 69 | if (state.lrcCurIndex > 0) { 70 | state.lyricArr[state.lrcCurIndex - 1].selected = true; 71 | } 72 | 73 | }, 74 | } 75 | 76 | }); 77 | 78 | 79 | export default store 80 | -------------------------------------------------------------------------------- /src/styles/base.less: -------------------------------------------------------------------------------- 1 | @import "./normalize.css"; 2 | @import "./vars.less"; 3 | *, 4 | *:before, 5 | *:after { 6 | box-sizing: border-box; 7 | } 8 | html{ 9 | font-size: 62.5%; 10 | } 11 | 12 | body{ 13 | font-family: @fontFamily; 14 | line-height: 1.5; 15 | font-size: 14px; 16 | font-weight: 400; 17 | width: 100%; 18 | -webkit-tap-highlight-color:rgba(0, 0, 0, 0); 19 | background-color: @backgroundColor; 20 | color: @textColor; 21 | } 22 | 23 | body,html{ 24 | overflow-x:hidden; 25 | overflow-y: auto; 26 | } 27 | 28 | pre{ 29 | white-space: pre-wrap; 30 | word-break: break-all; 31 | margin: 0; 32 | } 33 | 34 | a{ 35 | text-decoration: none; 36 | color: @accentColor; 37 | user-select: none; 38 | -webkit-user-select: none; 39 | } 40 | -------------------------------------------------------------------------------- /src/styles/colors.less: -------------------------------------------------------------------------------- 1 | @red50: #ffebee; 2 | @red100: #ffcdd2; 3 | @red200: #ef9a9a; 4 | @red300: #e57373; 5 | @red400: #ef5350; 6 | @red500: #f44336; 7 | @red600: #e53935; 8 | @red700: #d32f2f; 9 | @red800: #c62828; 10 | @red900: #b71c1c; 11 | @redA100: #ff8a80; 12 | @redA200: #ff5252; 13 | @redA400: #ff1744; 14 | @redA700: #d50000; 15 | @red: @red500; 16 | 17 | @pink50: #fce4ec; 18 | @pink100: #f8bbd0; 19 | @pink200: #f48fb1; 20 | @pink300: #f06292; 21 | @pink400: #ec407a; 22 | @pink500: #e91e63; 23 | @pink600: #d81b60; 24 | @pink700: #c2185b; 25 | @pink800: #ad1457; 26 | @pink900: #880e4f; 27 | @pinkA100: #ff80ab; 28 | @pinkA200: #ff4081; 29 | @pinkA400: #f50057; 30 | @pinkA700: #c51162; 31 | @pink: @pink500; 32 | 33 | @purple50: #f3e5f5; 34 | @purple100: #e1bee7; 35 | @purple200: #ce93d8; 36 | @purple300: #ba68c8; 37 | @purple400: #ab47bc; 38 | @purple500: #9c27b0; 39 | @purple600: #8e24aa; 40 | @purple700: #7b1fa2; 41 | @purple800: #6a1b9a; 42 | @purple900: #4a148c; 43 | @purpleA100: #ea80fc; 44 | @purpleA200: #e040fb; 45 | @purpleA400: #d500f9; 46 | @purpleA700: #aa00ff; 47 | @purple: @purple500; 48 | 49 | @deepPurple50: #ede7f6; 50 | @deepPurple100: #d1c4e9; 51 | @deepPurple200: #b39ddb; 52 | @deepPurple300: #9575cd; 53 | @deepPurple400: #7e57c2; 54 | @deepPurple500: #673ab7; 55 | @deepPurple600: #5e35b1; 56 | @deepPurple700: #512da8; 57 | @deepPurple800: #4527a0; 58 | @deepPurple900: #311b92; 59 | @deepPurpleA100: #b388ff; 60 | @deepPurpleA200: #7c4dff; 61 | @deepPurpleA400: #651fff; 62 | @deepPurpleA700: #6200ea; 63 | @deepPurple: @deepPurple500; 64 | 65 | @indigo50: #e8eaf6; 66 | @indigo100: #c5cae9; 67 | @indigo200: #9fa8da; 68 | @indigo300: #7986cb; 69 | @indigo400: #5c6bc0; 70 | @indigo500: #3f51b5; 71 | @indigo600: #3949ab; 72 | @indigo700: #303f9f; 73 | @indigo800: #283593; 74 | @indigo900: #1a237e; 75 | @indigoA100: #8c9eff; 76 | @indigoA200: #536dfe; 77 | @indigoA400: #3d5afe; 78 | @indigoA700: #304ffe; 79 | @indigo: @indigo500; 80 | 81 | @blue50: #e3f2fd; 82 | @blue100: #bbdefb; 83 | @blue200: #90caf9; 84 | @blue300: #64b5f6; 85 | @blue400: #42a5f5; 86 | @blue500: #2196f3; 87 | @blue600: #1e88e5; 88 | @blue700: #1976d2; 89 | @blue800: #1565c0; 90 | @blue900: #0d47a1; 91 | @blueA100: #82b1ff; 92 | @blueA200: #448aff; 93 | @blueA400: #2979ff; 94 | @blueA700: #2962ff; 95 | @blue: @blue500; 96 | 97 | @lightBlue50: #e1f5fe; 98 | @lightBlue100: #b3e5fc; 99 | @lightBlue200: #81d4fa; 100 | @lightBlue300: #4fc3f7; 101 | @lightBlue400: #29b6f6; 102 | @lightBlue500: #03a9f4; 103 | @lightBlue600: #039be5; 104 | @lightBlue700: #0288d1; 105 | @lightBlue800: #0277bd; 106 | @lightBlue900: #01579b; 107 | @lightBlueA100: #80d8ff; 108 | @lightBlueA200: #40c4ff; 109 | @lightBlueA400: #00b0ff; 110 | @lightBlueA700: #0091ea; 111 | @lightBlue: @lightBlue500; 112 | 113 | @cyan50: #e0f7fa; 114 | @cyan100: #b2ebf2; 115 | @cyan200: #80deea; 116 | @cyan300: #4dd0e1; 117 | @cyan400: #26c6da; 118 | @cyan500: #00bcd4; 119 | @cyan600: #00acc1; 120 | @cyan700: #0097a7; 121 | @cyan800: #00838f; 122 | @cyan900: #006064; 123 | @cyanA100: #84ffff; 124 | @cyanA200: #18ffff; 125 | @cyanA400: #00e5ff; 126 | @cyanA700: #00b8d4; 127 | @cyan: @cyan500; 128 | 129 | @teal50: #e0f2f1; 130 | @teal100: #b2dfdb; 131 | @teal200: #80cbc4; 132 | @teal300: #4db6ac; 133 | @teal400: #26a69a; 134 | @teal500: #009688; 135 | @teal600: #00897b; 136 | @teal700: #00796b; 137 | @teal800: #00695c; 138 | @teal900: #004d40; 139 | @tealA100: #a7ffeb; 140 | @tealA200: #64ffda; 141 | @tealA400: #1de9b6; 142 | @tealA700: #00bfa5; 143 | @teal: @teal500; 144 | 145 | @green50: #e8f5e9; 146 | @green100: #c8e6c9; 147 | @green200: #a5d6a7; 148 | @green300: #81c784; 149 | @green400: #66bb6a; 150 | @green500: #4caf50; 151 | @green600: #43a047; 152 | @green700: #388e3c; 153 | @green800: #2e7d32; 154 | @green900: #1b5e20; 155 | @greenA100: #b9f6ca; 156 | @greenA200: #69f0ae; 157 | @greenA400: #00e676; 158 | @greenA700: #00c853; 159 | @green: @green500; 160 | 161 | @lightGreen50: #f1f8e9; 162 | @lightGreen100: #dcedc8; 163 | @lightGreen200: #c5e1a5; 164 | @lightGreen300: #aed581; 165 | @lightGreen400: #9ccc65; 166 | @lightGreen500: #8bc34a; 167 | @lightGreen600: #7cb342; 168 | @lightGreen700: #689f38; 169 | @lightGreen800: #558b2f; 170 | @lightGreen900: #33691e; 171 | @lightGreenA100: #ccff90; 172 | @lightGreenA200: #b2ff59; 173 | @lightGreenA400: #76ff03; 174 | @lightGreenA700: #64dd17; 175 | @lightGreen: @lightGreen500; 176 | 177 | @lime50: #f9fbe7; 178 | @lime100: #f0f4c3; 179 | @lime200: #e6ee9c; 180 | @lime300: #dce775; 181 | @lime400: #d4e157; 182 | @lime500: #cddc39; 183 | @lime600: #c0ca33; 184 | @lime700: #afb42b; 185 | @lime800: #9e9d24; 186 | @lime900: #827717; 187 | @limeA100: #f4ff81; 188 | @limeA200: #eeff41; 189 | @limeA400: #c6ff00; 190 | @limeA700: #aeea00; 191 | @lime: @lime500; 192 | 193 | @yellow50: #fffde7; 194 | @yellow100: #fff9c4; 195 | @yellow200: #fff59d; 196 | @yellow300: #fff176; 197 | @yellow400: #ffee58; 198 | @yellow500: #ffeb3b; 199 | @yellow600: #fdd835; 200 | @yellow700: #fbc02d; 201 | @yellow800: #f9a825; 202 | @yellow900: #f57f17; 203 | @yellowA100: #ffff8d; 204 | @yellowA200: #ffff00; 205 | @yellowA400: #ffea00; 206 | @yellowA700: #ffd600; 207 | @yellow: @yellow500; 208 | 209 | @amber50: #fff8e1; 210 | @amber100: #ffecb3; 211 | @amber200: #ffe082; 212 | @amber300: #ffd54f; 213 | @amber400: #ffca28; 214 | @amber500: #ffc107; 215 | @amber600: #ffb300; 216 | @amber700: #ffa000; 217 | @amber800: #ff8f00; 218 | @amber900: #ff6f00; 219 | @amberA100: #ffe57f; 220 | @amberA200: #ffd740; 221 | @amberA400: #ffc400; 222 | @amberA700: #ffab00; 223 | @amber: @amber500; 224 | 225 | @orange50: #fff3e0; 226 | @orange100: #ffe0b2; 227 | @orange200: #ffcc80; 228 | @orange300: #ffb74d; 229 | @orange400: #ffa726; 230 | @orange500: #ff9800; 231 | @orange600: #fb8c00; 232 | @orange700: #f57c00; 233 | @orange800: #ef6c00; 234 | @orange900: #e65100; 235 | @orangeA100: #ffd180; 236 | @orangeA200: #ffab40; 237 | @orangeA400: #ff9100; 238 | @orangeA700: #ff6d00; 239 | @orange: @orange500; 240 | 241 | @deepOrange50: #fbe9e7; 242 | @deepOrange100: #ffccbc; 243 | @deepOrange200: #ffab91; 244 | @deepOrange300: #ff8a65; 245 | @deepOrange400: #ff7043; 246 | @deepOrange500: #ff5722; 247 | @deepOrange600: #f4511e; 248 | @deepOrange700: #e64a19; 249 | @deepOrange800: #d84315; 250 | @deepOrange900: #bf360c; 251 | @deepOrangeA100: #ff9e80; 252 | @deepOrangeA200: #ff6e40; 253 | @deepOrangeA400: #ff3d00; 254 | @deepOrangeA700: #dd2c00; 255 | @deepOrange: @deepOrange500; 256 | 257 | @brown50: #efebe9; 258 | @brown100: #d7ccc8; 259 | @brown200: #bcaaa4; 260 | @brown300: #a1887f; 261 | @brown400: #8d6e63; 262 | @brown500: #795548; 263 | @brown600: #6d4c41; 264 | @brown700: #5d4037; 265 | @brown800: #4e342e; 266 | @brown900: #3e2723; 267 | @brown: @brown500; 268 | 269 | @blueGrey50: #eceff1; 270 | @blueGrey100: #cfd8dc; 271 | @blueGrey200: #b0bec5; 272 | @blueGrey300: #90a4ae; 273 | @blueGrey400: #78909c; 274 | @blueGrey500: #607d8b; 275 | @blueGrey600: #546e7a; 276 | @blueGrey700: #455a64; 277 | @blueGrey800: #37474f; 278 | @blueGrey900: #263238; 279 | @blueGrey: @blueGrey500; 280 | 281 | @grey50: #fafafa; 282 | @grey100: #f5f5f5; 283 | @grey200: #eeeeee; 284 | @grey300: #e0e0e0; 285 | @grey400: #bdbdbd; 286 | @grey500: #9e9e9e; 287 | @grey600: #757575; 288 | @grey700: #616161; 289 | @grey800: #424242; 290 | @grey900: #212121; 291 | @grey: @grey500; 292 | 293 | @black: #000000; 294 | @white: #ffffff; 295 | 296 | @transparent: rgba(0, 0, 0, 0); 297 | @fullBlack: rgba(0, 0, 0, 1); 298 | @darkBlack: rgba(0, 0, 0, 0.87); 299 | @lightBlack: rgba(0, 0, 0, 0.54); 300 | @minBlack: rgba(0, 0, 0, 0.26); 301 | @faintBlack: rgba(0, 0, 0, 0.12); 302 | @fullWhite: rgba(255, 255, 255, 1); 303 | @darkWhite: rgba(255, 255, 255, 0.87); 304 | @lightWhite: rgba(255, 255, 255, 0.54); 305 | -------------------------------------------------------------------------------- /src/styles/import.less: -------------------------------------------------------------------------------- 1 | @import "./vars.less"; 2 | @import "./mixins.less"; 3 | -------------------------------------------------------------------------------- /src/styles/mixins.less: -------------------------------------------------------------------------------- 1 | .transition(@d) { 2 | -webkit-transition-duration: @d; 3 | transition-duration: @d; 4 | } 5 | .delay(@d) { 6 | -webkit-transition-delay: @d; 7 | transition-delay: @d; 8 | } 9 | .transform(@t) { 10 | -webkit-transform: @t; 11 | transform: @t; 12 | } 13 | .transform-origin(@to) { 14 | -webkit-transform-origin: @to; 15 | transform-origin: @to; 16 | } 17 | .translate3d(@x:0, @y:0, @z:0) { 18 | -webkit-transform: translate3d(@x,@y,@z); 19 | transform: translate3d(@x,@y,@z); 20 | } 21 | .animation (@a) { 22 | -webkit-animation: @a; 23 | animation: @a; 24 | } 25 | .scrollable() { 26 | overflow: auto; 27 | -webkit-overflow-scrolling: touch; 28 | } 29 | .flex-shrink(@fs) { 30 | -webkit-box-flex: @fs; 31 | -webkit-flex-shrink: @fs; 32 | -ms-flex: 0 @fs auto; 33 | flex-shrink: @fs; 34 | } 35 | .clearfix() { 36 | &:after, 37 | &:before { 38 | content: " "; 39 | display: table; 40 | } 41 | &:after { 42 | clear: both; 43 | } 44 | } 45 | .hairline(@position, @color) when (@position = top) { 46 | &:before { 47 | content: ''; 48 | position: absolute; 49 | left: 0; 50 | top: 0; 51 | bottom: auto; 52 | right: auto; 53 | height: 1px; 54 | width: 100%; 55 | background-color: @color; 56 | display: block; 57 | z-index: 15; 58 | // .transform-origin(50% 0%); 59 | html.pixel-ratio-2 & { 60 | .transform(scaleY(0.5)); 61 | } 62 | html.pixel-ratio-3 & { 63 | .transform(scaleY(0.33)); 64 | } 65 | } 66 | } 67 | .hairline(@position, @color) when (@position = left) { 68 | &:before { 69 | content: ''; 70 | position: absolute; 71 | left: 0; 72 | top: 0; 73 | bottom: auto; 74 | right: auto; 75 | width: 1px; 76 | height: 100%; 77 | background-color: @color; 78 | display: block; 79 | z-index: 15; 80 | // .transform-origin(0% 50%); 81 | html.pixel-ratio-2 & { 82 | .transform(scaleX(0.5)); 83 | } 84 | html.pixel-ratio-3 & { 85 | .transform(scaleX(0.33)); 86 | } 87 | } 88 | 89 | } 90 | .hairline(@position, @color) when (@position = bottom) { 91 | &:after { 92 | content: ''; 93 | position: absolute; 94 | left: 0; 95 | bottom: 0; 96 | right: auto; 97 | top: auto; 98 | height: 1px; 99 | width: 100%; 100 | background-color: @color; 101 | display: block; 102 | z-index: 15; 103 | html.pixel-ratio-2 & { 104 | .transform(scaleY(0.5)); 105 | } 106 | html.pixel-ratio-3 & { 107 | .transform(scaleY(0.33)); 108 | } 109 | } 110 | } 111 | .hairline(@position, @color) when (@position = right) { 112 | &:after { 113 | content: ''; 114 | position: absolute; 115 | right: 0; 116 | top: 0; 117 | left: auto; 118 | bottom: auto; 119 | width: 1px; 120 | height: 100%; 121 | background-color: @color; 122 | display: block; 123 | z-index: 15; 124 | // .transform-origin(100% 50%); 125 | html.pixel-ratio-2 & { 126 | .transform(scaleX(0.5)); 127 | } 128 | html.pixel-ratio-3 & { 129 | .transform(scaleX(0.33)); 130 | } 131 | } 132 | } 133 | // For right and bottom 134 | .hairline-remove(@position) when not (@position = left) and not (@position = top) { 135 | &:after { 136 | display: none; 137 | } 138 | } 139 | // For left and top 140 | .hairline-remove(@position) when not (@position = right) and not (@position = bottom) { 141 | &:before { 142 | display: none; 143 | } 144 | } 145 | // For right and bottom 146 | .hairline-color(@position, @color) when not (@position = left) and not (@position = top) { 147 | &:after { 148 | background-color: @color; 149 | } 150 | } 151 | // For left and top 152 | .hairline-color(@position, @color) when not (@position = right) and not (@position = bottom) { 153 | &:before { 154 | background-color: @color; 155 | } 156 | } 157 | // Encoded SVG Background 158 | .encoded-svg-background(@svg) { 159 | @url: `encodeURIComponent(@{svg})`; 160 | background-image: url("data:image/svg+xml;charset=utf-8,@{url}"); 161 | } 162 | // Preserve3D 163 | .preserve3d() { 164 | -webkit-transform-style: preserve-3d; 165 | -moz-transform-style: preserve-3d; 166 | -ms-transform-style: preserve-3d; 167 | transform-style: preserve-3d; 168 | } 169 | // Shadow 170 | .depth(@level:1) { 171 | & when (@level = 1) { 172 | box-shadow: rgba(0, 0, 0, 0.117647) 0px 1px 6px, rgba(0, 0, 0, 0.117647) 0px 1px 4px; 173 | } 174 | & when (@level = 2) { 175 | box-shadow: rgba(0, 0, 0, 0.156863) 0px 3px 10px, rgba(0, 0, 0, 0.227451) 0px 3px 10px; 176 | } 177 | & when (@level = 3) { 178 | box-shadow: rgba(0, 0, 0, 0.188235) 0px 10px 30px, rgba(0, 0, 0, 0.227451) 0px 6px 10px; 179 | } 180 | & when (@level = 4) { 181 | box-shadow: rgba(0, 0, 0, 0.247059) 0px 14px 45px, rgba(0, 0, 0, 0.219608) 0px 10px 18px; 182 | } 183 | & when (@level = 5) { 184 | box-shadow: rgba(0, 0, 0, 0.298039) 0px 19px 60px, rgba(0, 0, 0, 0.219608) 0px 15px 20px; 185 | } 186 | } 187 | // Highlighted Links 188 | .active-highlight(@color:rgba(255, 255, 255, 0.15)){ 189 | &:before { 190 | content: ''; 191 | width: 100%; 192 | height: 100%; 193 | position: absolute; 194 | left: 0; 195 | top: 0; 196 | background-color: @color; 197 | background-repeat: no-repeat; 198 | background-position: center; 199 | background-size: 100% 100%; 200 | opacity: 0; 201 | pointer-events: none; 202 | .transition(600ms); 203 | } 204 | &.active-state:before, 205 | html:not(.watch-active-state) &:active:before { 206 | opacity: 1; 207 | .transition(150ms); 208 | } 209 | } 210 | .active-highlight-color(@color) { 211 | &:before { 212 | background-image: -webkit-radial-gradient(center, circle cover, @color 66%, rgba(red(@color),green(@color),blue(@color),0) 66%); 213 | background-image: radial-gradient(circle at center, @color 66%, rgba(red(@color),green(@color),blue(@color),0) 66%); 214 | } 215 | } 216 | // No Scrollbar 217 | .no-scrollbar() { 218 | &::-webkit-scrollbar { 219 | display: none !important; 220 | width: 0 !important; 221 | height: 0 !important; 222 | -webkit-appearance: none; 223 | opacity: 0 !important; 224 | } 225 | } 226 | 227 | 228 | .ellipsis() { 229 | white-space:nowrap; 230 | text-overflow:ellipsis; 231 | overflow:hidden; 232 | word-wrap: break-word; 233 | } 234 | -------------------------------------------------------------------------------- /src/styles/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v4.1.1 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /** 4 | * 1. Change the default font family in all browsers (opinionated). 5 | * 2. Prevent adjustments of font size after orientation changes in IE and iOS. 6 | */ 7 | 8 | html { 9 | font-family: sans-serif; /* 1 */ 10 | -ms-text-size-adjust: 100%; /* 2 */ 11 | -webkit-text-size-adjust: 100%; /* 2 */ 12 | } 13 | 14 | /** 15 | * Remove the margin in all browsers (opinionated). 16 | */ 17 | 18 | body { 19 | margin: 0; 20 | } 21 | 22 | /* HTML5 display definitions 23 | ========================================================================== */ 24 | 25 | /** 26 | * Add the correct display in IE 9-. 27 | * 1. Add the correct display in Edge, IE, and Firefox. 28 | * 2. Add the correct display in IE. 29 | */ 30 | 31 | article, 32 | aside, 33 | details, /* 1 */ 34 | figcaption, 35 | figure, 36 | footer, 37 | header, 38 | main, /* 2 */ 39 | menu, 40 | nav, 41 | section, 42 | summary { /* 1 */ 43 | display: block; 44 | } 45 | 46 | /** 47 | * Add the correct display in IE 9-. 48 | */ 49 | 50 | audio, 51 | canvas, 52 | progress, 53 | video { 54 | display: inline-block; 55 | } 56 | 57 | /** 58 | * Add the correct display in iOS 4-7. 59 | */ 60 | 61 | audio:not([controls]) { 62 | display: none; 63 | height: 0; 64 | } 65 | 66 | /** 67 | * Add the correct vertical alignment in Chrome, Firefox, and Opera. 68 | */ 69 | 70 | progress { 71 | vertical-align: baseline; 72 | } 73 | 74 | /** 75 | * Add the correct display in IE 10-. 76 | * 1. Add the correct display in IE. 77 | */ 78 | 79 | template, /* 1 */ 80 | [hidden] { 81 | display: none; 82 | } 83 | 84 | /* Links 85 | ========================================================================== */ 86 | 87 | /** 88 | * 1. Remove the gray background on active links in IE 10. 89 | * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. 90 | */ 91 | 92 | a { 93 | background-color: transparent; /* 1 */ 94 | -webkit-text-decoration-skip: objects; /* 2 */ 95 | } 96 | 97 | /** 98 | * Remove the outline on focused links when they are also active or hovered 99 | * in all browsers (opinionated). 100 | */ 101 | 102 | a:active, 103 | a:hover { 104 | outline-width: 0; 105 | } 106 | 107 | /* Text-level semantics 108 | ========================================================================== */ 109 | 110 | /** 111 | * 1. Remove the bottom border in Firefox 39-. 112 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 113 | */ 114 | 115 | abbr[title] { 116 | border-bottom: none; /* 1 */ 117 | text-decoration: underline; /* 2 */ 118 | text-decoration: underline dotted; /* 2 */ 119 | } 120 | 121 | /** 122 | * Prevent the duplicate application of `bolder` by the next rule in Safari 6. 123 | */ 124 | 125 | b, 126 | strong { 127 | font-weight: inherit; 128 | } 129 | 130 | /** 131 | * Add the correct font weight in Chrome, Edge, and Safari. 132 | */ 133 | 134 | b, 135 | strong { 136 | font-weight: bolder; 137 | } 138 | 139 | /** 140 | * Add the correct font style in Android 4.3-. 141 | */ 142 | 143 | dfn { 144 | font-style: italic; 145 | } 146 | 147 | /** 148 | * Correct the font size and margin on `h1` elements within `section` and 149 | * `article` contexts in Chrome, Firefox, and Safari. 150 | */ 151 | 152 | h1 { 153 | font-size: 2em; 154 | margin: 0.67em 0; 155 | } 156 | 157 | /** 158 | * Add the correct background and color in IE 9-. 159 | */ 160 | 161 | mark { 162 | background-color: #ff0; 163 | color: #000; 164 | } 165 | 166 | /** 167 | * Add the correct font size in all browsers. 168 | */ 169 | 170 | small { 171 | font-size: 80%; 172 | } 173 | 174 | /** 175 | * Prevent `sub` and `sup` elements from affecting the line height in 176 | * all browsers. 177 | */ 178 | 179 | sub, 180 | sup { 181 | font-size: 75%; 182 | line-height: 0; 183 | position: relative; 184 | vertical-align: baseline; 185 | } 186 | 187 | sub { 188 | bottom: -0.25em; 189 | } 190 | 191 | sup { 192 | top: -0.5em; 193 | } 194 | 195 | /* Embedded content 196 | ========================================================================== */ 197 | 198 | /** 199 | * Remove the border on images inside links in IE 10-. 200 | */ 201 | 202 | img { 203 | border-style: none; 204 | } 205 | 206 | /** 207 | * Hide the overflow in IE. 208 | */ 209 | 210 | svg:not(:root) { 211 | overflow: hidden; 212 | } 213 | 214 | /* Grouping content 215 | ========================================================================== */ 216 | 217 | /** 218 | * 1. Correct the inheritance and scaling of font size in all browsers. 219 | * 2. Correct the odd `em` font sizing in all browsers. 220 | */ 221 | 222 | code, 223 | kbd, 224 | pre, 225 | samp { 226 | font-family: monospace, monospace; /* 1 */ 227 | font-size: 1em; /* 2 */ 228 | } 229 | 230 | /** 231 | * Add the correct margin in IE 8. 232 | */ 233 | 234 | figure { 235 | margin: 1em 40px; 236 | } 237 | 238 | /** 239 | * 1. Add the correct box sizing in Firefox. 240 | * 2. Show the overflow in Edge and IE. 241 | */ 242 | 243 | hr { 244 | box-sizing: content-box; /* 1 */ 245 | height: 0; /* 1 */ 246 | overflow: visible; /* 2 */ 247 | } 248 | 249 | /* Forms 250 | ========================================================================== */ 251 | 252 | /** 253 | * 1. Change font properties to `inherit` in all browsers (opinionated). 254 | * 2. Remove the margin in Firefox and Safari. 255 | */ 256 | 257 | button, 258 | input, 259 | select, 260 | textarea { 261 | font: inherit; /* 1 */ 262 | margin: 0; /* 2 */ 263 | } 264 | 265 | /** 266 | * Restore the font weight unset by the previous rule. 267 | */ 268 | 269 | optgroup { 270 | font-weight: bold; 271 | } 272 | 273 | /** 274 | * Show the overflow in IE. 275 | * 1. Show the overflow in Edge. 276 | */ 277 | 278 | button, 279 | input { /* 1 */ 280 | overflow: visible; 281 | } 282 | 283 | /** 284 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 285 | * 1. Remove the inheritance of text transform in Firefox. 286 | */ 287 | 288 | button, 289 | select { /* 1 */ 290 | text-transform: none; 291 | } 292 | 293 | /** 294 | * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` 295 | * controls in Android 4. 296 | * 2. Correct the inability to style clickable types in iOS and Safari. 297 | */ 298 | 299 | button, 300 | html [type="button"], /* 1 */ 301 | [type="reset"], 302 | [type="submit"] { 303 | -webkit-appearance: button; /* 2 */ 304 | } 305 | 306 | /** 307 | * Remove the inner border and padding in Firefox. 308 | */ 309 | 310 | button::-moz-focus-inner, 311 | [type="button"]::-moz-focus-inner, 312 | [type="reset"]::-moz-focus-inner, 313 | [type="submit"]::-moz-focus-inner { 314 | border-style: none; 315 | padding: 0; 316 | } 317 | 318 | /** 319 | * Restore the focus styles unset by the previous rule. 320 | */ 321 | 322 | button:-moz-focusring, 323 | [type="button"]:-moz-focusring, 324 | [type="reset"]:-moz-focusring, 325 | [type="submit"]:-moz-focusring { 326 | outline: 1px dotted ButtonText; 327 | } 328 | 329 | /** 330 | * Change the border, margin, and padding in all browsers (opinionated). 331 | */ 332 | 333 | fieldset { 334 | border: 1px solid #c0c0c0; 335 | margin: 0 2px; 336 | padding: 0.35em 0.625em 0.75em; 337 | } 338 | 339 | /** 340 | * 1. Correct the text wrapping in Edge and IE. 341 | * 2. Correct the color inheritance from `fieldset` elements in IE. 342 | * 3. Remove the padding so developers are not caught out when they zero out 343 | * `fieldset` elements in all browsers. 344 | */ 345 | 346 | legend { 347 | box-sizing: border-box; /* 1 */ 348 | color: inherit; /* 2 */ 349 | display: table; /* 1 */ 350 | max-width: 100%; /* 1 */ 351 | padding: 0; /* 3 */ 352 | white-space: normal; /* 1 */ 353 | } 354 | 355 | /** 356 | * Remove the default vertical scrollbar in IE. 357 | */ 358 | 359 | textarea { 360 | overflow: auto; 361 | } 362 | 363 | /** 364 | * 1. Add the correct box sizing in IE 10-. 365 | * 2. Remove the padding in IE 10-. 366 | */ 367 | 368 | [type="checkbox"], 369 | [type="radio"] { 370 | box-sizing: border-box; /* 1 */ 371 | padding: 0; /* 2 */ 372 | } 373 | 374 | /** 375 | * Correct the cursor style of increment and decrement buttons in Chrome. 376 | */ 377 | 378 | [type="number"]::-webkit-inner-spin-button, 379 | [type="number"]::-webkit-outer-spin-button { 380 | height: auto; 381 | } 382 | 383 | /** 384 | * 1. Correct the odd appearance in Chrome and Safari. 385 | * 2. Correct the outline style in Safari. 386 | */ 387 | 388 | [type="search"] { 389 | -webkit-appearance: textfield; /* 1 */ 390 | outline-offset: -2px; /* 2 */ 391 | } 392 | 393 | /** 394 | * Remove the inner padding and cancel buttons in Chrome and Safari on OS X. 395 | */ 396 | 397 | [type="search"]::-webkit-search-cancel-button, 398 | [type="search"]::-webkit-search-decoration { 399 | -webkit-appearance: none; 400 | } 401 | 402 | /** 403 | * Correct the text style of placeholders in Chrome, Edge, and Safari. 404 | */ 405 | 406 | ::-webkit-input-placeholder { 407 | color: inherit; 408 | opacity: 0.54; 409 | } 410 | 411 | /** 412 | * 1. Correct the inability to style clickable types in iOS and Safari. 413 | * 2. Change font properties to `inherit` in Safari. 414 | */ 415 | 416 | ::-webkit-file-upload-button { 417 | -webkit-appearance: button; /* 1 */ 418 | font: inherit; /* 2 */ 419 | } 420 | -------------------------------------------------------------------------------- /src/styles/themes/carbon.less: -------------------------------------------------------------------------------- 1 | @import "../vars.less"; 2 | 3 | @primaryColor: #474a4f; 4 | @darkerPrimaryColor: #7e848c; 5 | @lighterPrimaryColor: #bbbfc4; 6 | @accentColor: #ff5252; 7 | 8 | @textColor: #474a4f; 9 | @secondaryTextColor: #7e848c; 10 | @borderColor: #edeff2; 11 | @disabledColor: #d3d6db; 12 | 13 | @import "../../../less/theme-vars.less"; 14 | // components vars 15 | @badgePrimaryColor: @darkerPrimaryColor; 16 | @checkboxCheckedColor: @accentColor; 17 | @checkboxColor: @secondaryTextColor; 18 | @datePickerSelectColor: @accentColor; 19 | @flatButtonPrimaryTextColor: @accentColor; 20 | @circleColor: @accentColor; 21 | @linearProgressFillColor: @accentColor; 22 | @radioColor: @darkerPrimaryColor; 23 | @radioCheckedColor: @accentColor; 24 | @raisedButtonPrimaryColor: @darkerPrimaryColor; 25 | @refreshControlColor: @accentColor; 26 | @sliderSelectionColor: @accentColor; 27 | @snackbarColor: @darkBlack; 28 | @stepperIconColor: @accentColor; 29 | @switchThumbOnColor: @accentColor; 30 | @switchTrackOnColor: fade(@accentColor, 50%); 31 | @textFieldFocusTextColor: @accentColor; 32 | @textFieldFocusLineColor: @accentColor; 33 | @timePickerSelectColor: @accentColor; 34 | @toastColor: @darkBlack; 35 | @import "../../../less/theme.less"; 36 | -------------------------------------------------------------------------------- /src/styles/themes/dark.less: -------------------------------------------------------------------------------- 1 | @import "../vars.less"; 2 | 3 | @primaryColor: @lightBlue700; 4 | @darkerPrimaryColor: @lightBlue700; 5 | @lighterPrimaryColor: @grey600; 6 | @accentColor: @pinkA200; 7 | @darkerAccentColor: @pinkA400; 8 | @lighterAccentColor: @pinkA100; 9 | 10 | @textColor: @fullWhite; 11 | @secondaryTextColor: fade(@fullWhite, 70%); 12 | @alternateTextColor: #303030; 13 | @borderColor: fade(@fullWhite, 30%); 14 | @disabledColor: fade(@fullWhite, 30%); 15 | 16 | // background 17 | @backgroundColor: #303030; 18 | @statusBarBackgroundColor: @fullBlack; 19 | @appbarBackgroundColor: @grey900; 20 | @dialogBackgroundColor: #424242; // dialogs or cards 21 | 22 | // icon 23 | @activeIconColor: fade(@fullWhite, 100%); 24 | @inActiveIconColor: fade(@fullWhite, 50%); 25 | 26 | @import "../../../less/theme-vars.less"; 27 | // components vars 28 | @avatarBackgroundColor: lighten(@alternateTextColor, 26%); 29 | @datePickerHeaderColor: fade(@fullWhite, 12%); 30 | @timePickerHeaderColor: fade(@fullWhite, 12%); 31 | @timePickerClockCircleColor: fade(@fullWhite, 12%); 32 | @avatarBackgroundColor: lighten(@alternateTextColor, 26%); 33 | @chipColor: lighten(@alternateTextColor, 12%); 34 | @floatButtonDisabledColor: lighten(@alternateTextColor, 12%); 35 | 36 | @tableRowHoverBackgroundColor: fade(@textColor, 10%); 37 | @tableRowSelectedBackgroundColor: fade(@textColor, 5%); 38 | @datePickerTextColor: @textColor; 39 | @timePickerColor: @textColor; 40 | @import "../../../less/theme.less"; 41 | -------------------------------------------------------------------------------- /src/styles/themes/default.less: -------------------------------------------------------------------------------- 1 | @import "../vars.less"; 2 | @import "../../../less/theme-vars.less"; 3 | @import "../../../less/theme.less"; 4 | -------------------------------------------------------------------------------- /src/styles/themes/teal.less: -------------------------------------------------------------------------------- 1 | @import "../vars.less"; 2 | 3 | @primaryColor: @teal; 4 | @darkerPrimaryColor: @teal700; 5 | 6 | @import "../../../less/theme-vars.less"; 7 | @import "../../../less/theme.less"; 8 | -------------------------------------------------------------------------------- /src/styles/vars.less: -------------------------------------------------------------------------------- 1 | @import "./colors.less"; 2 | @fontFamily: Roboto, Lato, sans-serif; 3 | 4 | // primary and accent 5 | @primaryColor: @lightBlue; // 主色 6 | @darkerPrimaryColor: @lightBlue700; 7 | @lighterPrimaryColor: @grey400; 8 | @accentColor: @pinkA200; 9 | @darkerAccentColor: @grey100; 10 | @lighterAccentColor: @grey500; 11 | 12 | // textColor or borderColor 13 | @textColor: @darkBlack; 14 | @secondaryTextColor: fade(@fullBlack, 54%); 15 | @alternateTextColor: @white; 16 | @borderColor: fade(@fullBlack, 12%); 17 | @disabledColor: fade(@fullBlack, 38%); 18 | 19 | // background 20 | @backgroundColor: @white; 21 | @statusBarBackgroundColor: @grey300; 22 | @appbarBackgroundColor: @grey100; 23 | @dialogBackgroundColor: @white; // dialogs or cards 24 | 25 | // icon color 26 | @activeIconColor: fade(@fullBlack, 54%); 27 | @inActiveIconColor: fade(@fullBlack, 38%); 28 | 29 | // spaceing 30 | @iconSize: 24px; 31 | @desktopGutter: 24px; 32 | @desktopGutterMore: 32px; 33 | @desktopGutterLess: 16px; 34 | @desktopGutterMini: 8px; 35 | @desktopKeylineIncrement: 64px; 36 | @desktopDropDownMenuItemHeight: 32px; 37 | @desktopDropDownMenuFontSize: 15px; 38 | @desktopDrawerMenuItemHeight: 48px; 39 | @desktopSubheaderHeight: 48px; 40 | @desktopToolbarHeight: 56px; 41 | 42 | // animate 43 | @easeOutFunction: cubic-bezier(0.23, 1, 0.32, 1); 44 | @easeInOutFunction: cubic-bezier(0.445, 0.05, 0.55, 0.95); 45 | -------------------------------------------------------------------------------- /src/styles/zIndex.less: -------------------------------------------------------------------------------- 1 | @menu: 1000; 2 | @appBar: 1100; 3 | @drawerOverlay: 1200; 4 | @drawer: 1300; 5 | @dialogOverlay: 1400; 6 | @dialog: 1500; 7 | @layer: 2000; 8 | @popover: 2100; 9 | @snackbar: 2900; 10 | @tooltip: 3000; 11 | -------------------------------------------------------------------------------- /src/views/index.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/views/player.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pluto1114/vue-music-qq/d95f93cfe0c4fbb7c42540dfffead952f8c1fa57/static/.gitkeep -------------------------------------------------------------------------------- /static/hot_all.js: -------------------------------------------------------------------------------- 1 | 2 | var hot_all={ 3 | retcode: "1", 4 | songlist: [{ 5 | id: "1597410", 6 | type: 3, 7 | url: "http://stream1.qqmusic.qq.com:0/1597410.wma", 8 | songName: "江南style", 9 | singerId: "13143", 10 | singerName: "Psy", 11 | albumId: "128191", 12 | albumName: "PSY 6甲 Part.1", 13 | albumLink: "/musicbox/shop/v3/album/91/album_128191.htm", 14 | playtime: "219" 15 | }, 16 | { 17 | id: "1539873", 18 | type: 3, 19 | url: "http://stream6.qqmusic.qq.com:0/1539873.wma", 20 | songName: "没有什么不同", 21 | singerId: "34703", 22 | singerName: "曲婉婷", 23 | albumId: "107526", 24 | albumName: "我的歌声里", 25 | albumLink: "/musicbox/shop/v3/album/26/album_107526.htm", 26 | playtime: "288" 27 | }, 28 | { 29 | id: "1913719", 30 | type: 3, 31 | url: "http://stream3.qqmusic.qq.com:0/1913719.wma", 32 | songName: "想你的夜", 33 | singerId: "12770", 34 | singerName: "关喆", 35 | albumId: "139643", 36 | albumName: "身边的故事", 37 | albumLink: "/musicbox/shop/v3/album/43/album_139643.htm", 38 | playtime: "268" 39 | }, 40 | { 41 | id: "1803555", 42 | type: 3, 43 | url: "http://stream10.qqmusic.qq.com:0/1803555.wma", 44 | songName: "怒放的生命", 45 | singerId: "4604", 46 | singerName: "汪峰", 47 | albumId: "140820", 48 | albumName: "北京青年 电视原声带", 49 | albumLink: "/musicbox/shop/v3/album/20/album_140820.htm", 50 | playtime: "275" 51 | }, 52 | { 53 | id: "1773989", 54 | type: 3, 55 | url: "http://stream3.qqmusic.qq.com:0/1773989.wma", 56 | songName: "如果分开我也爱你", 57 | singerId: "12770", 58 | singerName: "关喆", 59 | albumId: "139643", 60 | albumName: "身边的故事", 61 | albumLink: "/musicbox/shop/v3/album/43/album_139643.htm", 62 | playtime: "289" 63 | }, 64 | { 65 | id: "1641090", 66 | type: 3, 67 | url: "http://stream9.qqmusic.qq.com:0/1641090.wma", 68 | songName: "你并不懂我", 69 | singerId: "13578", 70 | singerName: "BY2", 71 | albumId: "123849", 72 | albumName: "2020爱你爱你", 73 | albumLink: "/musicbox/shop/v3/album/49/album_123849.htm", 74 | playtime: "235" 75 | }, 76 | { 77 | id: "1531817", 78 | type: 3, 79 | url: "http://stream9.qqmusic.qq.com:0/1531817.wma", 80 | songName: "幻听", 81 | singerId: "7221", 82 | singerName: "许嵩", 83 | albumId: "119459", 84 | albumName: "梦游计", 85 | albumLink: "/musicbox/shop/v3/album/59/album_119459.htm", 86 | playtime: "273" 87 | }, 88 | { 89 | id: "1439470", 90 | type: 3, 91 | url: "http://stream8.qqmusic.qq.com:0/1439470.wma", 92 | songName: "一吻天荒", 93 | singerId: "4357", 94 | singerName: "胡歌", 95 | albumId: "115748", 96 | albumName: "轩辕剑之天之痕", 97 | albumLink: "/musicbox/shop/v3/album/48/album_115748.htm", 98 | playtime: "250" 99 | }, 100 | { 101 | id: "1913708", 102 | type: 3, 103 | url: "http://stream2.qqmusic.qq.com:0/1913708.wma", 104 | songName: "淋雨一直走", 105 | singerId: "224", 106 | singerName: "张韶涵", 107 | albumId: "130382", 108 | albumName: "有形的翅膀", 109 | albumLink: "/musicbox/shop/v3/album/82/album_130382.htm", 110 | playtime: "205" 111 | }, 112 | { 113 | id: "1067125", 114 | type: 3, 115 | url: "http://stream2.qqmusic.qq.com:0/1067125.wma", 116 | songName: "父亲", 117 | singerId: "11761", 118 | singerName: "筷子兄弟", 119 | albumId: "90932", 120 | albumName: "父亲", 121 | albumLink: "/musicbox/shop/v3/album/32/album_90932.htm", 122 | playtime: "301" 123 | }, 124 | { 125 | id: "1078214", 126 | type: 3, 127 | url: "http://stream5.qqmusic.qq.com:0/1078214.wma", 128 | songName: "后会无期", 129 | singerId: "22704", 130 | singerName: "徐良", 131 | albumId: "91325", 132 | albumName: "不良少年", 133 | albumLink: "/musicbox/shop/v3/album/25/album_91325.htm", 134 | playtime: "211" 135 | }, 136 | { 137 | id: "1908164", 138 | type: 3, 139 | url: "http://stream3.qqmusic.qq.com:0/1908164.wma", 140 | songName: "爱输给了谁", 141 | singerId: "15809", 142 | singerName: "黄勇", 143 | albumId: "143913", 144 | albumName: "2012年09月新歌速递", 145 | albumLink: "/musicbox/shop/v3/album/13/album_143913.htm", 146 | playtime: "209" 147 | }, 148 | { 149 | id: "804997", 150 | type: 3, 151 | url: "http://stream4.qqmusic.qq.com:0/804997.wma", 152 | songName: "因为爱情", 153 | singerId: "143", 154 | singerName: "陈奕迅 王菲", 155 | albumId: "68074", 156 | albumName: "Stranger Under My Skin", 157 | albumLink: "/musicbox/shop/v3/album/74/album_68074.htm", 158 | playtime: "217" 159 | }, 160 | { 161 | id: "140677", 162 | type: 3, 163 | url: "http://stream3.qqmusic.qq.com:0/140677.wma", 164 | songName: "爱要坦荡荡", 165 | singerId: "5117", 166 | singerName: "萧萧", 167 | albumId: "12416", 168 | albumName: "Beautiful Angel", 169 | albumLink: "/musicbox/shop/v3/album/16/album_12416.htm", 170 | playtime: "238" 171 | }, 172 | { 173 | id: "1756991", 174 | type: 3, 175 | url: "http://stream2.qqmusic.qq.com:0/1756991.wma", 176 | songName: "爱,有你才完整", 177 | singerId: "11453", 178 | singerName: "魏晨", 179 | albumId: "138767", 180 | albumName: "童话二分之一 电视原声带", 181 | albumLink: "/musicbox/shop/v3/album/67/album_138767.htm", 182 | playtime: "234" 183 | }, 184 | { 185 | id: "1229385", 186 | type: 3, 187 | url: "http://stream7.qqmusic.qq.com:0/1229385.wma", 188 | songName: "风度", 189 | singerId: "3954", 190 | singerName: "汪苏泷", 191 | albumId: "121274", 192 | albumName: "万有引力", 193 | albumLink: "/musicbox/shop/v3/album/74/album_121274.htm", 194 | playtime: "220" 195 | }, 196 | { 197 | id: "1366653", 198 | type: 3, 199 | url: "http://stream8.qqmusic.qq.com:0/1366653.wma", 200 | songName: "最亲爱的你", 201 | singerId: "4351", 202 | singerName: "范玮琪", 203 | albumId: "110648", 204 | albumName: "爱,在一起Together", 205 | albumLink: "/musicbox/shop/v3/album/48/album_110648.htm", 206 | playtime: "282" 207 | }, 208 | { 209 | id: "1887792", 210 | type: 3, 211 | url: "http://stream8.qqmusic.qq.com:0/1887792.wma", 212 | songName: "流恋", 213 | singerId: "4907", 214 | singerName: "吴奇隆 严艺丹", 215 | albumId: "146668", 216 | albumName: "新白发魔女传 电视原声带 Part.1", 217 | albumLink: "/musicbox/shop/v3/album/68/album_146668.htm", 218 | playtime: "245" 219 | }, 220 | { 221 | id: "1833391", 222 | type: 3, 223 | url: "http://stream2.qqmusic.qq.com:0/1833391.wma", 224 | songName: "末日不孤单", 225 | singerId: "61981", 226 | singerName: "李代沫 陈浩轩", 227 | albumId: "135242", 228 | albumName: "2012年08月新歌速递", 229 | albumLink: "/musicbox/shop/v3/album/42/album_135242.htm", 230 | playtime: "272" 231 | }, 232 | { 233 | id: "1319052", 234 | type: 3, 235 | url: "http://stream6.qqmusic.qq.com:0/1319052.wma", 236 | songName: "我的歌声里", 237 | singerId: "34703", 238 | singerName: "曲婉婷", 239 | albumId: "107526", 240 | albumName: "我的歌声里", 241 | albumLink: "/musicbox/shop/v3/album/26/album_107526.htm", 242 | playtime: "208" 243 | }, 244 | { 245 | id: "1878910", 246 | type: 3, 247 | url: "http://stream2.qqmusic.qq.com:0/1878910.wma", 248 | songName: "最近好吗", 249 | singerId: "224", 250 | singerName: "张韶涵", 251 | albumId: "130382", 252 | albumName: "有形的翅膀", 253 | albumLink: "/musicbox/shop/v3/album/82/album_130382.htm", 254 | playtime: "249" 255 | }, 256 | { 257 | id: "916834", 258 | type: 3, 259 | url: "http://stream5.qqmusic.qq.com:0/916834.wma", 260 | songName: "那些年", 261 | singerId: "24833", 262 | singerName: "胡夏", 263 | albumId: "77485", 264 | albumName: "那些年,我们一起追的女孩", 265 | albumLink: "/musicbox/shop/v3/album/85/album_77485.htm", 266 | playtime: "371" 267 | }, 268 | { 269 | id: "1781758", 270 | type: 3, 271 | url: "http://stream7.qqmusic.qq.com:0/1781758.wma", 272 | songName: "任由爱", 273 | singerId: "13578", 274 | singerName: "BY2", 275 | albumId: "140197", 276 | albumName: "爱情是从告白开始的 电视原声带", 277 | albumLink: "/musicbox/shop/v3/album/97/album_140197.htm", 278 | playtime: "210" 279 | }, 280 | { 281 | id: "1474843", 282 | type: 3, 283 | url: "http://stream9.qqmusic.qq.com:0/1474843.wma", 284 | songName: "胡萝卜须", 285 | singerId: "7221", 286 | singerName: "许嵩", 287 | albumId: "119459", 288 | albumName: "梦游计", 289 | albumLink: "/musicbox/shop/v3/album/59/album_119459.htm", 290 | playtime: "231" 291 | }, 292 | { 293 | id: "1554114", 294 | type: 3, 295 | url: "http://stream9.qqmusic.qq.com:0/1554114.wma", 296 | songName: "拥抱你的微笑", 297 | singerId: "11626", 298 | singerName: "郭静", 299 | albumId: "125039", 300 | albumName: "原来爱就是甜蜜 电视原声带", 301 | albumLink: "/musicbox/shop/v3/album/39/album_125039.htm", 302 | playtime: "240" 303 | }, 304 | { 305 | id: "974808", 306 | type: 3, 307 | url: "http://stream9.qqmusic.qq.com:0/974808.wma", 308 | songName: "依然爱你", 309 | singerId: "265", 310 | singerName: "王力宏", 311 | albumId: "81359", 312 | albumName: "火力全开 新歌+精选", 313 | albumLink: "/musicbox/shop/v3/album/59/album_81359.htm", 314 | playtime: "246" 315 | }, 316 | { 317 | id: "1791017", 318 | type: 3, 319 | url: "http://stream10.qqmusic.qq.com:0/1791017.wma", 320 | songName: "存在", 321 | singerId: "4604", 322 | singerName: "汪峰", 323 | albumId: "140820", 324 | albumName: "北京青年 电视原声带", 325 | albumLink: "/musicbox/shop/v3/album/20/album_140820.htm", 326 | playtime: "284" 327 | }, 328 | { 329 | id: "1500512", 330 | type: 3, 331 | url: "http://stream8.qqmusic.qq.com:0/1500512.wma", 332 | songName: "这样爱了", 333 | singerId: "19868", 334 | singerName: "张婧", 335 | albumId: "115748", 336 | albumName: "轩辕剑之天之痕", 337 | albumLink: "/musicbox/shop/v3/album/48/album_115748.htm", 338 | playtime: "263" 339 | }, 340 | { 341 | id: "1891844", 342 | type: 3, 343 | url: "http://stream9.qqmusic.qq.com:0/1891844.wma", 344 | songName: "愿得一人心", 345 | singerId: "23080", 346 | singerName: "李行亮", 347 | albumId: "141889", 348 | albumName: "愿得一人心", 349 | albumLink: "/musicbox/shop/v3/album/89/album_141889.htm", 350 | playtime: "277" 351 | }, 352 | { 353 | id: "1831828", 354 | type: 3, 355 | url: "http://stream7.qqmusic.qq.com:0/1831828.wma", 356 | songName: "爱的回归线", 357 | singerId: "6119", 358 | singerName: "陈韵若 陈每文", 359 | albumId: "97617", 360 | albumName: "爱情公寓3 电视原声带", 361 | albumLink: "/musicbox/shop/v3/album/17/album_97617.htm", 362 | playtime: "257" 363 | }, 364 | { 365 | id: "577172", 366 | type: 3, 367 | url: "http://stream2.qqmusic.qq.com:0/577172.wma", 368 | songName: "爱情转移", 369 | singerId: "143", 370 | singerName: "陈奕迅", 371 | albumId: "48918", 372 | albumName: "1997-2007 跨世纪国语精选 CD2", 373 | albumLink: "/musicbox/shop/v3/album/18/album_48918.htm", 374 | playtime: "262" 375 | }, 376 | { 377 | id: "1459416", 378 | type: 3, 379 | url: "http://stream6.qqmusic.qq.com:0/1459416.wma", 380 | songName: "无颜女", 381 | singerId: "22704", 382 | singerName: "徐良 小凌", 383 | albumId: "121966", 384 | albumName: "无颜女", 385 | albumLink: "/musicbox/shop/v3/album/66/album_121966.htm", 386 | playtime: "214" 387 | }, 388 | { 389 | id: "1923586", 390 | type: 3, 391 | url: "http://stream8.qqmusic.qq.com:0/1923586.wma", 392 | songName: "可能你还爱我", 393 | singerId: "11957", 394 | singerName: "炎亚纶", 395 | albumId: "150218", 396 | albumName: "纪念日", 397 | albumLink: "/musicbox/shop/v3/album/18/album_150218.htm", 398 | playtime: "278" 399 | }, 400 | { 401 | id: "726895", 402 | type: 3, 403 | url: "http://stream9.qqmusic.qq.com:0/726895.wma", 404 | songName: "最炫民族风", 405 | singerId: "5829", 406 | singerName: "凤凰传奇", 407 | albumId: "61517", 408 | albumName: "我从草原来 新歌+精选", 409 | albumLink: "/musicbox/shop/v3/album/17/album_61517.htm", 410 | playtime: "284" 411 | }, 412 | { 413 | id: "935920", 414 | type: 3, 415 | url: "http://stream7.qqmusic.qq.com:0/935920.wma", 416 | songName: "策马奔腾", 417 | singerId: "5829", 418 | singerName: "凤凰传奇", 419 | albumId: "77377", 420 | albumName: "大声唱", 421 | albumLink: "/musicbox/shop/v3/album/77/album_77377.htm", 422 | playtime: "282" 423 | }, 424 | { 425 | id: "447257", 426 | type: 3, 427 | url: "http://stream4.qqmusic.qq.com:0/447257.wma", 428 | songName: "AlwaysOnline", 429 | singerId: "4286", 430 | singerName: "林俊杰", 431 | albumId: "36160", 432 | albumName: "JJ陆", 433 | albumLink: "/musicbox/shop/v3/album/60/album_36160.htm", 434 | playtime: "222" 435 | }, 436 | { 437 | id: "430057", 438 | type: 3, 439 | url: "http://stream10.qqmusic.qq.com:0/430057.wma", 440 | songName: "类似爱情", 441 | singerId: "165", 442 | singerName: "萧亚轩", 443 | albumId: "34887", 444 | albumName: "三面夏娃", 445 | albumLink: "/musicbox/shop/v3/album/87/album_34887.htm", 446 | playtime: "282" 447 | }, 448 | { 449 | id: "1919590", 450 | type: 3, 451 | url: "http://stream9.qqmusic.qq.com:0/1919590.wma", 452 | songName: "还好有你在", 453 | singerId: "14262", 454 | singerName: "至上励合", 455 | albumId: "149889", 456 | albumName: "还好有你在", 457 | albumLink: "/musicbox/shop/v3/album/89/album_149889.htm", 458 | playtime: "293" 459 | }, 460 | { 461 | id: "1113312", 462 | type: 3, 463 | url: "http://stream6.qqmusic.qq.com:0/1113312.wma", 464 | songName: "滴答", 465 | singerId: "6307", 466 | singerName: "侃侃", 467 | albumId: "94666", 468 | albumName: "《北京爱情故事》音乐原声", 469 | albumLink: "/musicbox/shop/v3/album/66/album_94666.htm", 470 | playtime: "232" 471 | }, 472 | { 473 | id: "1600197", 474 | type: 3, 475 | url: "http://stream8.qqmusic.qq.com:0/1600197.wma", 476 | songName: "我知道你都知道", 477 | singerId: "5062", 478 | singerName: "薛之谦", 479 | albumId: "122328", 480 | albumName: "几个薛之谦", 481 | albumLink: "/musicbox/shop/v3/album/28/album_122328.htm", 482 | playtime: "274" 483 | }, 484 | { 485 | id: "1761210", 486 | type: 3, 487 | url: "http://stream7.qqmusic.qq.com:0/1761210.wma", 488 | songName: "快乐 不再快乐", 489 | singerId: "31719", 490 | singerName: "付梦妮", 491 | albumId: "138767", 492 | albumName: "童话二分之一 电视原声带", 493 | albumLink: "/musicbox/shop/v3/album/67/album_138767.htm", 494 | playtime: "252" 495 | }, 496 | { 497 | id: "974039", 498 | type: 3, 499 | url: "http://stream1.qqmusic.qq.com:0/974039.wma", 500 | songName: "爱着你却伤了她", 501 | singerId: "19722", 502 | singerName: "冷漠", 503 | albumId: "90215", 504 | albumName: "爱过以后", 505 | albumLink: "/musicbox/shop/v3/album/15/album_90215.htm", 506 | playtime: "260" 507 | }, 508 | { 509 | id: "1494222", 510 | type: 3, 511 | url: "http://stream6.qqmusic.qq.com:0/1494222.wma", 512 | songName: "万有引力", 513 | singerId: "3954", 514 | singerName: "汪苏泷", 515 | albumId: "121274", 516 | albumName: "万有引力", 517 | albumLink: "/musicbox/shop/v3/album/74/album_121274.htm", 518 | playtime: "246" 519 | }, 520 | { 521 | id: "1842091", 522 | type: 3, 523 | url: "http://stream5.qqmusic.qq.com:0/1842091.wma", 524 | songName: "再不疯狂我们就老了", 525 | singerId: "4615", 526 | singerName: "李宇春", 527 | albumId: "100385", 528 | albumName: "再不疯狂我们就老了", 529 | albumLink: "/musicbox/shop/v3/album/85/album_100385.htm", 530 | playtime: "246" 531 | }, 532 | { 533 | id: "440817", 534 | type: 3, 535 | url: "http://stream3.qqmusic.qq.com:0/440817.wma", 536 | songName: "我们都一样", 537 | singerId: "6499", 538 | singerName: "张杰", 539 | albumId: "35875", 540 | albumName: "明天过后", 541 | albumLink: "/musicbox/shop/v3/album/75/album_35875.htm", 542 | playtime: "303" 543 | }, 544 | { 545 | id: "793420", 546 | type: 3, 547 | url: "http://stream5.qqmusic.qq.com:0/793420.wma", 548 | songName: "Rolling in the Deep", 549 | singerId: "12578", 550 | singerName: "Adele", 551 | albumId: "67005", 552 | albumName: "21 (Target Deluxe Edition)", 553 | albumLink: "/musicbox/shop/v3/album/5/album_67005.htm", 554 | playtime: "229" 555 | }, 556 | { 557 | id: "1913422", 558 | type: 3, 559 | url: "http://stream3.qqmusic.qq.com:0/1913422.wma", 560 | songName: "御龙品青梅", 561 | singerId: "4674", 562 | singerName: "刘惜君", 563 | albumId: "121963", 564 | albumName: "御龙在天场景音乐", 565 | albumLink: "/musicbox/shop/v3/album/63/album_121963.htm", 566 | playtime: "207" 567 | }, 568 | { 569 | id: "1197338", 570 | type: 3, 571 | url: "http://stream7.qqmusic.qq.com:0/1197338.wma", 572 | songName: "逆战", 573 | singerId: "6499", 574 | singerName: "张杰", 575 | albumId: "101177", 576 | albumName: "逆战", 577 | albumLink: "/musicbox/shop/v3/album/77/album_101177.htm", 578 | playtime: "229" 579 | }, 580 | { 581 | id: "874843", 582 | type: 3, 583 | url: "http://stream5.qqmusic.qq.com:0/874843.wma", 584 | songName: "不要在我寂寞的时候说爱我(国)", 585 | singerId: "4715", 586 | singerName: "郑源", 587 | albumId: "33812", 588 | albumName: "源情歌", 589 | albumLink: "/musicbox/shop/v3/album/12/album_33812.htm", 590 | playtime: "244" 591 | }, 592 | { 593 | id: "1673329", 594 | type: 3, 595 | url: "http://stream7.qqmusic.qq.com:0/1673329.wma", 596 | songName: "单身美好", 597 | singerId: "11626", 598 | singerName: "郭静", 599 | albumId: "133127", 600 | albumName: "花是爱 电视原声带", 601 | albumLink: "/musicbox/shop/v3/album/27/album_133127.htm", 602 | playtime: "249" 603 | }, 604 | { 605 | id: "1887796", 606 | type: 3, 607 | url: "http://stream8.qqmusic.qq.com:0/1887796.wma", 608 | songName: "留香", 609 | singerId: "4907", 610 | singerName: "吴奇隆", 611 | albumId: "146668", 612 | albumName: "新白发魔女传 电视原声带 Part.1", 613 | albumLink: "/musicbox/shop/v3/album/68/album_146668.htm", 614 | playtime: "196" 615 | }, 616 | { 617 | id: "1037897", 618 | type: 3, 619 | url: "http://stream7.qqmusic.qq.com:0/1037897.wma", 620 | songName: "我想我不够好", 621 | singerId: "28634", 622 | singerName: "单色凌", 623 | albumId: "87797", 624 | albumName: "11月网络红歌2", 625 | albumLink: "/musicbox/shop/v3/album/97/album_87797.htm", 626 | playtime: "172" 627 | }, 628 | { 629 | id: "1878998", 630 | type: 3, 631 | url: "http://stream3.qqmusic.qq.com:0/1878998.wma", 632 | songName: "伤心童话(电影版)", 633 | singerId: "24833", 634 | singerName: "胡夏", 635 | albumId: "143913", 636 | albumName: "2012年09月新歌速递", 637 | albumLink: "/musicbox/shop/v3/album/13/album_143913.htm", 638 | playtime: "278" 639 | }, 640 | { 641 | id: "916320", 642 | type: 3, 643 | url: "http://stream1.qqmusic.qq.com:0/916320.wma", 644 | songName: "全世界宣布爱你", 645 | singerId: "22874", 646 | singerName: "孙子涵", 647 | albumId: "77451", 648 | albumName: "一年一度的夏天", 649 | albumLink: "/musicbox/shop/v3/album/51/album_77451.htm", 650 | playtime: "235" 651 | }, 652 | { 653 | id: "432421", 654 | type: 3, 655 | url: "http://stream3.qqmusic.qq.com:0/432421.wma", 656 | songName: "如果沒有你", 657 | singerId: "54", 658 | singerName: "莫文蔚", 659 | albumId: "35165", 660 | albumName: "就i Karen 莫文蔚精选", 661 | albumLink: "/musicbox/shop/v3/album/65/album_35165.htm", 662 | playtime: "289" 663 | }, 664 | { 665 | id: "1136672", 666 | type: 3, 667 | url: "http://stream4.qqmusic.qq.com:0/1136672.wma", 668 | songName: "经过", 669 | singerId: "11446", 670 | singerName: "陈楚生 何洁", 671 | albumId: "96774", 672 | albumName: "夫妻那些事", 673 | albumLink: "/musicbox/shop/v3/album/74/album_96774.htm", 674 | playtime: "244" 675 | }, 676 | { 677 | id: "1232479", 678 | type: 3, 679 | url: "http://stream5.qqmusic.qq.com:0/1232479.wma", 680 | songName: "一个人不可能", 681 | singerId: "11979", 682 | singerName: "丁当", 683 | albumId: "101565", 684 | albumName: "好难得", 685 | albumLink: "/musicbox/shop/v3/album/65/album_101565.htm", 686 | playtime: "290" 687 | }, 688 | { 689 | id: "936753", 690 | type: 3, 691 | url: "http://stream2.qqmusic.qq.com:0/936753.wma", 692 | songName: "说好了不见面", 693 | singerId: "16292", 694 | singerName: "小贱", 695 | albumId: "76932", 696 | albumName: "2011年8月新歌速递2", 697 | albumLink: "/musicbox/shop/v3/album/32/album_76932.htm", 698 | playtime: "208" 699 | }, 700 | { 701 | id: "674077", 702 | type: 3, 703 | url: "http://stream7.qqmusic.qq.com:0/674077.wma", 704 | songName: "手放开", 705 | singerId: "38", 706 | singerName: "李圣杰", 707 | albumId: "56866", 708 | albumName: "孤鸾疗伤版", 709 | albumLink: "/musicbox/shop/v3/album/66/album_56866.htm", 710 | playtime: "265" 711 | }, 712 | { 713 | id: "1539092", 714 | type: 3, 715 | url: "http://stream3.qqmusic.qq.com:0/1539092.wma", 716 | songName: "好男人都死哪儿去了", 717 | singerId: "37459", 718 | singerName: "崔子格", 719 | albumId: "123853", 720 | albumName: "好男人都死哪儿去了", 721 | albumLink: "/musicbox/shop/v3/album/53/album_123853.htm", 722 | playtime: "240" 723 | }, 724 | { 725 | id: "434447", 726 | type: 3, 727 | url: "http://stream6.qqmusic.qq.com:0/434447.wma", 728 | songName: "擦肩而过", 729 | singerId: "4715", 730 | singerName: "郑源", 731 | albumId: "35352", 732 | albumName: "擦肩而过", 733 | albumLink: "/musicbox/shop/v3/album/52/album_35352.htm", 734 | playtime: "234" 735 | }, 736 | { 737 | id: "1014867", 738 | type: 3, 739 | url: "http://stream4.qqmusic.qq.com:0/1014867.wma", 740 | songName: "朋友的酒", 741 | singerId: "6862", 742 | singerName: "李晓杰", 743 | albumId: "84524", 744 | albumName: "2011年10月新歌速递", 745 | albumLink: "/musicbox/shop/v3/album/24/album_84524.htm", 746 | playtime: "261" 747 | }, 748 | { 749 | id: "1385291", 750 | type: 3, 751 | url: "http://stream4.qqmusic.qq.com:0/1385291.wma", 752 | songName: "凌乱的华丽", 753 | singerId: "28634", 754 | singerName: "单色凌", 755 | albumId: "112454", 756 | albumName: "凌乱的华丽 EP", 757 | albumLink: "/musicbox/shop/v3/album/54/album_112454.htm", 758 | playtime: "186" 759 | }, 760 | { 761 | id: "1403189", 762 | type: 3, 763 | url: "http://stream6.qqmusic.qq.com:0/1403189.wma", 764 | songName: "一生无悔", 765 | singerId: "19229", 766 | singerName: "高安 杭娇", 767 | albumId: "114086", 768 | albumName: "一唱而红", 769 | albumLink: "/musicbox/shop/v3/album/86/album_114086.htm", 770 | playtime: "242" 771 | }, 772 | { 773 | id: "1547646", 774 | type: 3, 775 | url: "http://stream10.qqmusic.qq.com:0/1547646.wma", 776 | songName: "胡闹", 777 | singerId: "178", 778 | singerName: "吴克羣", 779 | albumId: "124530", 780 | albumName: "寂寞来了怎么办", 781 | albumLink: "/musicbox/shop/v3/album/30/album_124530.htm", 782 | playtime: "329" 783 | }, 784 | { 785 | id: "777178", 786 | type: 3, 787 | url: "http://stream5.qqmusic.qq.com:0/777178.wma", 788 | songName: "你是我的眼", 789 | singerId: "11606", 790 | singerName: "林宥嘉", 791 | albumId: "65505", 792 | albumName: "昨天今天明天", 793 | albumLink: "/musicbox/shop/v3/album/5/album_65505.htm", 794 | playtime: "283" 795 | }, 796 | { 797 | id: "1193426", 798 | type: 3, 799 | url: "http://stream3.qqmusic.qq.com:0/1193426.wma", 800 | songName: "有我在", 801 | singerId: "4651", 802 | singerName: "罗志祥", 803 | albumId: "100593", 804 | albumName: "有我在", 805 | albumLink: "/musicbox/shop/v3/album/93/album_100593.htm", 806 | playtime: "264" 807 | }, 808 | { 809 | id: "691943", 810 | type: 3, 811 | url: "http://stream1.qqmusic.qq.com:0/691943.wma", 812 | songName: "HIGH歌", 813 | singerId: "11476", 814 | singerName: "黄龄", 815 | albumId: "58502", 816 | albumName: "特别", 817 | albumLink: "/musicbox/shop/v3/album/2/album_58502.htm", 818 | playtime: "283" 819 | }, 820 | { 821 | id: "462620", 822 | type: 3, 823 | url: "http://stream9.qqmusic.qq.com:0/462620.wma", 824 | songName: "难以启齿的柔弱", 825 | singerId: "12111", 826 | singerName: "金志文", 827 | albumId: "37632", 828 | albumName: "爱比不爱更寂寞", 829 | albumLink: "/musicbox/shop/v3/album/32/album_37632.htm", 830 | playtime: "250" 831 | }, 832 | { 833 | id: "1067128", 834 | type: 3, 835 | url: "http://stream2.qqmusic.qq.com:0/1067128.wma", 836 | songName: "老男孩", 837 | singerId: "11761", 838 | singerName: "筷子兄弟", 839 | albumId: "90932", 840 | albumName: "父亲", 841 | albumLink: "/musicbox/shop/v3/album/32/album_90932.htm", 842 | playtime: "300" 843 | }, 844 | { 845 | id: "434074", 846 | type: 3, 847 | url: "http://stream1.qqmusic.qq.com:0/434074.wma", 848 | songName: "最初的梦想", 849 | singerId: "4351", 850 | singerName: "范玮琪", 851 | albumId: "35325", 852 | albumName: "Faces Of FanFan 新歌+精选32首全纪录", 853 | albumLink: "/musicbox/shop/v3/album/25/album_35325.htm", 854 | playtime: "298" 855 | }, 856 | { 857 | id: "1844597", 858 | type: 3, 859 | url: "http://stream6.qqmusic.qq.com:0/1844597.wma", 860 | songName: "诗人漫步", 861 | singerId: "227", 862 | singerName: "蔡依林", 863 | albumId: "139346", 864 | albumName: "MUSE", 865 | albumLink: "/musicbox/shop/v3/album/46/album_139346.htm", 866 | playtime: "308" 867 | }, 868 | { 869 | id: "185675", 870 | type: 3, 871 | url: "http://stream2.qqmusic.qq.com:0/185675.wma", 872 | songName: "我怀念的", 873 | singerId: "109", 874 | singerName: "孙燕姿", 875 | albumId: "15902", 876 | albumName: "逆光", 877 | albumLink: "/musicbox/shop/v3/album/2/album_15902.htm", 878 | playtime: "287" 879 | }, 880 | { 881 | id: "2441405", 882 | type: 3, 883 | url: "http://stream9.qqmusic.qq.com:0/2441405.wma", 884 | songName: "不再让你孤单", 885 | singerId: "208", 886 | singerName: "水木年华", 887 | albumId: "150859", 888 | albumName: "2012年10月新歌速递", 889 | albumLink: "/musicbox/shop/v3/album/59/album_150859.htm", 890 | playtime: "343" 891 | }, 892 | { 893 | id: "416764", 894 | type: 3, 895 | url: "http://stream4.qqmusic.qq.com:0/416764.wma", 896 | songName: "洋葱", 897 | singerId: "11608", 898 | singerName: "杨宗纬", 899 | albumId: "33703", 900 | albumName: "鸽子", 901 | albumLink: "/musicbox/shop/v3/album/3/album_33703.htm", 902 | playtime: "278" 903 | }, 904 | { 905 | id: "97870", 906 | type: 3, 907 | url: "http://stream7.qqmusic.qq.com:0/97870.wma", 908 | songName: "一直很安静", 909 | singerId: "3346", 910 | singerName: "阿桑", 911 | albumId: "8229", 912 | albumName: "寂寞在唱歌", 913 | albumLink: "/musicbox/shop/v3/album/29/album_8229.htm", 914 | playtime: "251" 915 | }, 916 | { 917 | id: "469831", 918 | type: 3, 919 | url: "http://stream2.qqmusic.qq.com:0/469831.wma", 920 | songName: "关不上的窗", 921 | singerId: "4365", 922 | singerName: "周传雄", 923 | albumId: "38202", 924 | albumName: "恋人创世纪", 925 | albumLink: "/musicbox/shop/v3/album/2/album_38202.htm", 926 | playtime: "293" 927 | }, 928 | { 929 | id: "1092641", 930 | type: 3, 931 | url: "http://stream4.qqmusic.qq.com:0/1092641.wma", 932 | songName: "我想大声告诉你", 933 | singerId: "15798", 934 | singerName: "樊凡", 935 | albumId: "92824", 936 | albumName: "我想大声告诉你", 937 | albumLink: "/musicbox/shop/v3/album/24/album_92824.htm", 938 | playtime: "275" 939 | }, 940 | { 941 | id: "797241", 942 | type: 3, 943 | url: "http://stream9.qqmusic.qq.com:0/797241.wma", 944 | songName: "暖暖", 945 | singerId: "44", 946 | singerName: "梁静茹", 947 | albumId: "67399", 948 | albumName: "现在开始我爱你(Disc2)", 949 | albumLink: "/musicbox/shop/v3/album/99/album_67399.htm", 950 | playtime: "243" 951 | }, 952 | { 953 | id: "1414751", 954 | type: 3, 955 | url: "http://stream4.qqmusic.qq.com:0/1414751.wma", 956 | songName: "慢慢", 957 | singerId: "174", 958 | singerName: "张学友", 959 | albumId: "20164", 960 | albumName: "Black & White", 961 | albumLink: "/musicbox/shop/v3/album/64/album_20164.htm", 962 | playtime: "282" 963 | }, 964 | { 965 | id: "1739275", 966 | type: 3, 967 | url: "http://stream1.qqmusic.qq.com:0/1739275.wma", 968 | songName: "哥有老婆", 969 | singerId: "64495", 970 | singerName: "纪晓斌", 971 | albumId: "137331", 972 | albumName: "哥有老婆", 973 | albumLink: "/musicbox/shop/v3/album/31/album_137331.htm", 974 | playtime: "239" 975 | }, 976 | { 977 | id: "1050795", 978 | type: 3, 979 | url: "http://stream7.qqmusic.qq.com:0/1050795.wma", 980 | songName: "多喜欢你", 981 | singerId: "16292", 982 | singerName: "小贱", 983 | albumId: "89627", 984 | albumName: "多喜欢你", 985 | albumLink: "/musicbox/shop/v3/album/27/album_89627.htm", 986 | playtime: "237" 987 | }, 988 | { 989 | id: "1363973", 990 | type: 3, 991 | url: "http://stream4.qqmusic.qq.com:0/1363973.wma", 992 | songName: "Someone Like You", 993 | singerId: "12578", 994 | singerName: "Adele", 995 | albumId: "110534", 996 | albumName: "21(Japan Bonus Track Version)", 997 | albumLink: "/musicbox/shop/v3/album/34/album_110534.htm", 998 | playtime: "287" 999 | }, 1000 | { 1001 | id: "231008", 1002 | type: 3, 1003 | url: "http://stream9.qqmusic.qq.com:0/231008.wma", 1004 | songName: "只想一生跟你走", 1005 | singerId: "174", 1006 | singerName: "张学友", 1007 | albumId: "20178", 1008 | albumName: "一生跟你走 (年度代表作品辑)", 1009 | albumLink: "/musicbox/shop/v3/album/78/album_20178.htm", 1010 | playtime: "313" 1011 | }, 1012 | { 1013 | id: "410316", 1014 | type: 3, 1015 | url: "http://stream8.qqmusic.qq.com:0/410316.wma", 1016 | songName: "青花瓷", 1017 | singerId: "4558", 1018 | singerName: "周杰伦", 1019 | albumId: "33021", 1020 | albumName: "我很忙", 1021 | albumLink: "/musicbox/shop/v3/album/21/album_33021.htm", 1022 | playtime: "239" 1023 | }, 1024 | { 1025 | id: "1200324", 1026 | type: 3, 1027 | url: "http://stream7.qqmusic.qq.com:0/1200324.wma", 1028 | songName: "藕断丝连", 1029 | singerId: "7298", 1030 | singerName: "陈瑞", 1031 | albumId: "101397", 1032 | albumName: "把你藏心里", 1033 | albumLink: "/musicbox/shop/v3/album/97/album_101397.htm", 1034 | playtime: "291" 1035 | }, 1036 | { 1037 | id: "1191160", 1038 | type: 3, 1039 | url: "http://stream9.qqmusic.qq.com:0/1191160.wma", 1040 | songName: "兄弟抱一下", 1041 | singerId: "221", 1042 | singerName: "庞龙", 1043 | albumId: "100659", 1044 | albumName: "兄弟抱一下", 1045 | albumLink: "/musicbox/shop/v3/album/59/album_100659.htm", 1046 | playtime: "265" 1047 | }, 1048 | { 1049 | id: "678753", 1050 | type: 3, 1051 | url: "http://stream8.qqmusic.qq.com:0/678753.wma", 1052 | songName: "十一年", 1053 | singerId: "3558", 1054 | singerName: "邱永传", 1055 | albumId: "57259", 1056 | albumName: "2010年5月新歌速递", 1057 | albumLink: "/musicbox/shop/v3/album/59/album_57259.htm", 1058 | playtime: "254" 1059 | }, 1060 | { 1061 | id: "797227", 1062 | type: 3, 1063 | url: "http://stream9.qqmusic.qq.com:0/797227.wma", 1064 | songName: "可惜不是你", 1065 | singerId: "44", 1066 | singerName: "梁静茹", 1067 | albumId: "69903", 1068 | albumName: "现在开始我爱你(Disc1)", 1069 | albumLink: "/musicbox/shop/v3/album/3/album_69903.htm", 1070 | playtime: "285" 1071 | }, 1072 | { 1073 | id: "1943608", 1074 | type: 3, 1075 | url: "http://stream10.qqmusic.qq.com:0/1943608.wma", 1076 | songName: "你懂得", 1077 | singerId: "12744", 1078 | singerName: "小沈阳 沈春阳", 1079 | albumId: "151990", 1080 | albumName: "后厨 电视原声带", 1081 | albumLink: "/musicbox/shop/v3/album/90/album_151990.htm", 1082 | playtime: "274" 1083 | }, 1084 | { 1085 | id: "1518325", 1086 | type: 3, 1087 | url: "http://stream1.qqmusic.qq.com:0/1518325.wma", 1088 | songName: "Whistle", 1089 | singerId: "12740", 1090 | singerName: "Flo Rida", 1091 | albumId: "121661", 1092 | albumName: "Wild Ones", 1093 | albumLink: "/musicbox/shop/v3/album/61/album_121661.htm", 1094 | playtime: "225" 1095 | }, 1096 | { 1097 | id: "672519", 1098 | type: 3, 1099 | url: "http://stream4.qqmusic.qq.com:0/672519.wma", 1100 | songName: "眼泪的错觉", 1101 | singerId: "44275", 1102 | singerName: "王露凝", 1103 | albumId: "8930", 1104 | albumName: "2010年四月热搜歌", 1105 | albumLink: "/musicbox/shop/v3/album/30/album_8930.htm", 1106 | playtime: "223" 1107 | }, 1108 | { 1109 | id: "435848", 1110 | type: 3, 1111 | url: "http://stream10.qqmusic.qq.com:0/435848.wma", 1112 | songName: "放生", 1113 | singerId: "220", 1114 | singerName: "范逸臣", 1115 | albumId: "35459", 1116 | albumName: "无乐不作 (新歌+精选)", 1117 | albumLink: "/musicbox/shop/v3/album/59/album_35459.htm", 1118 | playtime: "272" 1119 | }, 1120 | { 1121 | id: "938054", 1122 | type: 3, 1123 | url: "http://stream4.qqmusic.qq.com:0/938054.wma", 1124 | songName: "如果爱忘了", 1125 | singerId: "7033", 1126 | singerName: "戚薇", 1127 | albumId: "79174", 1128 | albumName: "如果爱忘了", 1129 | albumLink: "/musicbox/shop/v3/album/74/album_79174.htm", 1130 | playtime: "239" 1131 | }, 1132 | { 1133 | id: "947618", 1134 | type: 3, 1135 | url: "http://stream9.qqmusic.qq.com:0/947618.wma", 1136 | songName: "你在看孤独的风景", 1137 | singerId: "4545", 1138 | singerName: "本兮", 1139 | albumId: "80239", 1140 | albumName: "你在看孤独的风景", 1141 | albumLink: "/musicbox/shop/v3/album/39/album_80239.htm", 1142 | playtime: "250" 1143 | }, 1144 | { 1145 | id: "1857290", 1146 | type: 3, 1147 | url: "http://stream5.qqmusic.qq.com:0/1857290.wma", 1148 | songName: "天天想你", 1149 | singerId: "10", 1150 | singerName: "陈绮贞", 1151 | albumId: "145135", 1152 | albumName: "夏季练习曲世界巡回演唱会录音", 1153 | albumLink: "/musicbox/shop/v3/album/35/album_145135.htm", 1154 | playtime: "256" 1155 | }, 1156 | { 1157 | id: "1769730", 1158 | type: 3, 1159 | url: "http://stream6.qqmusic.qq.com:0/1769730.wma", 1160 | songName: "大艺术家", 1161 | singerId: "227", 1162 | singerName: "蔡依林", 1163 | albumId: "139346", 1164 | albumName: "MUSE", 1165 | albumLink: "/musicbox/shop/v3/album/46/album_139346.htm", 1166 | playtime: "197" 1167 | }, 1168 | { 1169 | id: "1114377", 1170 | type: 3, 1171 | url: "http://stream5.qqmusic.qq.com:0/1114377.wma", 1172 | songName: "因为爱情", 1173 | singerId: "264", 1174 | singerName: "王菲 陈奕迅", 1175 | albumId: "94805", 1176 | albumName: "2012龙年春晚", 1177 | albumLink: "/musicbox/shop/v3/album/5/album_94805.htm", 1178 | playtime: "215" 1179 | }, 1180 | { 1181 | id: "1943208", 1182 | type: 3, 1183 | url: "http://stream2.qqmusic.qq.com:0/1943208.wma", 1184 | songName: "只爱到一半", 1185 | singerId: "11453", 1186 | singerName: "魏晨", 1187 | albumId: "149192", 1188 | albumName: "V SPACE", 1189 | albumLink: "/musicbox/shop/v3/album/92/album_149192.htm", 1190 | playtime: "257" 1191 | }, 1192 | { 1193 | id: "1889873", 1194 | type: 3, 1195 | url: "http://stream8.qqmusic.qq.com:0/1889873.wma", 1196 | songName: "缺口", 1197 | singerId: "6204", 1198 | singerName: "林凡", 1199 | albumId: "147448", 1200 | albumName: "我家有喜 电视原声带", 1201 | albumLink: "/musicbox/shop/v3/album/48/album_147448.htm", 1202 | playtime: "242" 1203 | }] 1204 | }; -------------------------------------------------------------------------------- /static/vue-animated-list.js: -------------------------------------------------------------------------------- 1 | (function (global, factory) { 2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 3 | typeof define === 'function' && define.amd ? define(factory) : 4 | (global.VueAnimatedList = factory()); 5 | }(this, function () { 'use strict'; 6 | function install (Vue) { 7 | var _ = Vue.util 8 | var transitionEndEvent = _.transitionEndEvent 9 | var addClass = _.addClass 10 | var removeClass = _.removeClass 11 | var on = _.on 12 | var off = _.off 13 | var transitionProp = _.transitionProp 14 | 15 | // patch v-for 16 | var vFor = Vue.directive('for') 17 | var diff = vFor.diff 18 | vFor.diff = function () { 19 | var needMoveTransition = prepareMoveTransition(this.frags) 20 | diff.apply(this, arguments) 21 | if (needMoveTransition) { 22 | applyMoveTransition(this.frags) 23 | } 24 | } 25 | 26 | /** 27 | * Check if move transitions are needed, and if so, 28 | * record the bounding client rects for each item. 29 | * 30 | * @param {Array|undefined} frags 31 | * @return {Boolean|undefined} 32 | */ 33 | 34 | function prepareMoveTransition (frags) { 35 | var transition = 36 | transitionEndEvent && // css transition supported? 37 | frags && frags.length && // has frags to be moved? 38 | frags[0].node.__v_trans // has transitions? 39 | if (transition) { 40 | var node = frags[0].node 41 | var moveClass = transition.id + '-move' 42 | var moving = node._pendingMoveCb 43 | var hasTransition = false 44 | if (!moving) { 45 | // sniff whether element has a transition duration for transform 46 | // with the move class applied 47 | addClass(node, moveClass) 48 | var type = transition.getCssTransitionType(moveClass) 49 | if (type === 'transition') { 50 | var computedStyles = window.getComputedStyle(node) 51 | var transitionedProps = computedStyles[transitionProp + 'Property'] 52 | if (/\btransform(,|$)/.test(transitionedProps)) { 53 | hasTransition = true 54 | } 55 | } 56 | removeClass(node, moveClass) 57 | } 58 | if (moving || hasTransition) { 59 | frags.forEach(function (frag) { 60 | frag._oldPos = frag.node.getBoundingClientRect() 61 | }) 62 | return true 63 | } 64 | } 65 | } 66 | 67 | /** 68 | * Apply move transitions. 69 | * Calculate new target positions after the move, then apply the 70 | * FLIP technique to trigger CSS transforms. 71 | * 72 | * @param {Array} frags 73 | */ 74 | 75 | function applyMoveTransition (frags) { 76 | frags.forEach(function (frag) { 77 | frag._newPos = frag.node.getBoundingClientRect() 78 | }) 79 | frags.forEach(function (frag) { 80 | var node = frag.node 81 | var oldPos = frag._oldPos 82 | if (!oldPos) return 83 | if (!frag.moved) { 84 | // transition busting to ensure correct bounding rect: 85 | // if an element has an ongoing transition and not "reinserted", 86 | // the bounding rect will not be calculated at its target position, 87 | // but rather an in-transition position. 88 | var p = node.parentNode 89 | var next = node.nextSibling 90 | p.removeChild(node) 91 | p.insertBefore(node, next) 92 | } 93 | var dx = oldPos.left - frag._newPos.left 94 | var dy = oldPos.top - frag._newPos.top 95 | if (dx !== 0 || dy !== 0) { 96 | frag.moved = true 97 | node.style.transform = 98 | node.style.WebkitTransform = 99 | 'translate(' + dx + 'px, ' + dy + 'px)' 100 | node.style.transitionDuration = '0s' 101 | } else { 102 | frag.moved = false 103 | } 104 | }) 105 | Vue.nextTick(function () { 106 | var f = document.documentElement.offsetHeight 107 | frags.forEach(function (frag) { 108 | var node = frag.node 109 | var moveClass = node.__v_trans.id + '-move' 110 | if (frag.moved) { 111 | addClass(node, moveClass) 112 | node.style.transform = node.style.WebkitTransform = '' 113 | node.style.transitionDuration = '' 114 | if (node._pendingMoveCb) { 115 | off(node, transitionEndEvent, node._pendingMoveCb) 116 | } 117 | node._pendingMoveCb = function cb () { 118 | off(node, transitionEndEvent, cb) 119 | node._pendingMoveCb = null 120 | removeClass(node, moveClass) 121 | } 122 | on(node, transitionEndEvent, node._pendingMoveCb) 123 | } 124 | }) 125 | }) 126 | } 127 | } 128 | 129 | if (typeof Vue !== 'undefined') { 130 | Vue.use(install) 131 | } 132 | return install 133 | })); 134 | --------------------------------------------------------------------------------