├── .babelrc ├── .editorconfig ├── .gitignore ├── .postcssrc.js ├── README.md ├── build ├── build.js ├── check-versions.js ├── logo.png ├── utils.js ├── vue-loader.conf.js ├── webpack.base.conf.js ├── webpack.dev.conf.js └── webpack.prod.conf.js ├── config ├── dev.env.js ├── index.js └── prod.env.js ├── index.html ├── package-lock.json ├── package.json ├── src ├── App.vue ├── components │ ├── comment │ │ └── index.vue │ └── swiper │ │ └── index.vue ├── css │ └── common.less ├── images │ ├── load_err.jpg │ ├── loading.gif │ ├── menu1.png │ ├── menu2.png │ ├── menu3.png │ ├── menu4.png │ ├── menu5.png │ └── menu6.png ├── lib │ └── mui │ │ ├── css │ │ ├── icons-extra.css │ │ ├── mui.css │ │ └── mui.min.css │ │ ├── fonts │ │ ├── mui-icons-extra.ttf │ │ └── mui.ttf │ │ └── js │ │ ├── mui.js │ │ └── mui.min.js ├── main.js ├── pages │ ├── goodsList │ │ └── index.vue │ ├── home │ │ └── index.vue │ ├── member │ │ └── index.vue │ ├── newsInfo │ │ └── index.vue │ ├── newsList │ │ └── index.vue │ ├── photoList │ │ └── index.vue │ ├── search │ │ └── index.vue │ └── shopcar │ │ └── index.vue └── router │ └── index.js ├── static └── .gitkeep ├── 笔记(汇总).zip └── 笔记(汇总) ├── Vue基础-day01.md ├── Vue基础-day02.md ├── Vue基础-day03.md ├── Vue基础-day04.md ├── Vue基础-day05.md ├── Vue项目.md ├── img ├── day01 │ ├── MVVM.png │ ├── 为什么学习vue.png │ ├── 回车添加数据.png │ ├── 案例效果图.png │ └── 添加数据.png ├── day02 │ ├── jsonp跨域原理解析.png │ ├── transition结合css实现过渡.png │ ├── 响应报文.png │ └── 请求报文.png ├── day03 │ ├── template创建组件.png │ ├── vue-router传参.png │ ├── vue-router传参页面.png │ ├── vue.extend和vuecomponent创建组件.png │ ├── vuecomponent创建组件.png │ ├── webpack是什么.png │ ├── 动态组件.png │ ├── 动态组件页面.png │ ├── 子组件传值给父组件.png │ ├── 子组件传值给父组件页面.png │ ├── 父子组件.png │ ├── 父组件传值给子组件.png │ ├── 父组件传值给子组件页面.png │ ├── 组件中指令和事件的使用.png │ ├── 路由入门.png │ ├── 路由入门页面.png │ ├── 路由嵌套.png │ └── 路由嵌套页面.png └── vuex.png └── vue基础大纲.xmind /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime", ["component", [ 12 | { 13 | "libraryName": "mint-ui", 14 | "style": true 15 | } 16 | ]]], 17 | "ignore": [ 18 | "./src/lib/mui/js/*.js" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.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 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Editor directories and files 9 | .idea 10 | .vscode 11 | *.suo 12 | *.ntvs* 13 | *.njsproj 14 | *.sln 15 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | "postcss-import": {}, 6 | "postcss-url": {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | "autoprefixer": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-cms 2 | 3 | > 这是一个cms学习项目 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:3000 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | 17 | # build for production and view the bundle analyzer report 18 | npm run build --report 19 | ``` 20 | 21 | ## 修改首页tabBar图标 22 | 23 | 1. 找到mui的扩展图标库 24 | 2. 将扩展图标库拷贝到项目中(连带字体文件一起拷贝) 25 | 3. 在main.js中引入字体图标的样式文件 26 | 4. 使用字体图标 27 | 28 | ## 设置当前选中的tab栏高亮 29 | 30 | - 结合路由的`linkActiveClass`属性完成使用`mui-active`类样式的高亮 31 | 32 | ## 配置路由规则实现路由跳转 33 | 34 | - 项目文件的结构注意事项, 可以参考现有的开源项目, 更方便的管理自己的文件结构 35 | 36 | - 参考结构: 37 | 38 | src => pages => home => index.vue 39 | 40 | 配置路由规则: 41 | 42 | ```javascript 43 | import HomeComponent from '../pages/home/' 44 | import MemberComponent from '../pages/member/' 45 | import ShopcarComponent from '../pages/shopcar/' 46 | import SearchComponent from '../pages/search/' 47 | 48 | Vue.use(Router) 49 | 50 | export default new Router({ 51 | routes: [ 52 | { path: '/', redirect: '/home' }, 53 | { path: '/home', component: HomeComponent }, 54 | { path: '/member', component: MemberComponent }, 55 | { path: '/shopcar', component: ShopcarComponent }, 56 | { path: '/search', component: SearchComponent }, 57 | ], 58 | linkActiveClass: 'mui-active' 59 | }) 60 | ``` 61 | 62 | ## 制作首页轮播图 63 | 64 | 1. 通过mint-ui的swipe组件完成样式 65 | 2. 使用vue-resource获取接口中的数据, 进行渲染 66 | 67 | ## 首页九宫格的样式改造 68 | 69 | - 由于mint-ui没有合适的组件可供参考, 所以我们使用mui的代码片段作为改造的基础模板 70 | - 修改结构并覆盖mui的默认样式 71 | - 抽取全局的common.less样式, 通过main.js引入 72 | 73 | ## 添加组件切换动画 74 | 75 | - 切换动画的起点和终点不同, 所以单独设置v-enter和v-leave-to的样式 76 | 77 | ```css 78 | .v-enter { 79 | transform: translateX(100%); 80 | opacity: 0; 81 | } 82 | 83 | .v-leave-to { 84 | position: absolute; 85 | transform: translateX(-100%); 86 | opacity: 0; 87 | } 88 | 89 | .v-enter-active, 90 | .v-leave-active { 91 | transition: all 0.6s ease; 92 | } 93 | ``` -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | require('./check-versions')() 3 | 4 | process.env.NODE_ENV = 'production' 5 | 6 | const ora = require('ora') 7 | const rm = require('rimraf') 8 | const path = require('path') 9 | const chalk = require('chalk') 10 | const webpack = require('webpack') 11 | const config = require('../config') 12 | const webpackConfig = require('./webpack.prod.conf') 13 | 14 | const spinner = ora('building for production...') 15 | spinner.start() 16 | 17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 18 | if (err) throw err 19 | webpack(webpackConfig, (err, stats) => { 20 | spinner.stop() 21 | if (err) throw err 22 | process.stdout.write(stats.toString({ 23 | colors: true, 24 | modules: false, 25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. 26 | chunks: false, 27 | chunkModules: false 28 | }) + '\n\n') 29 | 30 | if (stats.hasErrors()) { 31 | console.log(chalk.red(' Build failed with errors.\n')) 32 | process.exit(1) 33 | } 34 | 35 | console.log(chalk.cyan(' Build complete.\n')) 36 | console.log(chalk.yellow( 37 | ' Tip: built files are meant to be served over an HTTP server.\n' + 38 | ' Opening index.html over file:// won\'t work.\n' 39 | )) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /build/check-versions.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const chalk = require('chalk') 3 | const semver = require('semver') 4 | const packageConfig = require('../package.json') 5 | const shell = require('shelljs') 6 | 7 | function exec (cmd) { 8 | return require('child_process').execSync(cmd).toString().trim() 9 | } 10 | 11 | const versionRequirements = [ 12 | { 13 | name: 'node', 14 | currentVersion: semver.clean(process.version), 15 | versionRequirement: packageConfig.engines.node 16 | } 17 | ] 18 | 19 | if (shell.which('npm')) { 20 | versionRequirements.push({ 21 | name: 'npm', 22 | currentVersion: exec('npm --version'), 23 | versionRequirement: packageConfig.engines.npm 24 | }) 25 | } 26 | 27 | module.exports = function () { 28 | const warnings = [] 29 | 30 | for (let i = 0; i < versionRequirements.length; i++) { 31 | const mod = versionRequirements[i] 32 | 33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 34 | warnings.push(mod.name + ': ' + 35 | chalk.red(mod.currentVersion) + ' should be ' + 36 | chalk.green(mod.versionRequirement) 37 | ) 38 | } 39 | } 40 | 41 | if (warnings.length) { 42 | console.log('') 43 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 44 | console.log() 45 | 46 | for (let i = 0; i < warnings.length; i++) { 47 | const warning = warnings[i] 48 | console.log(' ' + warning) 49 | } 50 | 51 | console.log() 52 | process.exit(1) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /build/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/build/logo.png -------------------------------------------------------------------------------- /build/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const config = require('../config') 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 5 | const packageConfig = require('../package.json') 6 | 7 | exports.assetsPath = function (_path) { 8 | const assetsSubDirectory = process.env.NODE_ENV === 'production' 9 | ? config.build.assetsSubDirectory 10 | : config.dev.assetsSubDirectory 11 | 12 | return path.posix.join(assetsSubDirectory, _path) 13 | } 14 | 15 | exports.cssLoaders = function (options) { 16 | options = options || {} 17 | 18 | const cssLoader = { 19 | loader: 'css-loader', 20 | options: { 21 | sourceMap: options.sourceMap 22 | } 23 | } 24 | 25 | const postcssLoader = { 26 | loader: 'postcss-loader', 27 | options: { 28 | sourceMap: options.sourceMap 29 | } 30 | } 31 | 32 | // generate loader string to be used with extract text plugin 33 | function generateLoaders (loader, loaderOptions) { 34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] 35 | 36 | if (loader) { 37 | loaders.push({ 38 | loader: loader + '-loader', 39 | options: Object.assign({}, loaderOptions, { 40 | sourceMap: options.sourceMap 41 | }) 42 | }) 43 | } 44 | 45 | // Extract CSS when that option is specified 46 | // (which is the case during production build) 47 | if (options.extract) { 48 | return ExtractTextPlugin.extract({ 49 | use: loaders, 50 | fallback: 'vue-style-loader' 51 | }) 52 | } else { 53 | return ['vue-style-loader'].concat(loaders) 54 | } 55 | } 56 | 57 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html 58 | return { 59 | css: generateLoaders(), 60 | postcss: generateLoaders(), 61 | less: generateLoaders('less'), 62 | sass: generateLoaders('sass', { indentedSyntax: true }), 63 | scss: generateLoaders('sass'), 64 | stylus: generateLoaders('stylus'), 65 | styl: generateLoaders('stylus') 66 | } 67 | } 68 | 69 | // Generate loaders for standalone style files (outside of .vue) 70 | exports.styleLoaders = function (options) { 71 | const output = [] 72 | const loaders = exports.cssLoaders(options) 73 | 74 | for (const extension in loaders) { 75 | const loader = loaders[extension] 76 | output.push({ 77 | test: new RegExp('\\.' + extension + '$'), 78 | use: loader 79 | }) 80 | } 81 | 82 | return output 83 | } 84 | 85 | exports.createNotifierCallback = () => { 86 | const notifier = require('node-notifier') 87 | 88 | return (severity, errors) => { 89 | if (severity !== 'error') return 90 | 91 | const error = errors[0] 92 | const filename = error.file && error.file.split('!').pop() 93 | 94 | notifier.notify({ 95 | title: packageConfig.name, 96 | message: severity + ': ' + error.name, 97 | subtitle: filename || '', 98 | icon: path.join(__dirname, 'logo.png') 99 | }) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const config = require('../config') 4 | const isProduction = process.env.NODE_ENV === 'production' 5 | const sourceMapEnabled = isProduction 6 | ? config.build.productionSourceMap 7 | : config.dev.cssSourceMap 8 | 9 | module.exports = { 10 | loaders: utils.cssLoaders({ 11 | sourceMap: sourceMapEnabled, 12 | extract: isProduction 13 | }), 14 | cssSourceMap: sourceMapEnabled, 15 | cacheBusting: config.dev.cacheBusting, 16 | transformToRequire: { 17 | video: ['src', 'poster'], 18 | source: 'src', 19 | img: 'src', 20 | image: 'xlink:href' 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const config = require('../config') 5 | const vueLoaderConfig = require('./vue-loader.conf') 6 | 7 | function resolve(dir) { 8 | return path.join(__dirname, '..', dir) 9 | } 10 | 11 | 12 | 13 | module.exports = { 14 | context: path.resolve(__dirname, '../'), 15 | entry: { 16 | app: './src/main.js' 17 | }, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: '[name].js', 21 | publicPath: process.env.NODE_ENV === 'production' 22 | ? config.build.assetsPublicPath 23 | : config.dev.assetsPublicPath 24 | }, 25 | resolve: { 26 | extensions: ['.js', '.vue', '.json'], 27 | alias: { 28 | '@': resolve('src'), 29 | } 30 | }, 31 | module: { 32 | rules: [ 33 | { 34 | test: /\.vue$/, 35 | loader: 'vue-loader', 36 | options: vueLoaderConfig 37 | }, 38 | { 39 | test: /\.js$/, 40 | loader: 'babel-loader', 41 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] 42 | }, 43 | { 44 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 45 | loader: 'url-loader', 46 | options: { 47 | limit: 10000, 48 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 49 | } 50 | }, 51 | { 52 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 53 | loader: 'url-loader', 54 | options: { 55 | limit: 10000, 56 | name: utils.assetsPath('media/[name].[hash:7].[ext]') 57 | } 58 | }, 59 | { 60 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 61 | loader: 'url-loader', 62 | options: { 63 | limit: 10000, 64 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 65 | } 66 | }, 67 | { 68 | test: /vue-preview.src.*?js$/, 69 | loader: 'babel' 70 | } 71 | ] 72 | }, 73 | node: { 74 | // prevent webpack from injecting useless setImmediate polyfill because Vue 75 | // source contains it (although only uses it if it's native). 76 | setImmediate: false, 77 | // prevent webpack from injecting mocks to Node native modules 78 | // that does not make sense for the client 79 | dgram: 'empty', 80 | fs: 'empty', 81 | net: 'empty', 82 | tls: 'empty', 83 | child_process: 'empty' 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const webpack = require('webpack') 4 | const config = require('../config') 5 | const merge = require('webpack-merge') 6 | const path = require('path') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 11 | const portfinder = require('portfinder') 12 | 13 | const HOST = process.env.HOST 14 | const PORT = process.env.PORT && Number(process.env.PORT) 15 | 16 | const devWebpackConfig = merge(baseWebpackConfig, { 17 | module: { 18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) 19 | }, 20 | // cheap-module-eval-source-map is faster for development 21 | devtool: config.dev.devtool, 22 | 23 | // these devServer options should be customized in /config/index.js 24 | devServer: { 25 | clientLogLevel: 'warning', 26 | historyApiFallback: { 27 | rewrites: [ 28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, 29 | ], 30 | }, 31 | hot: true, 32 | contentBase: false, // since we use CopyWebpackPlugin. 33 | compress: true, 34 | host: HOST || config.dev.host, 35 | port: PORT || config.dev.port, 36 | open: config.dev.autoOpenBrowser, 37 | overlay: config.dev.errorOverlay 38 | ? { warnings: false, errors: true } 39 | : false, 40 | publicPath: config.dev.assetsPublicPath, 41 | proxy: config.dev.proxyTable, 42 | quiet: true, // necessary for FriendlyErrorsPlugin 43 | watchOptions: { 44 | poll: config.dev.poll, 45 | } 46 | }, 47 | plugins: [ 48 | new webpack.DefinePlugin({ 49 | 'process.env': require('../config/dev.env') 50 | }), 51 | new webpack.HotModuleReplacementPlugin(), 52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. 53 | new webpack.NoEmitOnErrorsPlugin(), 54 | // https://github.com/ampedandwired/html-webpack-plugin 55 | new HtmlWebpackPlugin({ 56 | filename: 'index.html', 57 | template: 'index.html', 58 | inject: true 59 | }), 60 | // copy custom static assets 61 | new CopyWebpackPlugin([ 62 | { 63 | from: path.resolve(__dirname, '../static'), 64 | to: config.dev.assetsSubDirectory, 65 | ignore: ['.*'] 66 | } 67 | ]) 68 | ] 69 | }) 70 | 71 | module.exports = new Promise((resolve, reject) => { 72 | portfinder.basePort = process.env.PORT || config.dev.port 73 | portfinder.getPort((err, port) => { 74 | if (err) { 75 | reject(err) 76 | } else { 77 | // publish the new Port, necessary for e2e tests 78 | process.env.PORT = port 79 | // add port to devServer config 80 | devWebpackConfig.devServer.port = port 81 | 82 | // Add FriendlyErrorsPlugin 83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ 84 | compilationSuccessInfo: { 85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], 86 | }, 87 | onErrors: config.dev.notifyOnErrors 88 | ? utils.createNotifierCallback() 89 | : undefined 90 | })) 91 | 92 | resolve(devWebpackConfig) 93 | } 94 | }) 95 | }) 96 | -------------------------------------------------------------------------------- /build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const webpack = require('webpack') 5 | const config = require('../config') 6 | const merge = require('webpack-merge') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') 12 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin') 13 | 14 | const env = require('../config/prod.env') 15 | 16 | const webpackConfig = merge(baseWebpackConfig, { 17 | module: { 18 | rules: utils.styleLoaders({ 19 | sourceMap: config.build.productionSourceMap, 20 | extract: true, 21 | usePostCSS: true 22 | }), 23 | 24 | }, 25 | devtool: config.build.productionSourceMap ? config.build.devtool : false, 26 | output: { 27 | path: config.build.assetsRoot, 28 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 29 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 30 | }, 31 | plugins: [ 32 | // http://vuejs.github.io/vue-loader/en/workflow/production.html 33 | new webpack.DefinePlugin({ 34 | 'process.env': env 35 | }), 36 | new UglifyJsPlugin({ 37 | uglifyOptions: { 38 | compress: { 39 | warnings: false 40 | } 41 | }, 42 | sourceMap: config.build.productionSourceMap, 43 | parallel: true 44 | }), 45 | // extract css into its own file 46 | new ExtractTextPlugin({ 47 | filename: utils.assetsPath('css/[name].[contenthash].css'), 48 | // Setting the following option to `false` will not extract CSS from codesplit chunks. 49 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack. 50 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, 51 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110 52 | allChunks: true, 53 | }), 54 | // Compress extracted CSS. We are using this plugin so that possible 55 | // duplicated CSS from different components can be deduped. 56 | new OptimizeCSSPlugin({ 57 | cssProcessorOptions: config.build.productionSourceMap 58 | ? { safe: true, map: { inline: false } } 59 | : { safe: true } 60 | }), 61 | // generate dist index.html with correct asset hash for caching. 62 | // you can customize output by editing /index.html 63 | // see https://github.com/ampedandwired/html-webpack-plugin 64 | new HtmlWebpackPlugin({ 65 | filename: config.build.index, 66 | template: 'index.html', 67 | inject: true, 68 | minify: { 69 | removeComments: true, 70 | collapseWhitespace: true, 71 | removeAttributeQuotes: true 72 | // more options: 73 | // https://github.com/kangax/html-minifier#options-quick-reference 74 | }, 75 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 76 | chunksSortMode: 'dependency' 77 | }), 78 | // keep module.id stable when vendor modules does not change 79 | new webpack.HashedModuleIdsPlugin(), 80 | // enable scope hoisting 81 | new webpack.optimize.ModuleConcatenationPlugin(), 82 | // split vendor js into its own file 83 | new webpack.optimize.CommonsChunkPlugin({ 84 | name: 'vendor', 85 | minChunks (module) { 86 | // any required modules inside node_modules are extracted to vendor 87 | return ( 88 | module.resource && 89 | /\.js$/.test(module.resource) && 90 | module.resource.indexOf( 91 | path.join(__dirname, '../node_modules') 92 | ) === 0 93 | ) 94 | } 95 | }), 96 | // extract webpack runtime and module manifest to its own file in order to 97 | // prevent vendor hash from being updated whenever app bundle is updated 98 | new webpack.optimize.CommonsChunkPlugin({ 99 | name: 'manifest', 100 | minChunks: Infinity 101 | }), 102 | // This instance extracts shared chunks from code splitted chunks and bundles them 103 | // in a separate chunk, similar to the vendor chunk 104 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk 105 | new webpack.optimize.CommonsChunkPlugin({ 106 | name: 'app', 107 | async: 'vendor-async', 108 | children: true, 109 | minChunks: 3 110 | }), 111 | 112 | // copy custom static assets 113 | new CopyWebpackPlugin([ 114 | { 115 | from: path.resolve(__dirname, '../static'), 116 | to: config.build.assetsSubDirectory, 117 | ignore: ['.*'] 118 | } 119 | ]) 120 | ] 121 | }) 122 | 123 | if (config.build.productionGzip) { 124 | const CompressionWebpackPlugin = require('compression-webpack-plugin') 125 | 126 | webpackConfig.plugins.push( 127 | new CompressionWebpackPlugin({ 128 | asset: '[path].gz[query]', 129 | algorithm: 'gzip', 130 | test: new RegExp( 131 | '\\.(' + 132 | config.build.productionGzipExtensions.join('|') + 133 | ')$' 134 | ), 135 | threshold: 10240, 136 | minRatio: 0.8 137 | }) 138 | ) 139 | } 140 | 141 | if (config.build.bundleAnalyzerReport) { 142 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 143 | webpackConfig.plugins.push(new BundleAnalyzerPlugin()) 144 | } 145 | 146 | module.exports = webpackConfig 147 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.3.1 3 | // see http://vuejs-templates.github.io/webpack for documentation. 4 | 5 | const path = require('path') 6 | 7 | module.exports = { 8 | dev: { 9 | 10 | // Paths 11 | assetsSubDirectory: 'static', 12 | assetsPublicPath: '/', 13 | proxyTable: {}, 14 | 15 | // Various Dev Server settings 16 | host: 'localhost', // can be overwritten by process.env.HOST 17 | port: 3000, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 18 | autoOpenBrowser: true, 19 | errorOverlay: true, 20 | notifyOnErrors: true, 21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 22 | 23 | 24 | /** 25 | * Source Maps 26 | */ 27 | 28 | // https://webpack.js.org/configuration/devtool/#development 29 | devtool: 'cheap-module-eval-source-map', 30 | 31 | // If you have problems debugging vue-files in devtools, 32 | // set this to false - it *may* help 33 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 34 | cacheBusting: true, 35 | 36 | cssSourceMap: true 37 | }, 38 | 39 | build: { 40 | // Template for index.html 41 | index: path.resolve(__dirname, '../dist/index.html'), 42 | 43 | // Paths 44 | assetsRoot: path.resolve(__dirname, '../dist'), 45 | assetsSubDirectory: 'static', 46 | assetsPublicPath: '/', 47 | 48 | /** 49 | * Source Maps 50 | */ 51 | 52 | productionSourceMap: true, 53 | // https://webpack.js.org/configuration/devtool/#production 54 | devtool: '#source-map', 55 | 56 | // Gzip off by default as many popular static hosts such as 57 | // Surge or Netlify already gzip all static assets for you. 58 | // Before setting to `true`, make sure to: 59 | // npm install --save-dev compression-webpack-plugin 60 | productionGzip: false, 61 | productionGzipExtensions: ['js', 'css'], 62 | 63 | // Run the build command with an extra argument to 64 | // View the bundle analyzer report after build finishes: 65 | // `npm run build --report` 66 | // Set to `true` or `false` to always turn it on or off 67 | bundleAnalyzerReport: process.env.npm_config_report 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue CMS 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-cms", 3 | "version": "1.0.0", 4 | "description": "Just cms", 5 | "author": "TianchengLee ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "start": "npm run dev", 10 | "build": "node build/build.js" 11 | }, 12 | "dependencies": { 13 | "ajv": "^6.5.5", 14 | "mint-ui": "^2.2.13", 15 | "moment": "^2.22.2", 16 | "vue": "^2.5.2", 17 | "vue-resource": "^1.5.1", 18 | "vue-router": "^3.0.1", 19 | "vue2-preview": "^1.0.2" 20 | }, 21 | "devDependencies": { 22 | "autoprefixer": "^7.1.2", 23 | "babel-core": "^6.22.1", 24 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 25 | "babel-loader": "^7.1.1", 26 | "babel-plugin-component": "^1.1.1", 27 | "babel-plugin-syntax-jsx": "^6.18.0", 28 | "babel-plugin-transform-runtime": "^6.22.0", 29 | "babel-plugin-transform-vue-jsx": "^3.5.0", 30 | "babel-preset-env": "^1.3.2", 31 | "babel-preset-stage-2": "^6.22.0", 32 | "chalk": "^2.0.1", 33 | "copy-webpack-plugin": "^4.0.1", 34 | "css-loader": "^0.28.11", 35 | "extract-text-webpack-plugin": "^3.0.0", 36 | "file-loader": "^1.1.4", 37 | "friendly-errors-webpack-plugin": "^1.6.1", 38 | "html-webpack-plugin": "^2.30.1", 39 | "less": "^3.8.1", 40 | "less-loader": "^4.1.0", 41 | "node-notifier": "^5.1.2", 42 | "optimize-css-assets-webpack-plugin": "^3.2.0", 43 | "ora": "^1.2.0", 44 | "portfinder": "^1.0.13", 45 | "postcss-import": "^11.0.0", 46 | "postcss-loader": "^2.0.8", 47 | "postcss-url": "^7.2.1", 48 | "rimraf": "^2.6.0", 49 | "semver": "^5.3.0", 50 | "shelljs": "^0.7.6", 51 | "style-loader": "^0.23.1", 52 | "uglifyjs-webpack-plugin": "^1.1.1", 53 | "url-loader": "^0.5.8", 54 | "vue-lazyload": "^1.2.6", 55 | "vue-loader": "^13.3.0", 56 | "vue-style-loader": "^3.0.1", 57 | "vue-template-compiler": "^2.5.2", 58 | "webpack": "^3.6.0", 59 | "webpack-bundle-analyzer": "^2.9.0", 60 | "webpack-dev-server": "^2.9.1", 61 | "webpack-merge": "^4.1.0" 62 | }, 63 | "engines": { 64 | "node": ">= 6.0.0", 65 | "npm": ">= 3.0.0" 66 | }, 67 | "browserslist": [ 68 | "> 1%", 69 | "last 2 versions", 70 | "not ie <= 8" 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 37 | 38 | 93 | -------------------------------------------------------------------------------- /src/components/comment/index.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 73 | 74 | 92 | -------------------------------------------------------------------------------- /src/components/swiper/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 17 | 18 | 46 | -------------------------------------------------------------------------------- /src/css/common.less: -------------------------------------------------------------------------------- 1 | html, body { 2 | background: #FFF; 3 | } 4 | 5 | body, 6 | div, 7 | dl, 8 | dt, 9 | dd, 10 | ul, 11 | ol, 12 | li, 13 | h1, 14 | h2, 15 | h3, 16 | h4, 17 | h5, 18 | h6, 19 | pre, 20 | code, 21 | form, 22 | fieldset, 23 | legend, 24 | input, 25 | textarea, 26 | p, 27 | blockquote, 28 | th, 29 | td { 30 | margin: 0; 31 | padding: 0; 32 | } 33 | 34 | table { 35 | border-collapse: collapse; 36 | border-spacing: 0; 37 | } 38 | 39 | fieldset, 40 | img { 41 | border: 0; 42 | } 43 | 44 | address, 45 | caption, 46 | cite, 47 | code, 48 | dfn, 49 | em, 50 | strong, 51 | th, 52 | var { 53 | font-style: normal; 54 | font-weight: normal; 55 | } 56 | 57 | li { 58 | list-style: none; 59 | } 60 | 61 | caption, 62 | th { 63 | text-align: left; 64 | } 65 | 66 | h1, 67 | h2, 68 | h3, 69 | h4, 70 | h5, 71 | h6 { 72 | font-size: 100%; 73 | font-weight: normal; 74 | } 75 | 76 | q:before, 77 | q:after { 78 | content: ''; 79 | } 80 | 81 | abbr, 82 | acronym { 83 | border: 0; 84 | font-variant: normal; 85 | } 86 | 87 | sup { 88 | vertical-align: text-top; 89 | } 90 | 91 | sub { 92 | vertical-align: text-bottom; 93 | } 94 | 95 | input, 96 | textarea, 97 | select { 98 | font-family: inherit; 99 | font-size: inherit; 100 | font-weight: inherit; 101 | } 102 | 103 | input, 104 | textarea, 105 | select { 106 | *font-size: 100%; 107 | } 108 | 109 | legend { 110 | color: #000; 111 | } -------------------------------------------------------------------------------- /src/images/load_err.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/src/images/load_err.jpg -------------------------------------------------------------------------------- /src/images/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/src/images/loading.gif -------------------------------------------------------------------------------- /src/images/menu1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/src/images/menu1.png -------------------------------------------------------------------------------- /src/images/menu2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/src/images/menu2.png -------------------------------------------------------------------------------- /src/images/menu3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/src/images/menu3.png -------------------------------------------------------------------------------- /src/images/menu4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/src/images/menu4.png -------------------------------------------------------------------------------- /src/images/menu5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/src/images/menu5.png -------------------------------------------------------------------------------- /src/images/menu6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/src/images/menu6.png -------------------------------------------------------------------------------- /src/lib/mui/css/icons-extra.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: MuiiconSpread; 3 | font-weight: normal; 4 | font-style: normal; 5 | src: url("../fonts/mui-icons-extra.ttf") format("truetype"); /* iOS 4.1- */ 6 | } 7 | .mui-icon-extra 8 | { 9 | font-family: MuiiconSpread; 10 | font-size: 24px; 11 | font-weight: normal; 12 | font-style: normal; 13 | line-height: 1; 14 | display: inline-block; 15 | text-decoration: none; 16 | -webkit-font-smoothing: antialiased; 17 | } 18 | .mui-icon-extra-cold:before { content: "\e500"; } 19 | .mui-icon-extra-share:before { content: "\e200"; } 20 | .mui-icon-extra-class:before { content: "\e118"; } 21 | .mui-icon-extra-custom:before { content: "\e117"; } 22 | .mui-icon-extra-new:before { content: "\e103"; } 23 | .mui-icon-extra-card:before { content: "\e104"; } 24 | .mui-icon-extra-grech:before { content: "\e105"; } 25 | .mui-icon-extra-trend:before { content: "\e106"; } 26 | .mui-icon-extra-filter:before { content: "\e207"; } 27 | .mui-icon-extra-holiday:before { content: "\e300"; } 28 | .mui-icon-extra-cart:before { content: "\e107"; } 29 | .mui-icon-extra-heart:before { content: "\e180"; } 30 | .mui-icon-extra-computer:before { content: "\e600"; } 31 | .mui-icon-extra-express:before { content: "\e108"; } 32 | .mui-icon-extra-gift:before { content: "\e109"; } 33 | .mui-icon-extra-gold:before { content: "\e102"; } 34 | .mui-icon-extra-lamp:before { content: "\e601"; } 35 | .mui-icon-extra-rank:before { content: "\e110"; } 36 | .mui-icon-extra-notice:before { content: "\e111"; } 37 | .mui-icon-extra-sweep:before { content: "\e202"; } 38 | .mui-icon-extra-arrowleftcricle:before { content: "\e401"; } 39 | .mui-icon-extra-dictionary:before { content: "\e602"; } 40 | .mui-icon-extra-heart-filled:before { content: "\e119"; } 41 | .mui-icon-extra-xiaoshuo:before { content: "\e607"; } 42 | .mui-icon-extra-top:before { content: "\e403"; } 43 | .mui-icon-extra-people:before { content: "\e203"; } 44 | .mui-icon-extra-topic:before { content: "\e603"; } 45 | .mui-icon-extra-hotel:before { content: "\e301"; } 46 | .mui-icon-extra-like:before { content: "\e206"; } 47 | .mui-icon-extra-regist:before { content: "\e201"; } 48 | .mui-icon-extra-order:before { content: "\e113"; } 49 | .mui-icon-extra-alipay:before { content: "\e114"; } 50 | .mui-icon-extra-find:before { content: "\e400"; } 51 | .mui-icon-extra-arrowrightcricle:before { content: "\e402"; } 52 | .mui-icon-extra-calendar:before { content: "\e115"; } 53 | .mui-icon-extra-prech:before { content: "\e116"; } 54 | .mui-icon-extra-cate:before { content: "\e501"; } 55 | .mui-icon-extra-comment:before { content: "\e209"; } 56 | .mui-icon-extra-at:before { content: "\e208"; } 57 | .mui-icon-extra-addpeople:before { content: "\e204"; } 58 | .mui-icon-extra-peoples:before { content: "\e205"; } 59 | .mui-icon-extra-calc:before { content: "\e101"; } 60 | .mui-icon-extra-classroom:before { content: "\e604"; } 61 | .mui-icon-extra-phone:before { content: "\e404"; } 62 | .mui-icon-extra-university:before { content: "\e605"; } 63 | .mui-icon-extra-outline:before { content: "\e606"; } 64 | -------------------------------------------------------------------------------- /src/lib/mui/css/mui.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * ===================================================== 3 | * Mui v3.7.0 (http://dev.dcloud.net.cn/mui) 4 | * ===================================================== 5 | *//*! normalize.css v3.0.1 | MIT License | git.io/normalize */html{font-family:sans-serif;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{font:inherit;margin:0;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{margin:0 2px;padding:.35em .625em .75em;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}*{-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-user-select:none;outline:0;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent}body{font-family:"Helvetica Neue",Helvetica,sans-serif;font-size:17px;line-height:21px;color:#000;background-color:#efeff4;-webkit-overflow-scrolling:touch}a{text-decoration:none;color:#007aff}a:active{color:#0062cc}.mui-content{background-color:#efeff4;-webkit-overflow-scrolling:touch}.mui-bar-nav~.mui-content{padding-top:44px}.mui-bar-nav~.mui-content.mui-scroll-wrapper .mui-scrollbar-vertical{top:44px}.mui-bar-header-secondary~.mui-content{padding-top:88px}.mui-bar-header-secondary~.mui-content.mui-scroll-wrapper .mui-scrollbar-vertical{top:88px}.mui-bar-footer~.mui-content{padding-bottom:44px}.mui-bar-footer~.mui-content.mui-scroll-wrapper .mui-scrollbar-vertical{bottom:44px}.mui-bar-footer-secondary~.mui-content{padding-bottom:88px}.mui-bar-footer-secondary~.mui-content.mui-scroll-wrapper .mui-scrollbar-vertical{bottom:88px}.mui-bar-tab~.mui-content{padding-bottom:50px}.mui-bar-tab~.mui-content.mui-scroll-wrapper .mui-scrollbar-vertical{bottom:50px}.mui-bar-footer-secondary-tab~.mui-content{padding-bottom:94px}.mui-bar-footer-secondary-tab~.mui-content.mui-scroll-wrapper .mui-scrollbar-vertical{bottom:94px}.mui-content-padded{margin:10px}.mui-inline{display:inline-block;vertical-align:top}.mui-block{display:block!important}.mui-visibility{visibility:visible!important}.mui-hidden{display:none!important}.mui-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.mui-ellipsis-2{display:-webkit-box;overflow:hidden;white-space:normal!important;text-overflow:ellipsis;word-wrap:break-word;-webkit-line-clamp:2;-webkit-box-orient:vertical}.mui-table{display:table;width:100%;table-layout:fixed}.mui-table-cell{position:relative;display:table-cell}.mui-text-left{text-align:left!important}.mui-text-center{text-align:center!important}.mui-text-justify{text-align:justify!important}.mui-text-right{text-align:right!important}.mui-pull-left{float:left}.mui-pull-right{float:right}.mui-list-unstyled{padding-left:0;list-style:none}.mui-list-inline{margin-left:-5px;padding-left:0;list-style:none}.mui-list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}.mui-clearfix:after,.mui-clearfix:before{display:table;content:" "}.mui-clearfix:after{clear:both}.mui-bg-primary{background-color:#007aff}.mui-bg-positive{background-color:#4cd964}.mui-bg-negative{background-color:#dd524d}.mui-error{margin:88px 35px;padding:10px;border-radius:6px;background-color:#bbb}.mui-subtitle{font-size:15px}h1,h2,h3,h4,h5,h6{line-height:1;margin-top:5px;margin-bottom:5px}.mui-h1,h1{font-size:36px}.mui-h2,h2{font-size:30px}.mui-h3,h3{font-size:24px}.mui-h4,h4{font-size:18px}.mui-h5,h5{font-size:14px;font-weight:400;color:#8f8f94}.mui-h6,h6{font-size:12px;font-weight:400;color:#8f8f94}p{font-size:14px;margin-top:0;margin-bottom:10px;color:#8f8f94}.mui-row:after,.mui-row:before{display:table;content:" "}.mui-row:after{clear:both}.mui-col-sm-1,.mui-col-sm-10,.mui-col-sm-11,.mui-col-sm-12,.mui-col-sm-2,.mui-col-sm-3,.mui-col-sm-4,.mui-col-sm-5,.mui-col-sm-6,.mui-col-sm-7,.mui-col-sm-8,.mui-col-sm-9,.mui-col-xs-1,.mui-col-xs-10,.mui-col-xs-11,.mui-col-xs-12,.mui-col-xs-2,.mui-col-xs-3,.mui-col-xs-4,.mui-col-xs-5,.mui-col-xs-6,.mui-col-xs-7,.mui-col-xs-8,.mui-col-xs-9{position:relative;min-height:1px}.mui-row>[class*=mui-col-]{float:left}.mui-col-xs-12{width:100%}.mui-col-xs-11{width:91.66666667%}.mui-col-xs-10{width:83.33333333%}.mui-col-xs-9{width:75%}.mui-col-xs-8{width:66.66666667%}.mui-col-xs-7{width:58.33333333%}.mui-col-xs-6{width:50%}.mui-col-xs-5{width:41.66666667%}.mui-col-xs-4{width:33.33333333%}.mui-col-xs-3{width:25%}.mui-col-xs-2{width:16.66666667%}.mui-col-xs-1{width:8.33333333%}@media (min-width:400px){.mui-col-sm-12{width:100%}.mui-col-sm-11{width:91.66666667%}.mui-col-sm-10{width:83.33333333%}.mui-col-sm-9{width:75%}.mui-col-sm-8{width:66.66666667%}.mui-col-sm-7{width:58.33333333%}.mui-col-sm-6{width:50%}.mui-col-sm-5{width:41.66666667%}.mui-col-sm-4{width:33.33333333%}.mui-col-sm-3{width:25%}.mui-col-sm-2{width:16.66666667%}.mui-col-sm-1{width:8.33333333%}}.mui-scroll-wrapper{position:absolute;z-index:2;top:0;bottom:0;left:0;overflow:hidden;width:100%}.mui-scroll{position:absolute;z-index:1;width:100%;-webkit-transform:translateZ(0);transform:translateZ(0)}.mui-scrollbar{position:absolute;z-index:9998;overflow:hidden;-webkit-transition:500ms;transition:500ms;transform:translateZ(0px);pointer-events:none;opacity:0}.mui-scrollbar-vertical{top:0;right:1px;bottom:2px;width:4px}.mui-scrollbar-vertical .mui-scrollbar-indicator{width:100%}.mui-scrollbar-horizontal{right:2px;bottom:0;left:2px;height:4px}.mui-scrollbar-horizontal .mui-scrollbar-indicator{height:100%}.mui-scrollbar-indicator{position:absolute;display:block;box-sizing:border-box;-webkit-transition:.01s cubic-bezier(.1,.57,.1,1);transition:.01s cubic-bezier(.1,.57,.1,1);transform:translate(0px,0) translateZ(0px);border:1px solid rgba(255,255,255,.80196);border-radius:2px;background:rgba(0,0,0,.39804)}.mui-plus-pullrefresh .mui-fullscreen .mui-scroll-wrapper .mui-scroll-wrapper,.mui-plus-pullrefresh .mui-fullscreen .mui-slider-group .mui-scroll-wrapper{position:absolute;top:0;bottom:0;left:0;overflow:hidden;width:100%}.mui-plus-pullrefresh .mui-fullscreen .mui-scroll-wrapper .mui-scroll,.mui-plus-pullrefresh .mui-fullscreen .mui-slider-group .mui-scroll{position:absolute;width:100%}.mui-plus-pullrefresh .mui-scroll-wrapper,.mui-plus-pullrefresh .mui-slider-group{position:static;top:auto;bottom:auto;left:auto;overflow:auto;width:auto}.mui-plus-pullrefresh .mui-slider-group{overflow:visible}.mui-plus-pullrefresh .mui-scroll{position:static;width:auto}.mui-off-canvas-wrap .mui-bar{position:absolute!important;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-box-shadow:none;box-shadow:none}.mui-off-canvas-wrap{position:relative;z-index:1;overflow:hidden;width:100%;height:100%}.mui-off-canvas-wrap .mui-inner-wrap{position:relative;z-index:1;width:100%;height:100%}.mui-off-canvas-wrap .mui-inner-wrap.mui-transitioning{-webkit-transition:-webkit-transform 350ms;transition:transform 350ms cubic-bezier(.165,.84,.44,1)}.mui-off-canvas-wrap .mui-inner-wrap .mui-off-canvas-left{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.mui-off-canvas-wrap .mui-inner-wrap .mui-off-canvas-right{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.mui-off-canvas-wrap.mui-active{overflow:hidden;height:100%}.mui-off-canvas-wrap.mui-active .mui-off-canvas-backdrop{position:absolute;z-index:998;top:0;right:0;bottom:0;left:0;display:block;transition:background 350ms cubic-bezier(.165,.84,.44,1);background:rgba(0,0,0,.4);box-shadow:-4px 0 4px rgba(0,0,0,.5),4px 0 4px rgba(0,0,0,.5);-webkit-tap-highlight-color:transparent}.mui-off-canvas-wrap.mui-slide-in .mui-off-canvas-right{z-index:10000!important;-webkit-transform:translate3d(100%,0,0)}.mui-off-canvas-wrap.mui-slide-in .mui-off-canvas-left{z-index:10000!important;-webkit-transform:translate3d(-100%,0,0)}.mui-off-canvas-left,.mui-off-canvas-right{position:absolute;z-index:-1;top:0;bottom:0;visibility:hidden;box-sizing:content-box;width:70%;min-height:100%;background:#333;-webkit-overflow-scrolling:touch}.mui-off-canvas-left.mui-transitioning,.mui-off-canvas-right.mui-transitioning{-webkit-transition:-webkit-transform 350ms cubic-bezier(.165,.84,.44,1);transition:transform 350ms cubic-bezier(.165,.84,.44,1)}.mui-off-canvas-left{left:0}.mui-off-canvas-right{right:0}.mui-off-canvas-wrap:not(.mui-slide-in).mui-scalable{background-color:#333}.mui-off-canvas-wrap:not(.mui-slide-in).mui-scalable>.mui-off-canvas-left,.mui-off-canvas-wrap:not(.mui-slide-in).mui-scalable>.mui-off-canvas-right{width:80%;-webkit-transform:scale(.8);transform:scale(.8);opacity:.1}.mui-off-canvas-wrap:not(.mui-slide-in).mui-scalable>.mui-off-canvas-left.mui-transitioning,.mui-off-canvas-wrap:not(.mui-slide-in).mui-scalable>.mui-off-canvas-right.mui-transitioning{-webkit-transition:-webkit-transform 350ms cubic-bezier(.165,.84,.44,1),opacity 350ms cubic-bezier(.165,.84,.44,1);transition:transform 350ms cubic-bezier(.165,.84,.44,1),opacity 350ms cubic-bezier(.165,.84,.44,1)}.mui-off-canvas-wrap:not(.mui-slide-in).mui-scalable>.mui-off-canvas-left{-webkit-transform-origin:-100%;transform-origin:-100%}.mui-off-canvas-wrap:not(.mui-slide-in).mui-scalable>.mui-off-canvas-right{-webkit-transform-origin:200%;transform-origin:200%}.mui-off-canvas-wrap:not(.mui-slide-in).mui-scalable.mui-active>.mui-inner-wrap{-webkit-transform:scale(.8);transform:scale(.8)}.mui-off-canvas-wrap:not(.mui-slide-in).mui-scalable.mui-active>.mui-off-canvas-left,.mui-off-canvas-wrap:not(.mui-slide-in).mui-scalable.mui-active>.mui-off-canvas-right{-webkit-transform:scale(1);transform:scale(1);opacity:1}.mui-loading .mui-spinner{display:block;margin:0 auto}.mui-spinner{display:inline-block;width:24px;height:24px;-webkit-transform-origin:50%;transform-origin:50%;-webkit-animation:spinner-spin 1s step-end infinite;animation:spinner-spin 1s step-end infinite}.mui-spinner:after{display:block;width:100%;height:100%;content:"";background-image:url("data:image/svg+xml;charset=utf-8,");background-repeat:no-repeat;background-position:50%;background-size:100%}.mui-spinner-white:after{background-image:url("data:image/svg+xml;charset=utf-8,")}@-webkit-keyframes spinner-spin{0%{-webkit-transform:rotate(0deg)}8.33333333%{-webkit-transform:rotate(30deg)}16.66666667%{-webkit-transform:rotate(60deg)}25%{-webkit-transform:rotate(90deg)}33.33333333%{-webkit-transform:rotate(120deg)}41.66666667%{-webkit-transform:rotate(150deg)}50%{-webkit-transform:rotate(180deg)}58.33333333%{-webkit-transform:rotate(210deg)}66.66666667%{-webkit-transform:rotate(240deg)}75%{-webkit-transform:rotate(270deg)}83.33333333%{-webkit-transform:rotate(300deg)}91.66666667%{-webkit-transform:rotate(330deg)}100%{-webkit-transform:rotate(360deg)}}@keyframes spinner-spin{0%{transform:rotate(0deg)}8.33333333%{transform:rotate(30deg)}16.66666667%{transform:rotate(60deg)}25%{transform:rotate(90deg)}33.33333333%{transform:rotate(120deg)}41.66666667%{transform:rotate(150deg)}50%{transform:rotate(180deg)}58.33333333%{transform:rotate(210deg)}66.66666667%{transform:rotate(240deg)}75%{transform:rotate(270deg)}83.33333333%{transform:rotate(300deg)}91.66666667%{transform:rotate(330deg)}100%{transform:rotate(360deg)}}.mui-btn,button,input[type=button],input[type=reset],input[type=submit]{font-size:14px;font-weight:400;line-height:1.42;position:relative;display:inline-block;margin-bottom:0;padding:6px 12px;cursor:pointer;-webkit-transition:all;transition:all;-webkit-transition-timing-function:linear;transition-timing-function:linear;-webkit-transition-duration:.2s;transition-duration:.2s;text-align:center;vertical-align:top;white-space:nowrap;color:#333;border:1px solid #ccc;border-radius:3px;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:#fff;background-clip:padding-box}.mui-btn.mui-active:enabled,.mui-btn:enabled:active,button.mui-active:enabled,button:enabled:active,input[type=button].mui-active:enabled,input[type=button]:enabled:active,input[type=reset].mui-active:enabled,input[type=reset]:enabled:active,input[type=submit].mui-active:enabled,input[type=submit]:enabled:active{color:#fff;background-color:#929292}.mui-btn.mui-disabled,.mui-btn:disabled,button.mui-disabled,button:disabled,input[type=button].mui-disabled,input[type=button]:disabled,input[type=reset].mui-disabled,input[type=reset]:disabled,input[type=submit].mui-disabled,input[type=submit]:disabled{opacity:.6}.mui-btn-blue,.mui-btn-primary,input[type=submit]{color:#fff;border:1px solid #007aff;background-color:#007aff}.mui-btn-blue.mui-active:enabled,.mui-btn-blue:enabled:active,.mui-btn-primary.mui-active:enabled,.mui-btn-primary:enabled:active,input[type=submit].mui-active:enabled,input[type=submit]:enabled:active{color:#fff;border:1px solid #0062cc;background-color:#0062cc}.mui-btn-green,.mui-btn-positive,.mui-btn-success{color:#fff;border:1px solid #4cd964;background-color:#4cd964}.mui-btn-green.mui-active:enabled,.mui-btn-green:enabled:active,.mui-btn-positive.mui-active:enabled,.mui-btn-positive:enabled:active,.mui-btn-success.mui-active:enabled,.mui-btn-success:enabled:active{color:#fff;border:1px solid #2ac845;background-color:#2ac845}.mui-btn-warning,.mui-btn-yellow{color:#fff;border:1px solid #f0ad4e;background-color:#f0ad4e}.mui-btn-warning.mui-active:enabled,.mui-btn-warning:enabled:active,.mui-btn-yellow.mui-active:enabled,.mui-btn-yellow:enabled:active{color:#fff;border:1px solid #ec971f;background-color:#ec971f}.mui-btn-danger,.mui-btn-negative,.mui-btn-red{color:#fff;border:1px solid #dd524d;background-color:#dd524d}.mui-btn-danger.mui-active:enabled,.mui-btn-danger:enabled:active,.mui-btn-negative.mui-active:enabled,.mui-btn-negative:enabled:active,.mui-btn-red.mui-active:enabled,.mui-btn-red:enabled:active{color:#fff;border:1px solid #cf2d28;background-color:#cf2d28}.mui-btn-purple,.mui-btn-royal{color:#fff;border:1px solid #8a6de9;background-color:#8a6de9}.mui-btn-purple.mui-active:enabled,.mui-btn-purple:enabled:active,.mui-btn-royal.mui-active:enabled,.mui-btn-royal:enabled:active{color:#fff;border:1px solid #6641e2;background-color:#6641e2}.mui-btn-grey{color:#fff;border:1px solid #c7c7cc;background-color:#c7c7cc}.mui-btn-grey.mui-active:enabled,.mui-btn-grey:enabled:active{color:#fff;border:1px solid #acacb4;background-color:#acacb4}.mui-btn-outlined{background-color:transparent}.mui-btn-outlined.mui-btn-blue,.mui-btn-outlined.mui-btn-primary{color:#007aff}.mui-btn-outlined.mui-btn-green,.mui-btn-outlined.mui-btn-positive,.mui-btn-outlined.mui-btn-success{color:#4cd964}.mui-btn-outlined.mui-btn-warning,.mui-btn-outlined.mui-btn-yellow{color:#f0ad4e}.mui-btn-outlined.mui-btn-danger,.mui-btn-outlined.mui-btn-negative,.mui-btn-outlined.mui-btn-red{color:#dd524d}.mui-btn-outlined.mui-btn-purple,.mui-btn-outlined.mui-btn-royal{color:#8a6de9}.mui-btn-outlined.mui-btn-blue:enabled:active,.mui-btn-outlined.mui-btn-danger:enabled:active,.mui-btn-outlined.mui-btn-green:enabled:active,.mui-btn-outlined.mui-btn-negative:enabled:active,.mui-btn-outlined.mui-btn-positive:enabled:active,.mui-btn-outlined.mui-btn-primary:enabled:active,.mui-btn-outlined.mui-btn-purple:enabled:active,.mui-btn-outlined.mui-btn-red:enabled:active,.mui-btn-outlined.mui-btn-royal:enabled:active,.mui-btn-outlined.mui-btn-success:enabled:active,.mui-btn-outlined.mui-btn-warning:enabled:active,.mui-btn-outlined.mui-btn-yellow:enabled:active{color:#fff}.mui-btn-link{padding-top:6px;padding-bottom:6px;color:#007aff;border:0;background-color:transparent}.mui-btn-link.mui-active:enabled,.mui-btn-link:enabled:active{color:#0062cc;background-color:transparent}.mui-btn-block{font-size:18px;display:block;width:100%;margin-bottom:10px;padding:15px 0}.mui-btn .mui-badge{font-size:14px;margin:-2px -4px -2px 4px;background-color:rgba(0,0,0,.15)}.mui-btn .mui-badge-inverted,.mui-btn:enabled:active .mui-badge-inverted{background-color:transparent}.mui-btn-negative:enabled:active .mui-badge-inverted,.mui-btn-positive:enabled:active .mui-badge-inverted,.mui-btn-primary:enabled:active .mui-badge-inverted{color:#fff}.mui-btn-block .mui-badge{position:absolute;right:0;margin-right:10px}.mui-btn .mui-icon{font-size:inherit}.mui-btn.mui-icon{font-size:14px;line-height:1.42}.mui-btn.mui-fab{width:56px;height:56px;padding:16px;border-radius:50%;outline:0}.mui-btn.mui-fab.mui-btn-mini{width:40px;height:40px;padding:8px}.mui-btn.mui-fab .mui-icon{font-size:24px;line-height:24px;width:24px;height:24px}.mui-btn .mui-spinner{width:14px;height:14px;vertical-align:text-bottom}.mui-btn-block .mui-spinner{width:22px;height:22px}.mui-bar{position:fixed;z-index:10;right:0;left:0;height:44px;padding-right:10px;padding-left:10px;border-bottom:0;background-color:#f7f7f7;-webkit-box-shadow:0 0 1px rgba(0,0,0,.85);box-shadow:0 0 1px rgba(0,0,0,.85);-webkit-backface-visibility:hidden;backface-visibility:hidden}.mui-bar .mui-title{right:40px;left:40px;display:inline-block;overflow:hidden;width:auto;margin:0;text-overflow:ellipsis}.mui-bar .mui-backdrop{background:0 0}.mui-bar-header-secondary{top:44px}.mui-bar-footer{bottom:0}.mui-bar-footer-secondary{bottom:44px}.mui-bar-footer-secondary-tab{bottom:50px}.mui-bar-footer,.mui-bar-footer-secondary,.mui-bar-footer-secondary-tab{border-top:0}.mui-bar-transparent{top:0;background-color:rgba(247,247,247,0);-webkit-box-shadow:none;box-shadow:none}.mui-bar-nav{top:0;-webkit-box-shadow:0 1px 6px #ccc;box-shadow:0 1px 6px #ccc}.mui-bar-nav~.mui-content .mui-anchor{display:block;visibility:hidden;height:45px;margin-top:-45px}.mui-bar-nav.mui-bar .mui-icon{margin-right:-10px;margin-left:-10px;padding-right:10px;padding-left:10px}.mui-title{font-size:17px;font-weight:500;line-height:44px;position:absolute;display:block;width:100%;margin:0 -10px;padding:0;text-align:center;white-space:nowrap;color:#000}.mui-title a{color:inherit}.mui-bar-tab{bottom:0;display:table;width:100%;height:50px;padding:0;table-layout:fixed;border-top:0;border-bottom:0;-webkit-touch-callout:none}.mui-bar-tab .mui-tab-item{display:table-cell;overflow:hidden;width:1%;height:50px;text-align:center;vertical-align:middle;white-space:nowrap;text-overflow:ellipsis;color:#929292}.mui-bar-tab .mui-tab-item.mui-active{color:#007aff}.mui-bar-tab .mui-tab-item .mui-icon{top:3px;width:24px;height:24px;padding-top:0;padding-bottom:0}.mui-bar-tab .mui-tab-item .mui-icon~.mui-tab-label{font-size:11px;display:block;overflow:hidden;text-overflow:ellipsis}.mui-bar-tab .mui-tab-item .mui-icon:active{background:0 0}.mui-focusin>.mui-bar-header-secondary,.mui-focusin>.mui-bar-nav{position:absolute}.mui-focusin>.mui-bar~.mui-content{padding-bottom:0}.mui-bar .mui-btn{font-weight:400;position:relative;z-index:20;top:7px;margin-top:0;padding:6px 12px 7px}.mui-bar .mui-btn.mui-pull-right{margin-left:10px}.mui-bar .mui-btn.mui-pull-left{margin-right:10px}.mui-bar .mui-btn-link{font-size:16px;line-height:44px;top:0;padding:0;color:#007aff;border:0}.mui-bar .mui-btn-link.mui-active,.mui-bar .mui-btn-link:active{color:#0062cc}.mui-bar .mui-btn-block{font-size:16px;top:6px;margin-bottom:0;padding:5px 0}.mui-bar .mui-btn-nav.mui-pull-left{margin-left:-5px}.mui-bar .mui-btn-nav.mui-pull-left .mui-icon-left-nav{margin-right:-3px}.mui-bar .mui-btn-nav.mui-pull-right{margin-right:-5px}.mui-bar .mui-btn-nav.mui-pull-right .mui-icon-right-nav{margin-left:-3px}.mui-bar .mui-btn-nav:active{opacity:.3}.mui-bar .mui-icon{font-size:24px;position:relative;z-index:20;padding-top:10px;padding-bottom:10px}.mui-bar .mui-icon:active{opacity:.3}.mui-bar .mui-btn .mui-icon{top:1px;margin:0;padding:0}.mui-bar .mui-title .mui-icon{margin:0;padding:0}.mui-bar .mui-title .mui-icon.mui-icon-caret{top:4px;margin-left:-5px}.mui-bar input[type=search]{height:29px;margin:6px 0}.mui-bar .mui-input-row .mui-btn{padding:12px 10px}.mui-bar .mui-search:before{margin-top:-10px}.mui-bar .mui-input-row .mui-input-clear~.mui-icon-clear,.mui-bar .mui-input-row .mui-input-speech~.mui-icon-speech{top:0;right:12px}.mui-bar.mui-bar-header-secondary .mui-input-row .mui-input-clear~.mui-icon-clear,.mui-bar.mui-bar-header-secondary .mui-input-row .mui-input-speech~.mui-icon-speech{top:0;right:0}.mui-bar .mui-segmented-control{top:7px;width:auto;margin:0 auto}.mui-bar.mui-bar-header-secondary .mui-segmented-control{top:0}.mui-badge{font-size:12px;line-height:1;display:inline-block;padding:3px 6px;color:#333;border-radius:100px;background-color:rgba(0,0,0,.15)}.mui-badge.mui-badge-inverted{padding:0 5px 0 0;color:#929292;background-color:transparent}.mui-badge-blue,.mui-badge-primary{color:#fff;background-color:#007aff}.mui-badge-blue.mui-badge-inverted,.mui-badge-primary.mui-badge-inverted{color:#007aff;background-color:transparent}.mui-badge-green,.mui-badge-success{color:#fff;background-color:#4cd964}.mui-badge-green.mui-badge-inverted,.mui-badge-success.mui-badge-inverted{color:#4cd964;background-color:transparent}.mui-badge-warning,.mui-badge-yellow{color:#fff;background-color:#f0ad4e}.mui-badge-warning.mui-badge-inverted,.mui-badge-yellow.mui-badge-inverted{color:#f0ad4e;background-color:transparent}.mui-badge-danger,.mui-badge-red{color:#fff;background-color:#dd524d}.mui-badge-danger.mui-badge-inverted,.mui-badge-red.mui-badge-inverted{color:#dd524d;background-color:transparent}.mui-badge-purple,.mui-badge-royal{color:#fff;background-color:#8a6de9}.mui-badge-purple.mui-badge-inverted,.mui-badge-royal.mui-badge-inverted{color:#8a6de9;background-color:transparent}.mui-icon .mui-badge{font-size:10px;line-height:1.4;position:absolute;top:-2px;left:100%;margin-left:-10px;padding:1px 5px;color:#fff;background:red}.mui-card{font-size:14px;position:relative;overflow:hidden;margin:10px;border-radius:2px;background-color:#fff;background-clip:padding-box;box-shadow:0 1px 2px rgba(0,0,0,.3)}.mui-content>.mui-card:first-child{margin-top:15px}.mui-card .mui-input-group .mui-input-row:last-child:after,.mui-card .mui-input-group .mui-input-row:last-child:before,.mui-card .mui-input-group:after,.mui-card .mui-input-group:before{height:0}.mui-card .mui-table-view{margin-bottom:0;border-top:0;border-bottom:0;border-radius:6px}.mui-card .mui-table-view .mui-table-view-cell:first-child,.mui-card .mui-table-view .mui-table-view-divider:first-child{top:0;border-top-left-radius:6px;border-top-right-radius:6px}.mui-card .mui-table-view .mui-table-view-cell:last-child,.mui-card .mui-table-view .mui-table-view-divider:last-child{border-bottom-right-radius:6px;border-bottom-left-radius:6px}.mui-card .mui-table-view:after,.mui-card .mui-table-view:before,.mui-card>.mui-table-view>.mui-table-view-cell:last-child:after,.mui-card>.mui-table-view>.mui-table-view-cell:last-child:before{height:0}.mui-card-footer,.mui-card-header{position:relative;display:-webkit-box;display:-webkit-flex;display:flex;min-height:44px;padding:10px 15px;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.mui-card-footer .mui-card-link,.mui-card-header .mui-card-link{line-height:44px;position:relative;display:-webkit-box;display:-webkit-flex;display:flex;height:44px;margin-top:-10px;margin-bottom:-10px;-webkit-transition-duration:.3s;transition-duration:.3s;text-decoration:none;-webkit-box-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.mui-card-footer:before,.mui-card-header:after{position:absolute;top:0;right:0;left:0;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#c8c7cc}.mui-card-header{font-size:17px;border-radius:2px 2px 0 0}.mui-card-header:after{top:auto;bottom:0}.mui-card-header>img:first-child{font-size:0;line-height:0;float:left;width:34px;height:34px}.mui-card-footer{color:#6d6d72;border-radius:0 0 2px 2px}.mui-card-content{font-size:14px;position:relative}.mui-card-content-inner{position:relative;padding:15px}.mui-card-media{vertical-align:bottom;color:#fff;background-position:center;background-size:cover}.mui-card-header.mui-card-media{display:block;padding:10px}.mui-card-header.mui-card-media .mui-media-body{font-size:14px;font-weight:500;line-height:17px;margin-bottom:0;margin-left:44px;color:#333}.mui-card-header.mui-card-media .mui-media-body p{font-size:13px;margin-bottom:0}.mui-table-view{position:relative;margin-top:0;margin-bottom:0;padding-left:0;list-style:none;background-color:#fff}.mui-table-view:after{position:absolute;right:0;bottom:0;left:0;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#c8c7cc}.mui-table-view:before{position:absolute;right:0;left:0;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#c8c7cc;top:-1px}.mui-table-view-icon .mui-table-view-cell .mui-navigate-right .mui-icon{font-size:20px;margin-top:-1px;margin-right:5px;margin-left:-5px}.mui-table-view-icon .mui-table-view-cell:after{left:40px}.mui-table-view-chevron .mui-table-view-cell{padding-right:65px}.mui-table-view-chevron .mui-table-view-cell>a:not(.mui-btn){margin-right:-65px}.mui-table-view-radio .mui-table-view-cell{padding-right:65px}.mui-table-view-radio .mui-table-view-cell>a:not(.mui-btn){margin-right:-65px}.mui-table-view-radio .mui-table-view-cell .mui-navigate-right:after{font-size:30px;font-weight:600;right:9px;content:"";color:#007aff}.mui-table-view-radio .mui-table-view-cell.mui-selected .mui-navigate-right:after{content:"\e472"}.mui-table-view-inverted{color:#fff;background:#333}.mui-table-view-inverted:after{position:absolute;right:0;bottom:0;left:0;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#222}.mui-table-view-inverted:before{position:absolute;top:0;right:0;left:0;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#222}.mui-table-view-inverted .mui-table-view-cell:after{position:absolute;right:0;bottom:0;left:15px;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#222}.mui-table-view-inverted .mui-table-view-cell.mui-active,.mui-table-view-inverted .mui-table-view-cell>a:not(.mui-btn).mui-active{background-color:#242424}.mui-table-view-cell{position:relative;overflow:hidden;padding:11px 15px;-webkit-touch-callout:none}.mui-table-view-cell:after{position:absolute;right:0;bottom:0;left:15px;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#c8c7cc}.mui-table-view-cell.mui-checkbox input[type=checkbox],.mui-table-view-cell.mui-radio input[type=radio]{top:8px}.mui-table-view-cell.mui-checkbox.mui-left,.mui-table-view-cell.mui-radio.mui-left{padding-left:58px}.mui-table-view-cell.mui-active{background-color:#eee}.mui-table-view-cell:last-child:after,.mui-table-view-cell:last-child:before{height:0}.mui-table-view-cell>a:not(.mui-btn){position:relative;display:block;overflow:hidden;margin:-11px -15px;padding:inherit;white-space:nowrap;text-overflow:ellipsis;color:inherit}.mui-table-view-cell>a:not(.mui-btn).mui-active{background-color:#eee}.mui-table-view-cell p{margin-bottom:0}.mui-table-view-cell.mui-transitioning>.mui-slider-handle,.mui-table-view-cell.mui-transitioning>.mui-slider-left .mui-btn,.mui-table-view-cell.mui-transitioning>.mui-slider-right .mui-btn{-webkit-transition:-webkit-transform 300ms ease;transition:transform 300ms ease}.mui-table-view-cell.mui-active>.mui-slider-handle{background-color:#eee}.mui-table-view-cell>.mui-slider-handle{position:relative;background-color:#fff}.mui-table-view-cell>.mui-slider-handle .mui-navigate-right:after,.mui-table-view-cell>.mui-slider-handle.mui-navigate-right:after{right:0}.mui-table-view-cell>.mui-slider-handle,.mui-table-view-cell>.mui-slider-left .mui-btn,.mui-table-view-cell>.mui-slider-right .mui-btn{-webkit-transition:-webkit-transform 0ms ease;transition:transform 0ms ease}.mui-table-view-cell>.mui-slider-left,.mui-table-view-cell>.mui-slider-right{position:absolute;top:0;display:-webkit-box;display:-webkit-flex;display:flex;height:100%}.mui-table-view-cell>.mui-slider-left>.mui-btn,.mui-table-view-cell>.mui-slider-right>.mui-btn{position:relative;left:0;display:-webkit-box;display:-webkit-flex;display:flex;padding:0 30px;color:#fff;border:0;border-radius:0;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.mui-table-view-cell>.mui-slider-left>.mui-btn:after,.mui-table-view-cell>.mui-slider-right>.mui-btn:after{position:absolute;z-index:-1;top:0;width:600%;height:100%;content:"";background:inherit}.mui-table-view-cell>.mui-slider-left>.mui-btn.mui-icon,.mui-table-view-cell>.mui-slider-right>.mui-btn.mui-icon{font-size:30px}.mui-table-view-cell>.mui-slider-right{right:0;-webkit-transition:-webkit-transform 0ms ease;transition:transform 0ms ease;-webkit-transform:translateX(100%);transform:translateX(100%)}.mui-table-view-cell>.mui-slider-left{left:0;-webkit-transition:-webkit-transform 0ms ease;transition:transform 0ms ease;-webkit-transform:translateX(-100%);transform:translateX(-100%)}.mui-table-view-cell>.mui-slider-left>.mui-btn:after{right:100%;margin-right:-1px}.mui-table-view-divider{font-weight:500;position:relative;margin-top:-1px;margin-left:0;padding-top:6px;padding-bottom:6px;padding-left:15px;color:#999;background-color:#fafafa}.mui-table-view-divider:after{position:absolute;right:0;bottom:0;left:0;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#c8c7cc}.mui-table-view-divider:before{position:absolute;top:0;right:0;left:0;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#c8c7cc}.mui-table-view .mui-media,.mui-table-view .mui-media-body{overflow:hidden}.mui-table-view .mui-media-large .mui-media-object{line-height:80px;max-width:80px;height:80px}.mui-table-view .mui-media .mui-subtitle{color:#000}.mui-table-view .mui-media-object{line-height:42px;max-width:42px;height:42px}.mui-table-view .mui-media-object.mui-pull-left{margin-right:10px}.mui-table-view .mui-media-object.mui-pull-right{margin-left:10px}.mui-table-view .mui-table-view-cell.mui-media-icon .mui-media-object{line-height:29px;max-width:29px;height:29px;margin:-4px 0}.mui-table-view .mui-table-view-cell.mui-media-icon .mui-media-object img{line-height:29px;max-width:29px;height:29px}.mui-table-view .mui-table-view-cell.mui-media-icon .mui-media-object.mui-pull-left{margin-right:10px}.mui-table-view .mui-table-view-cell.mui-media-icon .mui-media-object .mui-icon{font-size:29px}.mui-table-view .mui-table-view-cell.mui-media-icon .mui-media-body:after{position:absolute;right:0;bottom:0;left:55px;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#c8c7cc}.mui-table-view .mui-table-view-cell.mui-media-icon:after{height:0!important}.mui-table-view.mui-unfold .mui-table-view-cell.mui-collapse .mui-table-view{display:block}.mui-table-view.mui-unfold .mui-table-view-cell.mui-collapse .mui-table-view:after,.mui-table-view.mui-unfold .mui-table-view-cell.mui-collapse .mui-table-view:before{height:0!important}.mui-table-view.mui-unfold .mui-table-view-cell.mui-media-icon.mui-collapse .mui-media-body:after{position:absolute;right:0;bottom:0;left:70px;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#c8c7cc}.mui-table-view-cell>.mui-badge,.mui-table-view-cell>.mui-btn,.mui-table-view-cell>.mui-switch,.mui-table-view-cell>a>.mui-badge,.mui-table-view-cell>a>.mui-btn,.mui-table-view-cell>a>.mui-switch{position:absolute;top:50%;right:15px;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.mui-table-view-cell .mui-navigate-right>.mui-badge,.mui-table-view-cell .mui-navigate-right>.mui-btn,.mui-table-view-cell .mui-navigate-right>.mui-switch,.mui-table-view-cell .mui-push-left>.mui-badge,.mui-table-view-cell .mui-push-left>.mui-btn,.mui-table-view-cell .mui-push-left>.mui-switch,.mui-table-view-cell .mui-push-right>.mui-badge,.mui-table-view-cell .mui-push-right>.mui-btn,.mui-table-view-cell .mui-push-right>.mui-switch,.mui-table-view-cell>a .mui-navigate-right>.mui-badge,.mui-table-view-cell>a .mui-navigate-right>.mui-btn,.mui-table-view-cell>a .mui-navigate-right>.mui-switch,.mui-table-view-cell>a .mui-push-left>.mui-badge,.mui-table-view-cell>a .mui-push-left>.mui-btn,.mui-table-view-cell>a .mui-push-left>.mui-switch,.mui-table-view-cell>a .mui-push-right>.mui-badge,.mui-table-view-cell>a .mui-push-right>.mui-btn,.mui-table-view-cell>a .mui-push-right>.mui-switch{right:35px}.mui-content>.mui-table-view:first-child{margin-top:15px}.mui-table-view-cell.mui-collapse .mui-table-view .mui-table-view-cell:last-child:after,.mui-table-view-cell.mui-collapse .mui-table-view:after,.mui-table-view-cell.mui-collapse .mui-table-view:before{height:0}.mui-table-view-cell.mui-collapse>.mui-navigate-right:after,.mui-table-view-cell.mui-collapse>.mui-push-right:after{content:"\e581"}.mui-table-view-cell.mui-collapse.mui-active{margin-top:-1px}.mui-table-view-cell.mui-collapse.mui-active .mui-collapse-content,.mui-table-view-cell.mui-collapse.mui-active .mui-table-view{display:block}.mui-table-view-cell.mui-collapse.mui-active>.mui-navigate-right:after,.mui-table-view-cell.mui-collapse.mui-active>.mui-push-right:after{content:"\e580"}.mui-table-view-cell.mui-collapse.mui-active .mui-table-view-cell>a:not(.mui-btn).mui-active{margin-left:-31px;padding-left:47px}.mui-table-view-cell.mui-collapse .mui-collapse-content{position:relative;display:none;overflow:hidden;margin:11px -15px -11px;padding:8px 15px;-webkit-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease;background:#fff}.mui-table-view-cell.mui-collapse .mui-collapse-content>.mui-input-group,.mui-table-view-cell.mui-collapse .mui-collapse-content>.mui-slider{width:auto;height:auto;margin:-8px -15px}.mui-table-view-cell.mui-collapse .mui-collapse-content>.mui-slider{margin:-8px -16px}.mui-table-view-cell.mui-collapse .mui-table-view{display:none;margin-top:11px;margin-right:-15px;margin-bottom:-11px;margin-left:-15px;border:0}.mui-table-view-cell.mui-collapse .mui-table-view.mui-table-view-chevron{margin-right:-65px}.mui-table-view-cell.mui-collapse .mui-table-view .mui-table-view-cell{padding-left:31px;background-position:31px 100%}.mui-table-view-cell.mui-collapse .mui-table-view .mui-table-view-cell:after{position:absolute;right:0;bottom:0;left:30px;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#c8c7cc}.mui-table-view.mui-grid-view{font-size:0;display:block;width:100%;padding:0 10px 10px 0;white-space:normal}.mui-table-view.mui-grid-view .mui-table-view-cell{font-size:17px;display:inline-block;margin-right:-4px;padding:10px 0 0 14px;text-align:center;vertical-align:middle;background:0 0}.mui-table-view.mui-grid-view .mui-table-view-cell .mui-media-object{width:100%;max-width:100%;height:auto}.mui-table-view.mui-grid-view .mui-table-view-cell>a:not(.mui-btn){margin:-10px 0 0 -14px}.mui-table-view.mui-grid-view .mui-table-view-cell>a:not(.mui-btn).mui-active,.mui-table-view.mui-grid-view .mui-table-view-cell>a:not(.mui-btn):active{background:0 0}.mui-table-view.mui-grid-view .mui-table-view-cell .mui-media-body{font-size:15px;line-height:15px;display:block;width:100%;height:15px;margin-top:8px;text-overflow:ellipsis;color:#333}.mui-table-view.mui-grid-view .mui-table-view-cell:after,.mui-table-view.mui-grid-view .mui-table-view-cell:before{height:0}.mui-grid-view.mui-grid-9{margin:0;padding:0;border-top:1px solid #eee;border-left:1px solid #eee;background-color:#f2f2f2}.mui-grid-view.mui-grid-9:after,.mui-grid-view.mui-grid-9:before{display:table;content:" "}.mui-grid-view.mui-grid-9:after{clear:both;position:static}.mui-grid-view.mui-grid-9 .mui-table-view-cell{margin:0;padding:11px 15px;vertical-align:top;border-right:1px solid #eee;border-bottom:1px solid #eee}.mui-grid-view.mui-grid-9 .mui-table-view-cell.mui-active{background-color:#eee}.mui-grid-view.mui-grid-9 .mui-table-view-cell>a:not(.mui-btn){margin:0;padding:10px 0}.mui-grid-view.mui-grid-9:before{height:0}.mui-grid-view.mui-grid-9 .mui-media{color:#797979}.mui-grid-view.mui-grid-9 .mui-media .mui-icon{font-size:2.4em;position:relative}.mui-slider-cell{position:relative}.mui-slider-cell>.mui-slider-handle{z-index:1}.mui-slider-cell>.mui-slider-left,.mui-slider-cell>.mui-slider-right{position:absolute;z-index:0;top:0;bottom:0}.mui-slider-cell>.mui-slider-left{left:0}.mui-slider-cell>.mui-slider-right{right:0}input,select,textarea{font-family:"Helvetica Neue",Helvetica,sans-serif;font-size:17px;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent}input:focus,select:focus,textarea:focus{-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent;-webkit-user-modify:read-write-plaintext-only}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{line-height:21px;width:100%;height:40px;margin-bottom:15px;padding:10px 15px;-webkit-user-select:text;border:1px solid rgba(0,0,0,.2);border-radius:3px;outline:0;background-color:#fff;-webkit-appearance:none}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{margin:0;-webkit-appearance:none}input[type=search]{font-size:16px;-webkit-box-sizing:border-box;box-sizing:border-box;height:34px;text-align:center;border:0;border-radius:6px;background-color:rgba(0,0,0,.1)}input[type=search]:focus{text-align:left}textarea{height:auto;resize:none}select{font-size:14px;height:auto;margin-top:1px;border:0!important;background-color:#fff}select:focus{-webkit-user-modify:read-only}.mui-input-group{position:relative;padding:0;border:0;background-color:#fff}.mui-input-group:after{position:absolute;right:0;bottom:0;left:0;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#c8c7cc}.mui-input-group:before{position:absolute;top:0;right:0;left:0;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#c8c7cc}.mui-input-group input,.mui-input-group textarea{margin-bottom:0;border:0;border-radius:0;background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.mui-input-group input[type=search]{background:0 0}.mui-input-group input:last-child{background-image:none}.mui-input-row{clear:left;overflow:hidden}.mui-input-row select{font-size:17px;height:37px;padding:0}.mui-input-row .mui-btn+input,.mui-input-row label+input,.mui-input-row:last-child{background:0 0}.mui-input-group .mui-input-row{height:40px}.mui-input-group .mui-input-row:after{position:absolute;right:0;bottom:0;left:15px;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#c8c7cc}.mui-input-row label{font-family:"Helvetica Neue",Helvetica,sans-serif;line-height:1.1;float:left;width:35%;padding:11px 15px}.mui-input-row label~input,.mui-input-row label~select,.mui-input-row label~textarea{float:right;width:65%;margin-bottom:0;padding-left:0;border:0}.mui-input-row .mui-btn{line-height:1.1;float:right;width:15%;padding:10px 15px}.mui-input-row .mui-btn~input,.mui-input-row .mui-btn~select,.mui-input-row .mui-btn~textarea{float:left;width:85%;margin-bottom:0;padding-left:0;border:0}.mui-button-row{position:relative;padding-top:5px;text-align:center}.mui-input-group .mui-button-row{height:45px}.mui-input-row{position:relative}.mui-input-row.mui-input-range{overflow:visible;padding-right:20px}.mui-input-row .mui-inline{padding:8px 0}.mui-input-row .mui-input-clear~.mui-icon-clear,.mui-input-row .mui-input-password~.mui-icon-eye,.mui-input-row .mui-input-speech~.mui-icon-speech{font-size:20px;position:absolute;z-index:1;top:10px;right:0;width:38px;height:38px;text-align:center;color:#999}.mui-input-row .mui-input-clear~.mui-icon-clear.mui-active,.mui-input-row .mui-input-password~.mui-icon-eye.mui-active,.mui-input-row .mui-input-speech~.mui-icon-speech.mui-active{color:#007aff}.mui-input-row .mui-input-speech~.mui-icon-speech{font-size:24px;top:8px}.mui-input-row .mui-input-clear~.mui-icon-clear~.mui-icon-speech{display:none}.mui-input-row .mui-input-clear~.mui-icon-clear.mui-hidden~.mui-icon-speech{display:inline-block}.mui-input-row .mui-icon-speech~.mui-placeholder{right:38px}.mui-input-row.mui-search .mui-icon-clear{top:7px}.mui-input-row.mui-search .mui-icon-speech{top:5px}.mui-checkbox,.mui-radio{position:relative}.mui-checkbox label,.mui-radio label{display:inline-block;float:none;width:100%;padding-right:58px}.mui-checkbox.mui-left input[type=checkbox],.mui-radio.mui-left input[type=radio]{left:20px}.mui-checkbox.mui-left label,.mui-radio.mui-left label{padding-right:15px;padding-left:58px}.mui-checkbox input[type=checkbox],.mui-radio input[type=radio]{position:absolute;top:4px;right:20px;display:inline-block;width:28px;height:26px;border:0;outline:0!important;background-color:transparent;-webkit-appearance:none}.mui-checkbox input[type=checkbox][disabled]:before,.mui-radio input[type=radio][disabled]:before{opacity:.3}.mui-checkbox input[type=checkbox]:before,.mui-radio input[type=radio]:before{font-family:Muiicons;font-size:28px;font-weight:400;line-height:1;text-decoration:none;color:#aaa;border-radius:0;background:0 0;-webkit-font-smoothing:antialiased}.mui-checkbox input[type=checkbox]:checked:before,.mui-radio input[type=radio]:checked:before{color:#007aff}.mui-checkbox label.mui-disabled,.mui-checkbox.mui-disabled label,.mui-radio label.mui-disabled,.mui-radio.mui-disabled label{opacity:.4}.mui-radio input[type=radio]:before{content:"\e411"}.mui-radio input[type=radio]:checked:before{content:"\e441"}.mui-checkbox input[type=checkbox]:before{content:"\e411"}.mui-checkbox input[type=checkbox]:checked:before{content:"\e442"}.mui-select{position:relative}.mui-select:before{font-family:Muiicons;position:absolute;top:8px;right:21px;content:"\e581";color:rgba(170,170,170,.6)}.mui-input-row .mui-switch{float:right;margin-top:5px;margin-right:20px}.mui-input-range input[type=range]{position:relative;width:100%;height:2px;margin:17px 0;padding:0;cursor:pointer;border:0;border-radius:3px;outline:0;background-color:#999;-webkit-appearance:none!important}.mui-input-range input[type=range]::-webkit-slider-thumb{width:28px;height:28px;border-color:#0062cc;border-radius:50%;background-color:#007aff;background-clip:padding-box;-webkit-appearance:none!important}.mui-input-range label~input[type=range]{width:65%}.mui-input-range .mui-tooltip{font-size:36px;line-height:64px;position:absolute;z-index:1;top:-70px;width:64px;height:64px;text-align:center;opacity:.8;color:#333;border:1px solid #ddd;border-radius:6px;background-color:#fff;text-shadow:0 1px 0 #f3f3f3}.mui-search{position:relative}.mui-search input[type=search]{padding-left:30px}.mui-search .mui-placeholder{font-size:16px;line-height:34px;position:absolute;z-index:1;top:0;right:0;bottom:0;left:0;display:inline-block;height:34px;text-align:center;color:#999;border:0;border-radius:6px;background:0 0}.mui-search .mui-placeholder .mui-icon{font-size:20px;color:#333}.mui-search:before{font-family:Muiicons;font-size:20px;font-weight:400;position:absolute;top:50%;right:50%;display:none;margin-top:-18px;margin-right:31px;content:"\e466"}.mui-search.mui-active:before{font-size:20px;right:auto;left:5px;display:block;margin-right:0}.mui-search.mui-active input[type=search]{text-align:left}.mui-search.mui-active .mui-placeholder{display:none}.mui-segmented-control{font-size:15px;font-weight:400;position:relative;display:table;overflow:hidden;width:100%;table-layout:fixed;border:1px solid #007aff;border-radius:3px;background-color:transparent;-webkit-touch-callout:none}.mui-segmented-control.mui-segmented-control-vertical{border-collapse:collapse;border-width:0;border-radius:0}.mui-segmented-control.mui-segmented-control-vertical .mui-control-item{display:block;border-bottom:1px solid #c8c7cc;border-left-width:0}.mui-segmented-control.mui-scroll-wrapper{height:38px}.mui-segmented-control.mui-scroll-wrapper .mui-scroll{width:auto;height:40px;white-space:nowrap}.mui-segmented-control.mui-scroll-wrapper .mui-control-item{display:inline-block;width:auto;padding:0 20px;border:0}.mui-segmented-control .mui-control-item{line-height:38px;display:table-cell;overflow:hidden;width:1%;-webkit-transition:background-color .1s linear;transition:background-color .1s linear;text-align:center;white-space:nowrap;text-overflow:ellipsis;color:#007aff;border-color:#007aff;border-left:1px solid #007aff}.mui-segmented-control .mui-control-item:first-child{border-left-width:0}.mui-segmented-control .mui-control-item.mui-active{color:#fff;background-color:#007aff}.mui-segmented-control.mui-segmented-control-inverted{width:100%;border:0;border-radius:0}.mui-segmented-control.mui-segmented-control-inverted.mui-segmented-control-vertical .mui-control-item,.mui-segmented-control.mui-segmented-control-inverted.mui-segmented-control-vertical .mui-control-item.mui-active{border-bottom:1px solid #c8c7cc}.mui-segmented-control.mui-segmented-control-inverted .mui-control-item{color:inherit;border:0}.mui-segmented-control.mui-segmented-control-inverted .mui-control-item.mui-active{color:#007aff;border-bottom:2px solid #007aff;background:0 0}.mui-segmented-control.mui-segmented-control-inverted~.mui-slider-progress-bar{background-color:#007aff}.mui-segmented-control-positive{border:1px solid #4cd964}.mui-segmented-control-positive .mui-control-item{color:#4cd964;border-color:inherit}.mui-segmented-control-positive .mui-control-item.mui-active{color:#fff;background-color:#4cd964}.mui-segmented-control-positive.mui-segmented-control-inverted .mui-control-item.mui-active{color:#4cd964;border-bottom:2px solid #4cd964;background:0 0}.mui-segmented-control-positive.mui-segmented-control-inverted~.mui-slider-progress-bar{background-color:#4cd964}.mui-segmented-control-negative{border:1px solid #dd524d}.mui-segmented-control-negative .mui-control-item{color:#dd524d;border-color:inherit}.mui-segmented-control-negative .mui-control-item.mui-active{color:#fff;background-color:#dd524d}.mui-segmented-control-negative.mui-segmented-control-inverted .mui-control-item.mui-active{color:#dd524d;border-bottom:2px solid #dd524d;background:0 0}.mui-segmented-control-negative.mui-segmented-control-inverted~.mui-slider-progress-bar{background-color:#dd524d}.mui-control-content{position:relative;display:none}.mui-control-content.mui-active{display:block}.mui-popover{position:absolute;z-index:999;display:none;width:280px;-webkit-transition:opacity .3s;transition:opacity .3s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transform:none;transform:none;opacity:0;border-radius:7px;background-color:#f7f7f7;-webkit-box-shadow:0 0 15px rgba(0,0,0,.1);box-shadow:0 0 15px rgba(0,0,0,.1)}.mui-popover .mui-popover-arrow{position:absolute;z-index:1000;top:-25px;left:0;overflow:hidden;width:26px;height:26px}.mui-popover .mui-popover-arrow:after{position:absolute;top:19px;left:0;width:26px;height:26px;content:" ";-webkit-transform:rotate(45deg);transform:rotate(45deg);border-radius:3px;background:#f7f7f7}.mui-popover .mui-popover-arrow.mui-bottom{top:100%;left:-26px;margin-top:-1px}.mui-popover .mui-popover-arrow.mui-bottom:after{top:-19px;left:0}.mui-popover.mui-popover-action{bottom:0;width:100%;-webkit-transition:-webkit-transform .3s,opacity .3s;transition:transform .3s,opacity .3s;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);border-radius:0;background:0 0;-webkit-box-shadow:none;box-shadow:none}.mui-popover.mui-popover-action .mui-popover-arrow{display:none}.mui-popover.mui-popover-action.mui-popover-bottom{position:fixed}.mui-popover.mui-popover-action.mui-active{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.mui-popover.mui-popover-action .mui-table-view{margin:8px;text-align:center;color:#007aff;border-radius:4px}.mui-popover.mui-popover-action .mui-table-view .mui-table-view-cell:after{position:absolute;right:0;bottom:0;left:0;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);background-color:#c8c7cc}.mui-popover.mui-popover-action .mui-table-view small{font-weight:400;line-height:1.3;display:block}.mui-popover.mui-active{display:block;opacity:1}.mui-popover .mui-bar~.mui-table-view{padding-top:44px}.mui-backdrop{position:fixed;z-index:998;top:0;right:0;bottom:0;left:0;background-color:rgba(0,0,0,.3)}.mui-bar-backdrop.mui-backdrop{bottom:50px;background:0 0}.mui-backdrop-action.mui-backdrop{background-color:rgba(0,0,0,.3)}.mui-backdrop-action.mui-backdrop,.mui-bar-backdrop.mui-backdrop{opacity:0}.mui-backdrop-action.mui-backdrop.mui-active,.mui-bar-backdrop.mui-backdrop.mui-active{-webkit-transition:all .4s ease;transition:all .4s ease;opacity:1}.mui-popover .mui-btn-block{margin-bottom:5px}.mui-popover .mui-btn-block:last-child{margin-bottom:0}.mui-popover .mui-bar{-webkit-box-shadow:none;box-shadow:none}.mui-popover .mui-bar-nav{border-bottom:1px solid rgba(0,0,0,.15);border-top-left-radius:12px;border-top-right-radius:12px;-webkit-box-shadow:none;box-shadow:none}.mui-popover .mui-scroll-wrapper{margin:7px 0;border-radius:7px;background-clip:padding-box}.mui-popover .mui-scroll .mui-table-view{max-height:none}.mui-popover .mui-table-view{overflow:auto;max-height:300px;margin-bottom:0;border-radius:7px;background-color:#f7f7f7;background-image:none;-webkit-overflow-scrolling:touch}.mui-popover .mui-table-view:after,.mui-popover .mui-table-view:before{height:0}.mui-popover .mui-table-view .mui-table-view-cell:first-child,.mui-popover .mui-table-view .mui-table-view-cell:first-child>a:not(.mui-btn){border-top-left-radius:12px;border-top-right-radius:12px}.mui-popover .mui-table-view .mui-table-view-cell:last-child,.mui-popover .mui-table-view .mui-table-view-cell:last-child>a:not(.mui-btn){border-bottom-right-radius:12px;border-bottom-left-radius:12px}.mui-popover.mui-bar-popover .mui-table-view{width:106px}.mui-popover.mui-bar-popover .mui-table-view .mui-table-view-cell{padding:11px 15px;background-position:0 100%}.mui-popover.mui-bar-popover .mui-table-view .mui-table-view-cell>a:not(.mui-btn){margin:-11px -15px -11px -15px}.mui-popup-backdrop{position:fixed;z-index:998;top:0;right:0;bottom:0;left:0;-webkit-transition-duration:400ms;transition-duration:400ms;opacity:0;background:rgba(0,0,0,.4)}.mui-popup-backdrop.mui-active{opacity:1}.mui-popup{position:fixed;z-index:10000;top:50%;left:50%;display:none;overflow:hidden;width:270px;-webkit-transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transform:translate3d(-50%,-50%,0) scale(1.185);transform:translate3d(-50%,-50%,0) scale(1.185);text-align:center;opacity:0;color:#000;border-radius:13px}.mui-popup.mui-popup-in{display:block;-webkit-transition-duration:400ms;transition-duration:400ms;-webkit-transform:translate3d(-50%,-50%,0) scale(1);transform:translate3d(-50%,-50%,0) scale(1);opacity:1}.mui-popup.mui-popup-out{-webkit-transition-duration:400ms;transition-duration:400ms;-webkit-transform:translate3d(-50%,-50%,0) scale(1);transform:translate3d(-50%,-50%,0) scale(1);opacity:0}.mui-popup-inner{position:relative;padding:15px;border-radius:13px 13px 0 0;background:rgba(255,255,255,.95)}.mui-popup-inner:after{position:absolute;z-index:15;top:auto;right:auto;bottom:0;left:0;display:block;width:100%;height:1px;content:"";-webkit-transform:scaleY(.5);transform:scaleY(.5);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;background-color:rgba(0,0,0,.2)}.mui-popup-title{font-size:18px;font-weight:500;text-align:center}.mui-popup-title+.mui-popup-text{font-family:inherit;font-size:14px;margin:5px 0 0}.mui-popup-buttons{position:relative;display:-webkit-box;display:-webkit-flex;display:flex;height:44px;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center}.mui-popup-button{font-size:17px;line-height:44px;position:relative;display:block;overflow:hidden;box-sizing:border-box;width:100%;height:44px;padding:0 5px;cursor:pointer;text-align:center;white-space:nowrap;text-overflow:ellipsis;color:#007aff;background:rgba(255,255,255,.95);-webkit-box-flex:1}.mui-popup-button:after{position:absolute;z-index:15;top:0;right:0;bottom:auto;left:auto;display:block;width:1px;height:100%;content:"";-webkit-transform:scaleX(.5);transform:scaleX(.5);-webkit-transform-origin:100% 50%;transform-origin:100% 50%;background-color:rgba(0,0,0,.2)}.mui-popup-button:first-child{border-radius:0 0 0 13px}.mui-popup-button:first-child:last-child{border-radius:0 0 13px 13px}.mui-popup-button:last-child{border-radius:0 0 13px}.mui-popup-button:last-child:after{display:none}.mui-popup-button.mui-popup-button-bold{font-weight:600}.mui-popup-input input{font-size:14px;width:100%;height:26px;margin:15px 0 0;padding:0 5px;border:1px solid rgba(0,0,0,.3);border-radius:0;background:#fff}.mui-plus.mui-android .mui-popup-backdrop{-webkit-transition-duration:1ms;transition-duration:1ms}.mui-plus.mui-android .mui-popup{-webkit-transition-duration:1ms;transition-duration:1ms;-webkit-transform:translate3d(-50%,-50%,0) scale(1);transform:translate3d(-50%,-50%,0) scale(1)}.mui-progressbar{position:relative;display:block;overflow:hidden;width:100%;height:2px;-webkit-transform-origin:center top;transform-origin:center top;vertical-align:middle;border-radius:2px;background:#b6b6b6;-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.mui-progressbar span{position:absolute;top:0;left:0;width:100%;height:100%;-webkit-transition:150ms;transition:150ms;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);background:#007aff}.mui-progressbar.mui-progressbar-infinite:before{position:absolute;top:0;left:0;width:100%;height:100%;content:"";-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transform-origin:left center;transform-origin:left center;-webkit-animation:mui-progressbar-infinite 1s linear infinite;animation:mui-progressbar-infinite 1s linear infinite;background:#007aff}body>.mui-progressbar{position:absolute;z-index:10000;top:44px;left:0;border-radius:0}.mui-progressbar-in{-webkit-animation:mui-progressbar-in 300ms forwards;animation:mui-progressbar-in 300ms forwards}.mui-progressbar-out{-webkit-animation:mui-progressbar-out 300ms forwards;animation:mui-progressbar-out 300ms forwards}@-webkit-keyframes mui-progressbar-in{from{-webkit-transform:scaleY(0);opacity:0}to{-webkit-transform:scaleY(1);opacity:1}}@keyframes mui-progressbar-in{from{transform:scaleY(0);opacity:0}to{transform:scaleY(1);opacity:1}}@-webkit-keyframes mui-progressbar-out{from{-webkit-transform:scaleY(1);opacity:1}to{-webkit-transform:scaleY(0);opacity:0}}@keyframes mui-progressbar-out{from{transform:scaleY(1);opacity:1}to{transform:scaleY(0);opacity:0}}@-webkit-keyframes mui-progressbar-infinite{0%{-webkit-transform:translate3d(-50%,0,0) scaleX(.5)}100%{-webkit-transform:translate3d(100%,0,0) scaleX(.5)}}@keyframes mui-progressbar-infinite{0%{transform:translate3d(-50%,0,0) scaleX(.5)}100%{transform:translate3d(100%,0,0) scaleX(.5)}}.mui-pagination{display:inline-block;margin:0 auto;padding-left:0;border-radius:6px}.mui-pagination>li{display:inline}.mui-pagination>li>a,.mui-pagination>li>span{line-height:1.428571429;position:relative;float:left;margin-left:-1px;padding:6px 12px;text-decoration:none;color:#007aff;border:1px solid #ddd;background-color:#fff}.mui-pagination>li:first-child>a,.mui-pagination>li:first-child>span{margin-left:0;border-top-left-radius:6px;border-bottom-left-radius:6px;background-clip:padding-box}.mui-pagination>li:last-child>a,.mui-pagination>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px;background-clip:padding-box}.mui-pagination>li.mui-active>a,.mui-pagination>li.mui-active>a:active,.mui-pagination>li.mui-active>span,.mui-pagination>li.mui-active>span:active,.mui-pagination>li:active>a,.mui-pagination>li:active>a:active,.mui-pagination>li:active>span,.mui-pagination>li:active>span:active{z-index:2;cursor:default;color:#fff;border-color:#007aff;background-color:#007aff}.mui-pagination>li.mui-disabled>a,.mui-pagination>li.mui-disabled>a:active,.mui-pagination>li.mui-disabled>span,.mui-pagination>li.mui-disabled>span:active{opacity:.6;color:#777;border:1px solid #ddd;background-color:#fff}.mui-pagination-lg>li>a,.mui-pagination-lg>li>span{font-size:18px;padding:10px 16px}.mui-pagination-sm>li>a,.mui-pagination-sm>li>span{font-size:12px;padding:5px 10px}.mui-pager{padding-left:0;list-style:none;text-align:center}.mui-pager:after,.mui-pager:before{display:table;content:" "}.mui-pager:after{clear:both}.mui-pager li{display:inline}.mui-pager li>a,.mui-pager li>span{display:inline-block;padding:5px 14px;border:1px solid #ddd;border-radius:6px;background-color:#fff;background-clip:padding-box}.mui-pager li.mui-active>a,.mui-pager li.mui-active>span,.mui-pager li:active>a,.mui-pager li:active>span{cursor:default;text-decoration:none;color:#fff;border-color:#007aff;background-color:#007aff}.mui-pager .mui-next>a,.mui-pager .mui-next>span{float:right}.mui-pager .mui-previous>a,.mui-pager .mui-previous>span{float:left}.mui-pager .mui-disabled>a,.mui-pager .mui-disabled>a:active,.mui-pager .mui-disabled>span,.mui-pager .mui-disabled>span:active{opacity:.6;color:#777;border:1px solid #ddd;background-color:#fff}.mui-modal{position:fixed;z-index:999;top:0;overflow:hidden;width:100%;min-height:100%;-webkit-transition:-webkit-transform .25s,opacity 1ms .25s;transition:transform .25s,opacity 1ms .25s;-webkit-transition-timing-function:cubic-bezier(.1,.5,.1,1);transition-timing-function:cubic-bezier(.1,.5,.1,1);-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);opacity:0;background-color:#fff}.mui-modal.mui-active{height:100%;-webkit-transition:-webkit-transform .25s;transition:transform .25s;-webkit-transition-timing-function:cubic-bezier(.1,.5,.1,1);transition-timing-function:cubic-bezier(.1,.5,.1,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}.mui-android .mui-modal .mui-bar{position:static}.mui-android .mui-modal .mui-bar-nav~.mui-content{padding-top:0}.mui-slider{position:relative;z-index:1;overflow:hidden;width:100%}.mui-slider .mui-segmented-control.mui-segmented-control-inverted .mui-control-item.mui-active{border-bottom:0}.mui-slider .mui-segmented-control.mui-segmented-control-inverted~.mui-slider-group .mui-slider-item{border-top:1px solid #c8c7cc;border-bottom:1px solid #c8c7cc}.mui-slider .mui-slider-group{font-size:0;position:relative;-webkit-transition:all 0s linear;transition:all 0s linear;white-space:nowrap}.mui-slider .mui-slider-group .mui-slider-item{font-size:14px;position:relative;display:inline-block;width:100%;height:100%;vertical-align:top;white-space:normal}.mui-slider .mui-slider-group .mui-slider-item>a:not(.mui-control-item){line-height:0;position:relative;display:block}.mui-slider .mui-slider-group .mui-slider-item img{width:100%}.mui-slider .mui-slider-group .mui-slider-item .mui-table-view:after,.mui-slider .mui-slider-group .mui-slider-item .mui-table-view:before{height:0}.mui-slider .mui-slider-group.mui-slider-loop{-webkit-transform:translate(-100%,0);transform:translate(-100%,0)}.mui-slider-title{line-height:30px;position:absolute;bottom:0;left:0;width:100%;height:30px;margin:0;text-align:left;text-indent:12px;opacity:.8;background-color:#000}.mui-slider-indicator{position:absolute;bottom:8px;width:100%;text-align:center;background:0 0}.mui-slider-indicator.mui-segmented-control{position:relative;bottom:auto}.mui-slider-indicator .mui-indicator{display:inline-block;width:6px;height:6px;margin:1px 6px;cursor:pointer;border-radius:50%;background:#aaa;-webkit-box-shadow:0 0 1px 1px rgba(130,130,130,.7);box-shadow:0 0 1px 1px rgba(130,130,130,.7)}.mui-slider-indicator .mui-active.mui-indicator{background:#fff}.mui-slider-indicator .mui-icon{font-size:20px;line-height:30px;width:40px;height:30px;margin:3px;text-align:center;border:1px solid #ddd}.mui-slider-indicator .mui-number{line-height:32px;display:inline-block;width:58px}.mui-slider-indicator .mui-number span{color:#ff5053}.mui-slider-progress-bar{z-index:1;height:2px;-webkit-transform:translateZ(0);transform:translateZ(0)}.mui-switch{position:relative;display:block;width:74px;height:30px;-webkit-transition-timing-function:ease-in-out;transition-timing-function:ease-in-out;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:background-color,border;transition-property:background-color,border;border:2px solid #ddd;border-radius:20px;background-color:#fff;background-clip:padding-box}.mui-switch.mui-disabled{opacity:.3}.mui-switch .mui-switch-handle{position:absolute;z-index:1;top:-1px;left:-1px;width:28px;height:28px;-webkit-transition:.2s ease-in-out;transition:.2s ease-in-out;-webkit-transition-property:-webkit-transform,width,left;transition-property:transform,width,left;border-radius:16px;background-color:#fff;background-clip:padding-box;-webkit-box-shadow:0 2px 5px rgba(0,0,0,.4);box-shadow:0 2px 5px rgba(0,0,0,.4)}.mui-switch:before{font-size:13px;position:absolute;top:3px;right:11px;content:"Off";text-transform:uppercase;color:#999}.mui-switch.mui-dragging{border-color:#f7f7f7;background-color:#f7f7f7}.mui-switch.mui-dragging .mui-switch-handle{width:38px}.mui-switch.mui-dragging.mui-active .mui-switch-handle{left:-11px;width:38px}.mui-switch.mui-active{border-color:#4cd964;background-color:#4cd964}.mui-switch.mui-active .mui-switch-handle{-webkit-transform:translate(43px,0);transform:translate(43px,0)}.mui-switch.mui-active:before{right:auto;left:15px;content:"On";color:#fff}.mui-switch input[type=checkbox]{display:none}.mui-switch-mini{width:47px}.mui-switch-mini:before{display:none}.mui-switch-mini.mui-active .mui-switch-handle{-webkit-transform:translate(16px,0);transform:translate(16px,0)}.mui-switch-blue.mui-active{border:2px solid #007aff;background-color:#007aff}.mui-content.mui-fade{left:0;opacity:0}.mui-content.mui-fade.mui-in{opacity:1}.mui-content.mui-sliding{z-index:2;-webkit-transition:-webkit-transform .4s;transition:transform .4s;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.mui-content.mui-sliding.mui-left{z-index:1;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.mui-content.mui-sliding.mui-right{z-index:3;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.mui-navigate-right:after,.mui-push-left:after,.mui-push-right:after{font-family:Muiicons;font-size:inherit;line-height:1;position:absolute;top:50%;display:inline-block;-webkit-transform:translateY(-50%);transform:translateY(-50%);text-decoration:none;color:#bbb;-webkit-font-smoothing:antialiased}.mui-push-left:after{left:15px;content:"\e582"}.mui-navigate-right:after,.mui-push-right:after{right:15px;content:"\e583"}.mui-pull-bottom-pocket,.mui-pull-top-pocket{position:absolute;left:0;display:block;visibility:hidden;overflow:hidden;width:100%;height:50px}.mui-plus-pullrefresh .mui-pull-bottom-pocket,.mui-plus-pullrefresh .mui-pull-top-pocket{display:none;visibility:visible}.mui-pull-top-pocket{top:0}.mui-bar-nav~.mui-content .mui-pull-top-pocket{top:44px}.mui-bar-nav~.mui-bar-header-secondary~.mui-content .mui-pull-top-pocket{top:88px}.mui-pull-bottom-pocket{position:relative;bottom:0;height:40px}.mui-pull-bottom-pocket .mui-pull-loading{visibility:hidden}.mui-pull-bottom-pocket .mui-pull-loading.mui-in{display:inline-block}.mui-pull{font-weight:700;position:absolute;right:0;bottom:10px;left:0;text-align:center;color:#777}.mui-pull-loading{margin-right:10px;-webkit-transition:-webkit-transform .4s;transition:transform .4s;-webkit-transition-duration:400ms;transition-duration:400ms;vertical-align:middle}.mui-pull-loading.mui-reverse{-webkit-transform:rotate(180deg) translateZ(0);transform:rotate(180deg) translateZ(0)}.mui-pull-caption{font-size:15px;line-height:24px;position:relative;display:inline-block;overflow:visible;margin-top:0;vertical-align:middle}.mui-pull-caption span{display:none}.mui-pull-caption span.mui-in{display:inline}.mui-toast-container{line-height:17px;position:fixed;z-index:9999;bottom:50px;left:50%;-webkit-transition:opacity .3s;transition:opacity .3s;-webkit-transform:translate(-50%,0);transform:translate(-50%,0);opacity:0}.mui-toast-container.mui-active{opacity:.9}.mui-toast-message{font-size:14px;padding:10px 25px;text-align:center;color:#fff;border-radius:6px;background-color:#323232}.mui-numbox{position:relative;display:inline-block;overflow:hidden;width:120px;height:35px;padding:0 40px;vertical-align:top;vertical-align:middle;border:solid 1px #bbb;border-radius:3px;background-color:#efeff4}.mui-numbox [class*=btn-numbox],.mui-numbox [class*=numbox-btn]{font-size:18px;font-weight:400;line-height:100%;position:absolute;top:0;overflow:hidden;width:40px;height:100%;padding:0;color:#555;border:none;border-radius:0;background-color:#f9f9f9}.mui-numbox [class*=btn-numbox]:active,.mui-numbox [class*=numbox-btn]:active{background-color:#ccc}.mui-numbox [class*=btn-numbox][disabled],.mui-numbox [class*=numbox-btn][disabled]{color:silver}.mui-numbox .mui-btn-numbox-plus,.mui-numbox .mui-numbox-btn-plus{right:0;border-top-right-radius:3px;border-bottom-right-radius:3px}.mui-numbox .mui-btn-numbox-minus,.mui-numbox .mui-numbox-btn-minus{left:0;border-top-left-radius:3px;border-bottom-left-radius:3px}.mui-numbox .mui-input-numbox,.mui-numbox .mui-numbox-input{display:inline-block;overflow:hidden;width:100%!important;height:100%;margin:0;padding:0 3px!important;text-align:center;text-overflow:ellipsis;word-break:normal;border:none!important;border-right:solid 1px #ccc!important;border-left:solid 1px #ccc!important;border-radius:0!important}.mui-input-row .mui-numbox{float:right;margin:2px 8px}@font-face{font-family:Muiicons;font-weight:400;font-style:normal;src:url(../fonts/mui.ttf) format("truetype")}.mui-icon{font-family:Muiicons;font-size:24px;font-weight:400;font-style:normal;line-height:1;display:inline-block;text-decoration:none;-webkit-font-smoothing:antialiased}.mui-icon.mui-active{color:#007aff}.mui-icon.mui-right:before{float:right;padding-left:.2em}.mui-icon-contact:before{content:"\e100"}.mui-icon-person:before{content:"\e101"}.mui-icon-personadd:before{content:"\e102"}.mui-icon-contact-filled:before{content:"\e130"}.mui-icon-person-filled:before{content:"\e131"}.mui-icon-personadd-filled:before{content:"\e132"}.mui-icon-phone:before{content:"\e200"}.mui-icon-email:before{content:"\e201"}.mui-icon-chatbubble:before{content:"\e202"}.mui-icon-chatboxes:before{content:"\e203"}.mui-icon-phone-filled:before{content:"\e230"}.mui-icon-email-filled:before{content:"\e231"}.mui-icon-chatbubble-filled:before{content:"\e232"}.mui-icon-chatboxes-filled:before{content:"\e233"}.mui-icon-weibo:before{content:"\e260"}.mui-icon-weixin:before{content:"\e261"}.mui-icon-pengyouquan:before{content:"\e262"}.mui-icon-chat:before{content:"\e263"}.mui-icon-qq:before{content:"\e264"}.mui-icon-videocam:before{content:"\e300"}.mui-icon-camera:before{content:"\e301"}.mui-icon-mic:before{content:"\e302"}.mui-icon-location:before{content:"\e303"}.mui-icon-mic-filled:before,.mui-icon-speech:before{content:"\e332"}.mui-icon-location-filled:before{content:"\e333"}.mui-icon-micoff:before{content:"\e360"}.mui-icon-image:before{content:"\e363"}.mui-icon-map:before{content:"\e364"}.mui-icon-compose:before{content:"\e400"}.mui-icon-trash:before{content:"\e401"}.mui-icon-upload:before{content:"\e402"}.mui-icon-download:before{content:"\e403"}.mui-icon-close:before{content:"\e404"}.mui-icon-redo:before{content:"\e405"}.mui-icon-undo:before{content:"\e406"}.mui-icon-refresh:before{content:"\e407"}.mui-icon-star:before{content:"\e408"}.mui-icon-plus:before{content:"\e409"}.mui-icon-minus:before{content:"\e410"}.mui-icon-checkbox:before,.mui-icon-circle:before{content:"\e411"}.mui-icon-clear:before,.mui-icon-close-filled:before{content:"\e434"}.mui-icon-refresh-filled:before{content:"\e437"}.mui-icon-star-filled:before{content:"\e438"}.mui-icon-plus-filled:before{content:"\e439"}.mui-icon-minus-filled:before{content:"\e440"}.mui-icon-circle-filled:before{content:"\e441"}.mui-icon-checkbox-filled:before{content:"\e442"}.mui-icon-closeempty:before{content:"\e460"}.mui-icon-refreshempty:before{content:"\e461"}.mui-icon-reload:before{content:"\e462"}.mui-icon-starhalf:before{content:"\e463"}.mui-icon-spinner:before{content:"\e464"}.mui-icon-spinner-cycle:before{content:"\e465"}.mui-icon-search:before{content:"\e466"}.mui-icon-plusempty:before{content:"\e468"}.mui-icon-forward:before{content:"\e470"}.mui-icon-back:before,.mui-icon-left-nav:before{content:"\e471"}.mui-icon-checkmarkempty:before{content:"\e472"}.mui-icon-home:before{content:"\e500"}.mui-icon-navigate:before{content:"\e501"}.mui-icon-gear:before{content:"\e502"}.mui-icon-paperplane:before{content:"\e503"}.mui-icon-info:before{content:"\e504"}.mui-icon-help:before{content:"\e505"}.mui-icon-locked:before{content:"\e506"}.mui-icon-more:before{content:"\e507"}.mui-icon-flag:before{content:"\e508"}.mui-icon-home-filled:before{content:"\e530"}.mui-icon-gear-filled:before{content:"\e532"}.mui-icon-info-filled:before{content:"\e534"}.mui-icon-help-filled:before{content:"\e535"}.mui-icon-more-filled:before{content:"\e537"}.mui-icon-settings:before{content:"\e560"}.mui-icon-list:before{content:"\e562"}.mui-icon-bars:before{content:"\e563"}.mui-icon-loop:before{content:"\e565"}.mui-icon-paperclip:before{content:"\e567"}.mui-icon-eye:before{content:"\e568"}.mui-icon-arrowup:before{content:"\e580"}.mui-icon-arrowdown:before{content:"\e581"}.mui-icon-arrowleft:before{content:"\e582"}.mui-icon-arrowright:before{content:"\e583"}.mui-icon-arrowthinup:before{content:"\e584"}.mui-icon-arrowthindown:before{content:"\e585"}.mui-icon-arrowthinleft:before{content:"\e586"}.mui-icon-arrowthinright:before{content:"\e587"}.mui-icon-pulldown:before{content:"\e588"}.mui-fullscreen{position:absolute;top:0;right:0;bottom:0;left:0}.mui-fullscreen.mui-slider .mui-slider-group{height:100%}.mui-fullscreen .mui-segmented-control~.mui-slider-group{position:absolute;top:40px;bottom:0;width:100%;height:auto}.mui-fullscreen.mui-slider .mui-slider-item>a{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.mui-fullscreen .mui-off-canvas-wrap .mui-slider-item>a{top:auto;-webkit-transform:none;transform:none}.mui-bar-nav~.mui-content .mui-slider.mui-fullscreen{top:44px}.mui-bar-tab~.mui-content .mui-slider.mui-fullscreen .mui-segmented-control~.mui-slider-group{bottom:50px}.mui-android.mui-android-4-0 input:focus,.mui-android.mui-android-4-0 textarea:focus{-webkit-user-modify:inherit}.mui-android.mui-android-4-2 input,.mui-android.mui-android-4-2 textarea,.mui-android.mui-android-4-3 input,.mui-android.mui-android-4-3 textarea{-webkit-user-select:text}.mui-ios .mui-table-view-cell{-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.mui-plus-visible,.mui-wechat-visible{display:none!important}.mui-plus-hidden,.mui-wechat-hidden{display:block!important}.mui-tab-item.mui-plus-hidden,.mui-tab-item.mui-wechat-hidden{display:table-cell!important}.mui-plus .mui-plus-visible,.mui-wechat .mui-wechat-visible{display:block!important}.mui-plus .mui-tab-item.mui-plus-visible,.mui-wechat .mui-tab-item.mui-wechat-visible{display:table-cell!important}.mui-plus .mui-plus-hidden,.mui-wechat .mui-wechat-hidden{display:none!important}.mui-plus.mui-statusbar.mui-statusbar-offset .mui-bar-nav{height:64px;padding-top:20px}.mui-plus.mui-statusbar.mui-statusbar-offset .mui-bar-nav~.mui-content{padding-top:64px}.mui-plus.mui-statusbar.mui-statusbar-offset .mui-bar-header-secondary,.mui-plus.mui-statusbar.mui-statusbar-offset .mui-bar-nav~.mui-content .mui-pull-top-pocket{top:64px}.mui-plus.mui-statusbar.mui-statusbar-offset .mui-bar-header-secondary~.mui-content{padding-top:94px}.mui-iframe-wrapper{position:absolute;right:0;left:0;-webkit-overflow-scrolling:touch}.mui-iframe-wrapper iframe{width:100%;height:100%;border:0} -------------------------------------------------------------------------------- /src/lib/mui/fonts/mui-icons-extra.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/src/lib/mui/fonts/mui-icons-extra.ttf -------------------------------------------------------------------------------- /src/lib/mui/fonts/mui.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/src/lib/mui/fonts/mui.ttf -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' // /node_modules/vue/package.json : main => 2 | import App from './App' 3 | import router from './router/' 4 | import moment from 'moment' 5 | 6 | // 导入vue-resource 7 | import VueResource from 'vue-resource' 8 | // 注册vue-resource 9 | Vue.use(VueResource) 10 | // 配置vue-resource的请求根域名 11 | Vue.http.options.root = 'http://www.lovegf.cn:8899/' 12 | // 配置post请求以传统表单形式提交参数 application/x-www-form-urlencoded 13 | Vue.http.options.emulateJSON = true; 14 | 15 | Vue.config.productionTip = false 16 | 17 | // 按需导入需要的mint-ui组件 18 | import { 19 | Header, 20 | Swipe, 21 | SwipeItem, 22 | Button, 23 | // Lazyload 24 | } from 'mint-ui' 25 | // import MintUI from 'mint-ui' 26 | // import 'mint-ui/lib/style.css' 27 | // Vue.use(MintUI) 28 | // 全局注册 注册组件 29 | Vue.component(Header.name, Header) 30 | Vue.component(Swipe.name, Swipe) 31 | Vue.component(SwipeItem.name, SwipeItem) 32 | Vue.component(Button.name, Button) 33 | // Vue.use(Lazyload); 34 | 35 | // 导入mui的样式 36 | import './lib/mui/css/mui.css' 37 | import './lib/mui/css/icons-extra.css' 38 | 39 | // 引入自己的全局样式 40 | import './css/common.less' 41 | 42 | import VueLazyload from 'vue-lazyload' 43 | Vue.use(VueLazyload) 44 | 45 | import VuePreview from 'vue2-preview' 46 | Vue.use(VuePreview) 47 | 48 | // 定义全局过滤器 49 | Vue.filter('dateFormat', function (dateStr, pattern = 'YYYY-MM-DD HH:mm:ss') { 50 | // 直接调用表示获取当前时间 51 | return moment(dateStr).format(pattern) 52 | }) 53 | 54 | /* eslint-disable no-new */ 55 | new Vue({ 56 | el: '#app', 57 | router, 58 | render: h => h(App) 59 | }) 60 | -------------------------------------------------------------------------------- /src/pages/goodsList/index.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/pages/home/index.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 71 | 72 | -------------------------------------------------------------------------------- /src/pages/member/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 14 | -------------------------------------------------------------------------------- /src/pages/newsInfo/index.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 46 | 47 | 71 | -------------------------------------------------------------------------------- /src/pages/newsList/index.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 60 | 61 | 88 | -------------------------------------------------------------------------------- /src/pages/photoList/index.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 91 | 92 | 112 | -------------------------------------------------------------------------------- /src/pages/search/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 14 | -------------------------------------------------------------------------------- /src/pages/shopcar/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 14 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | 4 | import homeComponent from '../pages/home/' 5 | import memberComponent from '../pages/member/' 6 | import shopcarComponent from '../pages/shopcar/' 7 | import searchComponent from '../pages/search/' 8 | import newsListComponent from '../pages/newsList/' 9 | import newsInfoComponent from '../pages/newsInfo/' 10 | import photoListComponent from '../pages/photoList/' 11 | import goodsListComponent from '../pages/goodsList/' 12 | 13 | Vue.use(Router) 14 | 15 | const router = new Router({ 16 | routes: [ 17 | { path: '/', redirect: '/home' }, 18 | { path: '/home', component: homeComponent }, 19 | { path: '/member', component: memberComponent }, 20 | { path: '/shopcar', component: shopcarComponent }, 21 | { path: '/search', component: searchComponent }, 22 | { path: '/home/newsList', component: newsListComponent }, 23 | { path: '/home/newsInfo/:id', component: newsInfoComponent }, 24 | { path: '/home/photoList', component: photoListComponent }, 25 | { path: '/home/goodsList', component: goodsListComponent }, 26 | ], 27 | linkActiveClass: 'mui-active' 28 | }) 29 | 30 | // router.beforeEach((to, from, next) => { 31 | // // 在路由进入之前做的事情, 如果不调用next()方法就可以阻止路由的跳转 32 | // console.log(to) 33 | // console.log(from) 34 | // // 阻止路由跳转到newsList页面 35 | // if (to.path === '/home/newsList') { 36 | // return; 37 | // } 38 | 39 | // next(); 40 | // }) 41 | 42 | // router.afterEach((to, from) => { 43 | 44 | // }) 45 | 46 | export default router -------------------------------------------------------------------------------- /static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/static/.gitkeep -------------------------------------------------------------------------------- /笔记(汇总).zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总).zip -------------------------------------------------------------------------------- /笔记(汇总)/Vue基础-day01.md: -------------------------------------------------------------------------------- 1 | Vue基础-day01 2 | === 3 | 4 | 5 | - [课前准备](#课前准备) 6 | - [浏览器插件](#浏览器插件) 7 | - [VS Code插件](#vs-code插件) 8 | - [玩转Vs code](#玩转vs-code) 9 | - [课程介绍](#课程介绍) 10 | - [为什么学习Vue](#为什么学习vue) 11 | - [什么是MVVM](#什么是mvvm) 12 | - [Vue初体验](#vue初体验) 13 | - [Vue常用系统指令](#vue常用系统指令) 14 | - [插值表达式](#插值表达式) 15 | - [v-text](#v-text) 16 | - [v-html](#v-html) 17 | - [v-bind](#v-bind) 18 | - [v-for](#v-for) 19 | - [v-model](#v-model) 20 | - [v-on](#v-on) 21 | - [v-on按键修饰符](#v-on按键修饰符) 22 | - [v-if](#v-if) 23 | - [v-show](#v-show) 24 | - [v-cloak](#v-cloak) 25 | - [案例-利用系统指令实现品牌案例管理](#案例-利用系统指令实现品牌案例管理) 26 | - [目的](#目的) 27 | - [资源准备](#资源准备) 28 | - [功能-数据展示实现](#功能-数据展示实现) 29 | - [功能-数据删除](#功能-数据删除) 30 | - [功能-数据添加](#功能-数据添加) 31 | - [功能-按回车键添加数据](#功能-按回车键添加数据) 32 | - [功能-输入框自动聚焦](#功能-输入框自动聚焦) 33 | - [ref](#ref) 34 | - [功能-时间格式化](#功能-时间格式化) 35 | - [过滤器](#过滤器) 36 | 37 | 38 | 39 | ## 课前准备 40 | 41 | ### 浏览器插件 42 | 43 | * Vue.js devtools 44 | 45 | ### VS Code插件 46 | 47 | 自动补全标签 48 | * Auto Close Tag 49 | * Auto Complete Tag 50 | * Auto Rename Tag 51 | 52 | 开启一个服务器浏览HTML网页,第一次使用需要Ctrl + Shift + p输入 live server选择open 53 | * Live Server 54 | 55 | 路径自动补全 56 | * Path Intellisense 57 | 58 | vue语法高亮和自动补全代码 59 | * Vetur 60 | * VueHelper 61 | 62 | ### 玩转Vs code 63 | 64 | * [Vs Code奇淫技巧](https://github.com/Microsoft/vscode-tips-and-tricks) 65 | 66 | * Vs Code设置 67 | 68 | 文件--->首选项--->设置,然后添加如下代码: 69 | 70 | ```json 71 | "emmet.syntaxProfiles": { 72 | "vue-html": "html", 73 | "vue": "html" 74 | }, 75 | "emmet.includeLanguages": { 76 | "vue-html": "html", 77 | "vue": "html" 78 | } 79 | ``` 80 | ## 课程介绍 81 | 82 | ### 为什么学习Vue 83 | 84 | ![为什么学习vue](./img/day01/为什么学习vue.png) 85 | 86 | ### 什么是MVVM 87 | 88 | - M => Model(数据模型) 89 | - V => View(视图模型,负责将数据模型转化成UI展现出来,就是那些DOM结构) 90 | - VM => ViewModel(一个同步View和Model的对象) 91 | 92 | ![MVVM](./img/day01/MVVM.png) 93 | 94 | ### Vue初体验 95 | 96 | ```html 97 | 98 | 99 | 100 | 101 | 102 | 103 | Document 104 | 105 | 106 | 107 | 108 | 109 |
{{msg}}
110 |
111 | 112 |

{{msg}}

113 |
114 | 125 | 126 | 127 | ``` 128 | ## Vue常用系统指令 129 | 130 | ### 插值表达式 131 | 132 | ```html 133 | 数据绑定最常见的形式,其中最常见的是使用插值表达式,写法是{{}} 中写表达式 134 | 例如:Message: {{ msg }} 135 | Mustache 标签将会被替代为对应数据对象上 msg 属性(msg定义在data对象中)的值。 136 | 无论何时,绑定的数据对象上 msg 属性发生了改变,插值处的内容都会更新。 137 | 138 | {{}}对JavaScript 表达式支持,例如: 139 | {{ number + 1 }} 140 | {{ ok ? 'YES' : 'NO' }} 141 | {{ message.split('').reverse().join('') }} 142 | 143 | 但是有个限制就是,每个绑定都只能包含单个表达式,如下表达式无效: 144 | 145 | {{ var a = 1 }} 146 | 147 | 148 | {{ number++ }} 会报警告:vue2.js:482 [Vue warn]: You may have an infinite update loop in a component render function. 149 | 150 | 151 | {{ if (ok) { return message } }} 152 | ``` 153 | 154 | ### v-text 155 | 156 | ```html 157 | 158 |
159 | new Vue({ 160 | data:{ 161 | msg:'hello world' 162 | } 163 | }); 164 | 165 | 166 |
hello world
167 | ``` 168 | 169 | ### v-html 170 | 171 | ```html 172 | 差值表达式和v-text会将数据解释为纯文本,而非 HTML 。 173 | 为了输出真正的 HTML ,你需要使用 v-html 指令: 174 | 例如: 175 |
176 | new Vue({ 177 | data:{ 178 | rawHtml:'

hello world

' 179 | } 180 | }) 181 | 182 | 被插入的内容都会被当做 HTML,但是对于没有HTML标签的数据绑定时作用同v-text和{{}} 183 | ``` 184 | 185 | ### v-bind 186 | 187 | ```html 188 | 1、作用:可以给html元素或者组件动态地绑定一个或多个特性,例如动态绑定style和class 189 | 190 | 2、举例: 191 | 1、img的src从imageSrc变量中取得 192 | 193 | 194 | 2、从classA, classB两个变量的值作为class的值, 195 | 结果是:
classA, classB
196 |
classA, classB
197 | 198 | 3、isRed变量如果为true,则class的值为red,否则没有 199 |
isred
200 | 201 | 4、div的class属性值一定有classA变量的值,而是否有classB和classC变量的值取决于isB和isC是否为true,二者一一对应 202 |
数组对象
203 | 204 | 5、变量加常量 205 |
size22
206 | 207 | 6、变量加常量的另一种写法 208 | 209 | 210 | 7、对象数组 211 |
styleObjectA, styleObjectB
212 | 213 | 3、缩写形式 214 | 215 |
classA, classB
216 |
isred
217 |
数组对象
218 |
size22
219 | 220 |
styleObjectA, styleObjectB
221 | 222 | 223 | vue对象初始化 224 | 246 | ``` 247 | 248 | ### v-for 249 | 250 | ```html 251 | 268 | 275 | 292 | ``` 293 | 294 | ### v-model 295 | 296 | ```html 297 | 1、在表单控件或者组件上创建双向绑定 298 | 2、v-model仅能在如下元素中使用: 299 | input 300 | select 301 | textarea 302 | components(Vue中的组件) 303 | 304 | 3、举例: 305 | 306 | 307 | new Vue({ 308 | data:{ 309 | uname:'' //这个属性值和input元素的值相互一一对应,二者任何一个的改变都会联动的改变对方 310 | } 311 | }) 312 | ``` 313 | 314 | ### v-on 315 | 316 | ```html 317 | 1、作用:绑定事件监听,表达式可以是一个方法的名字或一个内联语句, 318 | 如果没有修饰符也可以省略,用在普通的html元素上时,只能监听 原生 319 | DOM 事件。用在自定义元素组件上时,也可以监听子组件触发的自定义事件。 320 | 321 | 2、常用事件: 322 | v-on:click 323 | v-on:keydown 324 | v-on:keyup 325 | v-on:mousedown 326 | v-on:mouseover 327 | v-on:submit 328 | .... 329 | 330 | 3、示例: 331 | 332 | 333 | 334 | 335 | 336 | 337 |
338 | 339 | 5、v-on的缩写形式:可以使用@替代 v-on: 340 | 341 | 342 | 343 | 6、按键修饰符 344 | 触发像keydown这样的按键事件时,可以使用按键修饰符指定按下特殊的键后才触发事件 345 | 346 | 写法: 347 | 当按下回车键时才触发kd1事件 348 | 349 | 由于回车键对应的keyCode是13,也可以使用如下替代 350 | 当按下回车键时才触发kd1事件 351 | 352 | 但是如果需要按下字母a(对应的keyCode=65)才触发kd1事件,有两种写法: 353 | 1、由于默认不支持a这个按键修饰符,需要Vue.config.keyCodes.a = 65 添加一个对应,所以这种写法为: 354 | 355 | Vue.config.keyCodes.a = 65 356 | 这样即可触发 357 | 358 | 2、也可以之间加上a对应的数字65作为按键修饰符 359 | 这样即可触发 360 | 361 | 键盘上对应的每个按键可以通过 http://keycode.info/ 获取到当前按下键所对应的数字 362 | ``` 363 | 364 | ### v-on按键修饰符 365 | 366 | * 作用说明 367 | 368 | ```html 369 | 文档地址:https://cn.vuejs.org/v2/guide/events.html#键值修饰符 370 | 371 | 在监听键盘事件时,我们经常需要监测常见的键值。 Vue 允许为 v-on 在监听键盘事件时添加按键修饰符: 372 | .enter 373 | .tab 374 | .delete (捕获 “删除” 和 “退格” 键) 375 | .esc 376 | .space 377 | .up 378 | .down 379 | .left 380 | .right 381 | ``` 382 | 383 | * 可以自定义按键别名 384 | 385 | ```html 386 | // 在Vue2.0版本中扩展一个f1的按键修饰符写法: 387 | Vue.config.keyCodes.f1 = 112 388 | 389 | // 使用 390 | 391 | ``` 392 | 393 | ### v-if 394 | 395 | ```html 396 | 1、作用:根据表达式的值的真假条件来决定是否渲染元素,如果条件为false不渲染(达到隐藏元素的目的),为true则渲染。在切换时元素及它的数据绑定被销毁并重建 397 | 398 | 2、示例: 399 | 400 | {{#if isShow}} 401 |

Yes

402 | {{/if}} 403 | 404 | 通常我们使用写法居多: 405 |

Yes

406 | 407 | 也可以用 v-else 添加一个 “else” 块: 408 |

Yes

409 |

No

410 | 411 | 注意:v-else 元素必须紧跟在 v-if 元素否则它不能被识别。 412 | 413 | new Vue({ 414 | data:{ 415 | isShow:true 416 | } 417 | }); 418 | ``` 419 | 420 | ### v-show 421 | 422 | ```html 423 | 1、根据表达式的真假值,切换元素的 display CSS 属性,如果为false,则在元素上添加 display:none来隐藏元素,否则移除display:none实现显示元素 424 | 425 | 2、示例: 426 |

Yes

427 | 428 | new Vue({ 429 | data:{ 430 | isShow:true 431 | } 432 | }); 433 | 434 | 3、v-if和v-show的总结: 435 | v-if和v-show 都能够实现对一个元素的隐藏和显示操作,但是v-if是将这个元素添加或者移除到dom中,而v-show 436 | 是在这个元素上添加 style="display:none"和移除它来控制元素的显示和隐藏的 437 | ``` 438 | 439 | ### v-cloak 440 | 441 | ```html 442 | v-cloak指令保持在元素上直到关联实例结束编译后自动移除,v-cloak和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。 443 | 通常用来防止{{}}表达式闪烁问题 444 | 例如: 445 | 448 | 449 | 450 | {{msg}} 451 | 452 | new Vue({ 453 | data:{ 454 | msg:'hello ivan' 455 | } 456 | }) 457 | ``` 458 | 459 | ## 案例-利用系统指令实现品牌案例管理 460 | 461 | ### 目的 462 | 463 | 通过案例熟悉Vue系统指令的用法和结构的写法练习,做到知识点的巩固和学会 464 | 应用,并且在案例的扩展需求中,学习Vue新知识点,做到先有需求,再有知识点 465 | 学习,最后到知识点的应用,让学员学习知识点的同时学会知识点的应用 466 | 467 | ### 资源准备 468 | 469 | * 效果图
470 | ![效果图](./img/day01/案例效果图.png) 471 | 472 | * 案例html结构 473 | ```html 474 | 475 |
476 |
477 | 编号: 478 | 品牌名称: 479 | 480 |
481 | 482 |
483 | 品牌名称: 484 |
485 | 486 |
487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 |
编号品牌名称创立时间操作
没有品牌数据
499 |
500 |
501 | 502 | ``` 503 | 504 | * 案例css样式 505 | 506 | ```html 507 | 534 | ``` 535 | 536 | ### 功能-数据展示实现 537 | 538 | 1. 在 data 中添加 一个名称为 list的变量,类型为数组,存放品牌数据的对象,格式为:{id:1,name:'宝马',ctime:Date()} 539 | 540 | ```js 541 | var vm = new Vue({ 542 | el: '#app', 543 | data: { 544 | list: [ 545 | {id: 1, title: 'LV', ctime: new Date()}, 546 | {id: 2, title: 'CC', ctime: new Date()}, 547 | {id: 3, title: 'CK', ctime: new Date()}, 548 | ] 549 | } 550 | }) 551 | ``` 552 | 553 | 2. 在table中的“动态生成内容tr”位置使用v-for指令遍历list数组数据生成表格内容行,注意要写`:key` 554 | 555 | ```html 556 | 557 | {{item.id}} 558 | {{item.title}} 559 | {{item.ctime}} 560 | 561 | 删除 562 | 563 | 564 | ``` 565 | 566 | 3. 处理 “没有品牌数据” 提示问题,代码如下 567 | 568 | ```html 569 | 利用:v-if进行判断,当list为空时,才显示没有品牌数据 570 | 571 | 572 | 没有品牌数据 573 | 574 | ``` 575 | 576 | ### 功能-数据删除 577 | 578 | 1. 给按钮绑定删除方法,并传入一个id 579 | 580 | ```html 581 | 删除 582 | ``` 583 | 584 | 2. Vue实例中定义删除的方法 585 | ```js 586 | methods: { 587 | deleteData(id) { 588 | // 返回满足函数条件的数组的项的index 589 | var index = this.list.findIndex(item => { 590 | return item.id === id 591 | }) 592 | // 删除该索引对应的值 593 | this.list.splice(index, 1) 594 | } 595 | } 596 | ``` 597 | 598 | ### 功能-数据添加 599 | 600 | * 效果图
601 | ![添加数据](./img/day01/添加数据.png) 602 | 603 | 1. 实现步骤1:在Vue对象实例的data中添加一个product对象{id:0,name:'',ctime:Date()} 604 | 605 | ```js 606 | new Vue({ 607 | el: '#app', 608 | data: { 609 | product:{id:0,name:'',ctime:Date()}, 610 | list:[ 611 | {id:1,name:'宝马',ctime:Date()}, 612 | {id:2,name:'奔驰',ctime:Date()} 613 | ] 614 | }, 615 | methods: { 616 | } 617 | }) 618 | ``` 619 | 620 | 2. 实现步骤2:在编号和品牌名称文本框中利用v-model对product对象中的id和name属性进行一一绑定 同时在添加按钮上利用 v-on:click注册事件addData 621 | 622 | ```html 623 | 编号: 624 | 品牌名称: 625 | 626 | ``` 627 | 628 | 3. 实现步骤3:在Vue对象实例的methods中添加一个 addData的方法实现添加逻辑即可完成 629 | 630 | ```js 631 | new Vue({ 632 | // vm控制的区块为id为app的div,此div中的所有vue指令均可以被vm解析 633 | el: '#app', 634 | data: { 635 | product:{id:0,name:'',ctime:Date()}, 636 | list:[ 637 | {id:1,name:'宝马',ctime:Date()}, 638 | {id:2,name:'奔驰',ctime:Date()} 639 | ] 640 | }, 641 | methods: { 642 | addData(){ 643 | // 修改品牌添加时间为当前时间 644 | this.product.ctime = Date(); 645 | 646 | // 添加数据到品牌列表中 647 | this.list.push(this.product); 648 | 649 | // 清空product 650 | this.product = {id:0,name:'',ctime:Date()}; 651 | } 652 | } 653 | }) 654 | ``` 655 | 656 | ### 功能-按回车键添加数据 657 | 658 | **关键点:利用v-on的.enter按键修饰符实现,回车键的keycode=13**
659 | ![回车添加数据](./img/day01/回车添加数据.png) 660 | 661 | ```html 662 | 品牌名称: 663 | 664 | 665 | 品牌名称: 666 | ``` 667 | ### 功能-输入框自动聚焦 668 | 669 | 在vue中实现这个需求有三种方式: 670 | * 可以使用document.getElementById()获取到文本框元素对象后调用其focus()方法和设置style属性 671 | * 可以在文本框上元素上增加一个 ref="自定义名称",再使用this.$refs.自定义名称.focus()和 672 | this.$refs.自定义名称.style="color:red" 设置style属性 673 | * 使用自定义指令实现封装 674 | 675 | > 注意:前两种方式的代码需要写到生命周期事件:mounted(){}中 676 | 677 | 1. 原生js操作DOM实现 678 | 679 | ```html 680 | // html代码 681 | 编号: 682 | 683 | // vue对象mounted(){}中代码 684 | mounted(){ 685 | document.getElementById('id').focus(); 686 | document.getElementById('id').style="color:red"; 687 | } 688 | ``` 689 | 690 | 2. ref方式实现 691 | 692 | ```html 693 | // html代码: 694 | 编号: 695 | 696 | // vue对象mounted(){}中代码 697 | mounted(){ 698 | this.$refs.id.focus(); 699 | this.$refs.id.style="color:red"; 700 | } 701 | ``` 702 | 3. 使用自定义指令 703 | 704 | * 使用说明 705 | 706 | - 利用Vue.directive('指令id',{inserted:function(el,binding){}}) 707 | - 参数说明 708 | + 指令id可由程序员自行定义,注意和系统指令名称有所区别,例如: 709 | focus,在某个元素上具体使用的时候请在 指令id前面再加上v-,例如 710 | `` 711 | 712 | + 第二个参数是一个对象,其中inserted是一个函数,表示 “被绑定元素插入父节点时调用” 713 | * inserted的参数: 714 | - el参数:表示使用此自定义指令的dom对象 715 | - binding参数:一个对象,包含以下属性: 716 | + name:指令名,不包括 v- 前缀。 717 | + value:指令的绑定值,例如:v-focus="colorvalue", value 的值是colorvalue这个变量的值,colorvalue定义在data(){}中 718 | + expression:绑定值的字符串形式。例如 v-focus="colorvalue" ,expression 的值是 "colorvalue" 719 | 720 | * 开始使用Vue.directive()封装自定义指令v-focus实现光标自动定位 721 | 722 | ```html 723 | 1、定义指令color 724 | Vue.directive('color',{ 725 | inserted:function(el,binding){ 726 | //将颜色设置给使用v-color指令的元素上 727 | el.style.color=binding.value; 728 | } 729 | }); 730 | 731 | 732 | 2、 在dom元素上使用指令,注意加上前缀 v- 733 | 编号: 734 | 735 | 3、在Vue对象实例中的data(){}中定义colorvalue 736 | new Vue({ 737 | data: { 738 | colorvalue:'red' 739 | } 740 | }); 741 | ``` 742 | 743 | ### ref 744 | 745 | ref的作用类似于document.getElementByID,在vue中想要获取一个dom对象或者组件对象,则只需要 在此元素上添加一个 ref="自定义名称" ,再使用 this.$refs.自定义名称即可获取 746 | 747 | ```html 748 | 749 | 750 | 751 | 752 | 753 |
754 | 755 |
756 | 757 | 769 | 770 | ``` 771 | 772 | ### 功能-时间格式化 773 | 774 | ```html 775 | // 定义全局过滤器datefmt 776 | Vue.filter('datefmt',function(input){ 777 | var date = new Date(input); 778 | var year = date.getFullYear(); 779 | var m = date.getMonth() + 1; 780 | var d = date.getDate(); 781 | var fmtStr = year+'-'+m +'-'+d; 782 | return fmtStr; //返回输出结果 783 | }); 784 | 785 | // 调用, 注意datefmt的第一个参数默认就是管道符左边的值 786 | {{item.ctime | datefmt }} 787 | ``` 788 | 789 | ### 过滤器 790 | 791 | 1. 私有过滤器 792 | 793 | * 定义方式 794 | 795 | 可以在 new Vue({filters:{}})中的filters中注册一个私有过滤器 796 | 797 | 定义格式: 798 | new Vue({ 799 | el:'#app', 800 | filters:{ 801 | '过滤器名称':function(管道符号|左边对象的值,参数1,参数2,....) { 802 | return 对管道符号|左边参数的值做处理以后的值 803 | }) 804 | } 805 | }); 806 | 807 | Vue2.0 调用过滤器传参写法: 808 | {{ msg | 过滤器id('参数1','参数2' ....) }} 809 | 810 | * (应用示例)自定义私有过滤器实现日期格式化 811 | 812 | ```html 813 | 1、 定义私有的日期格式化过滤器: 814 | new Vue({ 815 | el:'#app', 816 | data:{ 817 | time:new Date() 818 | }, 819 | filters:{ 820 | //定义在 VM中的filters对象中的所有过滤器都是私有过滤器 821 | datefmt:function(input,splicchar){ 822 | var date = new Date(input); 823 | var year = date.getFullYear(); 824 | var m = date.getMonth() + 1; 825 | var d = date.getDate(); 826 | var fmtStr = year+splicchar+m +splicchar+d; 827 | return fmtStr; //返回输出结果 828 | } 829 | } 830 | }); 831 | 2、使用 832 |
833 | {{ time | datefmt('-') }} //Vue2.0传参写法 834 |
835 | ``` 836 | 837 | 2. 全局过滤器 838 | 839 | * 定义方式 840 | 841 | 可以用全局方法 Vue.filter() 注册一个全局自定义过滤器,它接收两个参数:过滤器 ID 和过滤器函数。过滤器函数以值为参数,返回转换后的值 842 | 843 | 定义格式: 844 | Vue.filter('过滤器名称', function (管道符号|左边参数的值,其他参数1,其他参数2,....) { 845 | return 对管道符号|左边参数的值做处理以后的值 846 | }) 847 | 848 | Vue2.0 使用:参数调用时用(),多个参数中间使用逗号分开 849 | {{ msg | 过滤器名称('参数1','参数2' ....) }} 850 | 851 | * (应用示例)自定义全局过滤器实现日期格式化 852 | 853 | ```html 854 | 1、 定义全局的日期格式化过滤器: 855 | Vue.filter('datefmt',function(input,splicchar){ 856 | var date = new Date(input); 857 | var year = date.getFullYear(); 858 | var m = date.getMonth() + 1; 859 | var d = date.getDate(); 860 | var fmtStr = year+splicchar+m +splicchar+d; 861 | return fmtStr; //返回输出结果 862 | }); 863 | 864 | 2、使用 865 |
866 | {{ time | datefmt('-') }} //Vue2.0传参写法 867 |
868 | 869 | 877 | ``` 878 | -------------------------------------------------------------------------------- /笔记(汇总)/Vue基础-day02.md: -------------------------------------------------------------------------------- 1 | Vue基础-day02 2 | === 3 | 4 | 5 | - [computed](#computed) 6 | - [watch](#watch) 7 | - [案例-利用系统指令实现品牌案例管理](#案例-利用系统指令实现品牌案例管理) 8 | - [功能-实现品牌列表数据过滤功能](#功能-实现品牌列表数据过滤功能) 9 | - [功能-利用vue的动画实现删除提示框动画呈现和离开](#功能-利用vue的动画实现删除提示框动画呈现和离开) 10 | - [axios(基于 promise 的 HTTP 库)](#axios基于-promise-的-http-库) 11 | - [get请求示例](#get请求示例) 12 | - [post请求示例](#post请求示例) 13 | - [案例-品牌管理API](#案例-品牌管理api) 14 | - [案例-axios版获取及删除数据](#案例-axios版获取及删除数据) 15 | - [vue-resource(不推荐使用)](#vue-resource不推荐使用) 16 | - [vue过渡&动画](#vue过渡动画) 17 | - [transition的作用](#transition的作用) 18 | - [transition结合css实现过渡](#transition结合css实现过渡) 19 | - [transition结合animate.css实现过渡](#transition结合animatecss实现过渡) 20 | - [transition结合钩子函数实现过渡](#transition结合钩子函数实现过渡) 21 | 22 | 23 | 24 | ## computed 25 | 26 | 计算属性出现的目的是解决模板中放入过多的逻辑会让模板过重且难以维护的问题;计算属性是基于它们的依赖进行缓存的 27 | 28 | ```js 29 | computed: { 30 | fullName: function () { 31 | console.log(this.firstName + this.lastName) 32 | return this.firstName + this.lastName 33 | } 34 | } 35 | ``` 36 | 37 | ## watch 38 | 39 | 侦听器(watch)用来观察和响应 Vue 实例上的数据变动 40 | 41 | ```js 42 | watch: { 43 | firstName: function (val) { 44 | this.fullName = val + ' ' + this.lastName 45 | }, 46 | lastName: function (val) { 47 | this.fullName = this.firstName + ' ' + val 48 | } 49 | } 50 | ``` 51 | 52 | 注意:通常情况下用computed,当需要在数据变化时**执行异步**或**开销较大**的操作时,用watch 53 | 54 | ## 案例-利用系统指令实现品牌案例管理 55 | 56 | ### 功能-实现品牌列表数据过滤功能 57 | 58 | 利用两种方式实现: 59 | 1. watch 监听器 60 | 61 | ```js 62 | 1. 在data(){}中定义searchvalue变量,作为存储用户是输入搜索值 63 | new Vue({ 64 | // vm控制的区块为id为app的div,此div中的所有vue指令均可以被vm解析 65 | el: '#app', 66 | data: { 67 | searchvalue:'' 68 | listold:[ 69 | {id:1,name:'宝马',ctime:Date()}, 70 | {id:2,name:'奔驰',ctime:Date()} 71 | ], 72 | list:[ 73 | {id:1,name:'宝马',ctime:Date()}, 74 | {id:2,name:'奔驰',ctime:Date()} 75 | ] 76 | }, 77 | methods: { 78 | adddata(){ 79 | this.product.ctime = Date(); 80 | this.list.push(this.product); 81 | this.product = {id:0,name:'',ctime:Date()}; 82 | // 为了防止搜索出来的新数组覆盖list,需要利用listold来存储一个list中完整的值 83 | this.listold = this.list; 84 | } 85 | }, 86 | }); 87 | 88 | 89 | 2. 双向数据绑定searchvalue 90 |
91 | 品牌名称: 92 |
93 | 94 | 3. 在watch中监控searchvalue变量的值,当值有改变,则触发方法searchvalue 95 | new Vue({ 96 | watch:{ 97 | // 监控searchvalue变量的值,当值有改变,则触发方法 98 | // newval:searchvalue变量改变以后的值 99 | //oldval:searchvalue变量改变之前的值 100 | 'searchvalue':function(newval,oldval){ 101 | // 为了防止搜索出来的新数组覆盖list,需要利用listold来存储一个list中完整的值 102 | this.list= this.listold.filter(item=>item.name.indexOf(newval)!=-1); 103 | } 104 | } 105 | }); 106 | ``` 107 | 108 | 2. computed 计算属性 109 | 110 | ```js 111 | 1. 在data(){}中定义searchvalue变量,作为存储用户是输入搜索值,利用computed定义计算属性来实现按照条件筛选数据逻辑 112 | new Vue({ 113 | // vm控制的区块为id为app的div,此div中的所有vue指令均可以被vm解析 114 | el: '#app', 115 | data: { 116 | searchvalue:'' 117 | }, 118 | computed:{ 119 | listdata(){ 120 | return this.list.filter(item=>item.name.indexOf(this.searchvalue)!=-1); 121 | } 122 | } 123 | }); 124 | 125 | 2. 在v-for中遍历计算属性listdata数组中的值 126 | 127 | 128 | 由计算属性的特点可以知道:当改变了list数组中的值以后,会自动触发计算属性listdata的执行,从而更新v-for对于的列表 129 | ``` 130 | 131 | ### 功能-利用vue的动画实现删除提示框动画呈现和离开 132 | 133 | [transition官方文档](https://cn.vuejs.org/v2/guide/transitions.html) 134 | 135 | 1. transition结合css实现 136 | 137 | ```html 138 | // 1. 用transition组件包裹需要添加过渡的元素,并添加name属性 139 | 140 | hello 黑马 141 | 142 | 143 | // 2. 定义以slide开头的css类 144 | 160 | 161 | // 3. 在点击事件中控制元素显示与隐藏 162 | 163 | 164 | // 4. 定义一个isshow变量,用来控制元素显示或隐藏,并在点击事件中改变它的值 165 | // 实例化vue对象(MVVM中的View Model) 166 | new Vue({ 167 | // vm控制的区块为id为app的div,此div中的所有vue指令均可以被vm解析 168 | el: '#app', 169 | data: { 170 | // 数据 (MVVM中的Model) 171 | isshow: false 172 | }, 173 | methods: { 174 | toggleShow: function () { 175 | this.isshow = !this.isshow; 176 | } 177 | } 178 | }) 179 | ``` 180 | 181 | 2. transition结合animate.css实现 182 | 183 | ```html 184 | // 1. 导入animate.css 185 | 186 | // 2. 使用 187 | 188 | 192 | 193 | hello 黑马 194 | 195 | 196 | // 利用methods中的方法去控制data中的isshow属性,实现元素的显示与隐藏 197 | ``` 198 | 199 | 3. transition结合动画钩子函数实现 200 | 201 | > 注意:enter和leave钩子中,当动画结束一定要调用done()函数,不然后续钩子函数不会被调用 202 | 203 | ```html 204 | 205 |
206 | 207 |
208 | 209 | 216 | 221 | hello 黑马 222 | 223 |
224 | 225 | 226 | 227 | 273 | ``` 274 | 275 | ## axios(基于 promise 的 HTTP 库) 276 | 277 | [axios文档](https://github.com/axios/axios) 278 | 279 | 1. http请求报文 280 | 281 | 浏览器与服务器数据交互是遵循http协议的,当浏览器要访问服务器的时候,浏览器需要将相关请求数据提交给服务器(例如:浏览器信息,url地址,参数等),通常是通过请求报文来提交的 282 | 283 | * 请求报文的格式分为: 284 | 1. 请求报文行 285 | 2. 请求报文头 286 | 3. 请求报文体 287 | 288 | ![请求报文](./img/day02/请求报文.png) 289 | 290 | 2. http响应报文 291 | 292 | 当浏览器请求服务器的时候,服务器需要将数据返回给浏览器,这种数据是通过响应报文响应回浏览器的 293 | 294 | * 响应报文的格式分为: 295 | 1. 响应报文行 296 | 2. 响应报文头 297 | 3. 响应报文体 298 | 299 | ![响应报文](./img/day02/响应报文.png) 300 | 301 | ### get请求示例 302 | 303 | ```js 304 | axios.get('/user?ID=12345') 305 | .then(function (response) { 306 | console.log(response); 307 | }) 308 | .catch(function (error) { 309 | console.log(error); 310 | }); 311 | 312 | // 或者 313 | axios.get('/user', { 314 | params: { 315 | ID: 12345 316 | } 317 | }) 318 | .then(function (response) { 319 | console.log(response); 320 | }) 321 | .catch(function (error) { 322 | console.log(error); 323 | }); 324 | ``` 325 | 演示代码 326 | 327 | ```js 328 | methods: { 329 | getData: function () { 330 | var url = 'http://157.122.54.189:9093/api/getprodlist' 331 | axios.get(url) 332 | .then(res => { 333 | this.list = res.data.message 334 | console.log(this.list); 335 | }) 336 | .catch(error => { 337 | console.log(error); 338 | }) 339 | } 340 | } 341 | ``` 342 | 343 | ### post请求示例 344 | 345 | ```js 346 | axios.post('/user', { 347 | firstName: 'Fred', 348 | lastName: 'Flintstone' 349 | }) 350 | .then(function (response) { 351 | console.log(response); 352 | }) 353 | .catch(function (error) { 354 | console.log(error); 355 | }); 356 | ``` 357 | 演示代码 358 | 359 | ```js 360 | methods: { 361 | getData: function () { 362 | var url = 'http://157.122.54.189:9093/api/addproduct' 363 | axios.post(url, "name=hello") 364 | .then(res => { 365 | console.log(res); 366 | }) 367 | .catch(error => { 368 | console.log(error); 369 | }) 370 | } 371 | } 372 | ``` 373 | 374 | ## 案例-品牌管理API 375 | 376 | 377 | | 接口说明 | URL | 请求方式 | 参数 | 成功返回 | 失败返回 | 378 | | ---------------- | --------------------------------------------- | -------- | ------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | 379 | | 获取品牌数据列表 | http://157.122.54.189:9093/api/getprodlist | GET | searchvalue(可选) | {"status": 0,"message": [{"id": 104772,"name": "LV","ctime": "2017-12-05T08:35:57.000Z"}]} | 未做处理 | 380 | | 添加品牌数据 | http://157.122.54.189:9093/api/addproduct | POST | name(必填) | {"status": 0,"message": "新增品牌成功"} | 未做处理 | 381 | | 删除品牌数据 | http://157.122.54.189:9093/api/delproduct/:id | GET | id(必填) | {"status": 0, "message": "删除品牌数据ok"} | {"status": 1,"message": "ER_BAD_FIELD_ERROR: Unknown column 'xxx' in 'where clause'"} | 382 | 383 | ## 案例-axios版获取及删除数据 384 | 385 | ```html 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | Document 394 | 395 | 396 | 425 | 426 | 427 | 428 |
429 |
430 | 编号: 431 | 品牌名称: 432 | 433 | 434 |
435 | 436 |
437 | 品牌名称: 438 | 439 |
440 | 441 |
442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 456 | 457 | 458 | 459 | 460 | 461 |
编号品牌名称创立时间操作
{{item.id}}{{item.title}}{{item.ctime}} 454 | 455 |
没有品牌数据
462 |
463 |
464 | 465 | 498 | 499 | 500 | ``` 501 | 502 | ## vue-resource(不推荐使用) 503 | 504 | 一个使用 XMLHttpRequest 或者 JSONP处理请求的vue插件 505 | 506 | [vue-resource文档](https://github.com/pagekit/vue-resource) 507 | 508 | 509 | * 书写步骤 510 | ```js 511 | 1. 通过 https://cdn.jsdelivr.net/vue.resource/1.2.1/vue-resource.min.js 下载到vue-resource文件 512 | 513 | 2. 在html页面中通过script标签导入vue-resource.min.js 文件后,就会自动的在Vue对象实例上初始化 $http 514 | 515 | 3. 使用 516 | // 全局Vue构造器写法 517 | Vue.http.get('/someUrl', [options]).then(successCallback, errorCallback); 518 | Vue.http.post('/someUrl', [body], [options]).then(successCallback, errorCallback); 519 | 520 | // 在Vue实例中的写法 521 | this.$http.get('/someUrl', [options]).then(successCallback, errorCallback); 522 | this.$http.post('/someUrl', [body], [options]).then(successCallback, errorCallback); 523 | ``` 524 | 525 | * vue-resource get请求 526 | 527 | ```js 528 | 写法格式: 529 | this.$http.get('请求的url', [可选参数对象,使用{}传参]).then(成功回调函数, 失败回调函数); 530 | 531 | 成功回调函数参数对象主要属性说明: 532 | 1. url : 请求的原始url 533 | 2. body: 响应报文体中的数据(我们通常用这个属性获取服务器返回的数据) 534 | 3. 其他属性请看文档 535 | 536 | 举例: 537 | this.$http.get('http://vuecms.ittun.com/api/getlunbo?id=1').then(function(res){console.log(res.body)}, function(err){//err是异常数据}); 538 | ``` 539 | 540 | * vue-resource post请求 541 | 542 | ```js 543 | 写法格式: 544 | this.$http.post('请求的url',[可选参数请求报文体对象body,使用{}传参], [可选参数对象,使用{}传参]).then(成功回调函数, 失败回调函数); 545 | 546 | 成功回调函数参数对象主要属性说明: 547 | 1. url : 请求的原始url 548 | 2. body: 响应报文体中的数据(我们通常用这个属性获取服务器返回的数据) 549 | 3. 其他属性请看文档 550 | 551 | 注意点: 552 | $http.post()方法中的第二个参数固定写成:{emulateJSON:true},否则可能造成服务器无法接收到请求报文体中的参数值 553 | 554 | 举例: 555 | this.$http.post('http://vuecms.ittun.com/api/adddata?id=1' //请求的url 556 | ,{content:'hello'} //请求报文体中传入的参数对象,多个使用逗号分隔 557 | ,{emulateJSON:true} //固定写法,保证服务器可以获取到请求报文体参数值 558 | ).then(function(res){console.log(res.body)}, function(err){//err是异常数据}); 559 | ``` 560 | 561 | * vue-resource jsonp请求 562 | 563 | ![jsonp跨域原理解析](./img/day02/jsonp跨域原理解析.png) 564 | 565 | ```js 566 | jsonp请求主要用来解决ajax跨域请求问题,使用jsonp实现跨域首先要保证服务器api支持jsonp请求的格式 567 | 568 | 写法格式: 569 | this.$http.jsonp('请求的url', [可选参数对象,使用{}传参]).then(成功回调函数, 失败回调函数); 570 | 571 | 成功回调函数参数对象主要属性说明: 572 | 1. url : 请求的原始url 573 | 2. body: 响应报文体中的数据(我们通常用这个属性获取服务器返回的数据) 574 | 3. 其他属性请看文档 575 | 576 | 举例: 577 | this.$http.jsonp('http://157.122.54.189:9093/jsonp').then(function(res){console.log(res.body)}, function(err){//err是异常数据}); 578 | ``` 579 | 580 | ## vue过渡&动画 581 | 582 | Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入或离开的过渡 583 | * 条件渲染 (使用 v-if) 584 | * 条件展示 (使用 v-show) 585 | * 动态组件 586 | 587 | ### transition的作用 588 | 589 | 将需要添加过渡的元素用transition组件包裹起来,结合css或者js钩子函数就能实现该元素进入或者离开的动画效果 590 | 591 | ### transition结合css实现过渡 592 | 593 | ```html 594 | 610 | 611 | 612 | hello 黑马 613 | 614 | ``` 615 | 动画图解
616 | ![transition结合css实现过渡](./img/day02/transition结合css实现过渡.png) 617 | 618 | ### transition结合animate.css实现过渡 619 | 620 | ```html 621 | 622 | 623 | 624 | 634 | 635 | hello 黑马 636 | 637 | ``` 638 | 639 | ### transition结合钩子函数实现过渡 640 | 641 | 1. 过渡动画进入 642 | before-enter 过渡动画进入之前,一般在这个方法中定义目标元素的初始位置 643 | enter 过渡动画进入中,在这个方法中定义目标元素的结束位置 644 | after-enter 过渡动画结束后,通常在这个方法里面重置初始值 645 | enter-cancelled 取消过渡动画时被调用 646 | 647 | 2. 过渡动画离开 648 | before-leave 动画离开之前触发 649 | leave 过渡动画进入中触发 650 | after-leave 过渡动画离开结束后 651 | leave-cancelled 取消过渡动画时被调用 652 | 653 | ```html 654 | 659 | hello 黑马 660 | 661 | ``` 662 | ```js 663 | methods: { 664 | // 1.0 动画进入前 665 | beforeEnter: function (el) { 666 | console.log('1.0 beforeEnter'); 667 | 668 | // 在这个方法中设定当前动画元素的起始位置 669 | el.style = "padding-left:100px"; 670 | }, 671 | // 2.0 动画执行中 672 | // el:动画的元素dom对象 673 | // done:enter事件执行完以后的回调,执行了它之后,afterEnter事件才会执行 674 | enter: function (el, done) { 675 | console.log('2.0 enter'); 676 | 677 | var step = 3; 678 | var interval = setInterval(() => { 679 | el.style.paddingLeft = (100 - step) + 'px'; 680 | step++; 681 | if (parseInt(el.style.paddingLeft) <= 0) { 682 | clearInterval(interval) 683 | // 动画结束后必须执行done()函数 684 | done() 685 | } 686 | }, 10) 687 | }, 688 | // 3.0 动画执行完毕 689 | afterEnter: function (el) { 690 | console.log('3.0 afterEnter'); 691 | // 将isshow重置为false即可 692 | this.isshow = false; 693 | }, 694 | showhide: function () { 695 | this.isshow = !this.isshow; 696 | } 697 | } 698 | ``` -------------------------------------------------------------------------------- /笔记(汇总)/Vue基础-day03.md: -------------------------------------------------------------------------------- 1 | Vue基础-day03 2 | === 3 | 4 | 5 | 6 | - [Vue组件](#vue组件) 7 | - [Vue组件的创建](#vue组件的创建) 8 | - [vue.extend结合vue.component创建](#vueextend结合vuecomponent创建) 9 | - [vue.component创建](#vuecomponent创建) 10 | - [template方式创建](#template方式创建) 11 | - [组件中的指令以及事件绑定](#组件中的指令以及事件绑定) 12 | - [父子组件创建](#父子组件创建) 13 | - [父子组件通信](#父子组件通信) 14 | - [父组件传值给子组件(props)](#父组件传值给子组件props) 15 | - [子组件传值给父组件($emit)](#子组件传值给父组件emit) 16 | - [利用component组件和is属性实现动态组件](#利用component组件和is属性实现动态组件) 17 | - [组件生命周期](#组件生命周期) 18 | - [vue-router(路由)](#vue-router路由) 19 | - [vue-router入门](#vue-router入门) 20 | - [vur-router传参](#vur-router传参) 21 | - [vue-router嵌套](#vue-router嵌套) 22 | 23 | 24 | 25 | ## Vue组件 26 | 27 | 组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。所有的 Vue 组件同时也都是 Vue 的实例,所以可接受相同的选项对象 (除了一些根级特有的选项) 并提供相同的生命周期钩子。 28 | 29 | ### Vue组件的创建 30 | 31 | #### vue.extend结合vue.component创建 32 | 33 | ![vue.extend和vuecomponent创建组件](./img/day03/vue.extend和vuecomponent创建组件.png) 34 | 35 | #### vue.component创建 36 | 37 | ![vuecomponent创建组件](./img/day03/vuecomponent创建组件.png) 38 | 39 | #### template方式创建 40 | 41 | ![template创建组件](./img/day03/template创建组件.png) 42 | 43 | ### 组件中的指令以及事件绑定 44 | 45 | ![组件间指令和事件的使用](./img/day03/组件中指令和事件的使用.png) 46 | 47 | ### 父子组件创建 48 | 49 | ![父子组件](./img/day03/父子组件.png) 50 | 51 | ### 父子组件通信 52 | 53 | #### 父组件传值给子组件(props) 54 | 55 | ![父组件传值给子组件页面.png](./img/day03/父组件传值给子组件页面.png) 56 | 57 | ![父组件传值给子组件](./img/day03/父组件传值给子组件.png) 58 | 59 | #### 子组件传值给父组件($emit) 60 | 61 | ![子组件传值给父组件](./img/day03/子组件传值给父组件页面.png) 62 | 63 | ![子组件传值给父组件](./img/day03/子组件传值给父组件.png) 64 | 65 | ### 利用component组件和is属性实现动态组件 66 | 67 | ![动态组件](./img/day03/动态组件页面.png) 68 | 69 | ![动态组件](./img/day03/动态组件.png) 70 | 71 | ## 组件生命周期 72 | 73 | ```js 74 | 75 |
76 |

{{info}}

77 | 78 | 79 |
80 | 150 | 151 | ``` 152 | 153 | ## vue-router(路由) 154 | 155 | [vue-router文档](https://router.vuejs.org/zh-cn/) 156 | 157 | 在一个系统中会由很多页面组成,在Vue开发中这些页面通常使用的是Vue中的组件来实现的,那么当在一个页面要跳转到另外一个页面的时候是通过改变url路径来实现的,那么这个时候Vue需要知道当前url对应的是哪个组件页面,这个控制着就是vue-router接下来,学习vue-router的相关写法,注意的是:vue-router 在vue2.0版本中做了很大的改动,所以要注意Vue的版本来选择预期对应的vue-router版本我们主讲vue-router2的使用 158 | 159 | ### vue-router入门 160 | 161 | ![路由入门页面](./img/day03/路由入门页面.png) 162 | ![路由入门](./img/day03/路由入门.png) 163 | 164 | ### vur-router传参 165 | 166 | ![vue-router传参页面](./img/day03/vue-router传参页面.png) 167 | 168 | ![vue-router传参](./img/day03/vue-router传参.png) 169 | 170 | ### vue-router嵌套 171 | 172 | ![路由嵌套页面](./img/day03/路由嵌套页面.png) 173 | 174 | ![路由嵌套](./img/day03/路由嵌套.png) 175 | 176 | 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /笔记(汇总)/Vue基础-day04.md: -------------------------------------------------------------------------------- 1 | Vue基础-day04 2 | === 3 | 4 | 5 | 6 | - [webpack](#webpack) 7 | - [什么是webpack](#什么是webpack) 8 | - [为什么需要webpack](#为什么需要webpack) 9 | - [webpack安装](#webpack安装) 10 | - [使用webpack](#使用webpack) 11 | - [01-webpack-cli](#01-webpack-cli) 12 | - [02-webpack-config](#02-webpack-config) 13 | - [03-webpack-dev-server](#03-webpack-dev-server) 14 | - [04-webpack-css](#04-webpack-css) 15 | - [05-webpack-less&webpack-sass](#05-webpack-lesswebpack-sass) 16 | - [06-webpack-图片&字体](#06-webpack-图片字体) 17 | - [07-webpack-html](#07-webpack-html) 18 | - [08-webpack-babel](#08-webpack-babel) 19 | 20 | 21 | 22 | ## webpack 23 | 24 | ### 什么是webpack 25 | 26 | webpack 是一个现代 JavaScript 应用程序的模块打包器(module bundler),分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Sass,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。 27 | 28 | ![webpack是什么](./img/day03/webpack是什么.png) 29 | 30 | ### 为什么需要webpack 31 | 32 | 现在的前端,越来越复杂,特别是SPA(single page web application)流行之后,一个应用程序往往会依赖很多其他的模块,或者编译scss、less、stylus等,如果仅仅是靠人来管理是不可能的,这个时候我们必须依赖于webpack来解决。 33 | 34 | 现在最流行的三个SPA的框架,都于webpack紧密相连。 35 | * React.js + webpack 36 | * Vue.js + webpack 37 | * Angular.js + webpack 38 | 39 | 学习webpack有4个重点内容: 40 | * 入口(entry) 41 | * 输出(output) 42 | * 加载器(loader) 43 | * 插件(plugins) 44 | 45 | ### webpack安装 46 | 47 | 注意:请先安装node环境 48 | 49 | `npm install webpack@3.11.0 -g` 50 | 51 | 建议大家这样操作(随时切换镜像源): 52 | 1. npm install nrm -g // 安装nrm 53 | 2. nrm ls // 查看镜像源 54 | 3. nrm use taobao // 选择淘宝镜像,也可以选择cnpm 55 | 56 | ### 使用webpack 57 | 58 | #### 01-webpack-cli 59 | 60 | 使用命令:`webpack 输入文件路径 打包后文件路径`将一个文件打包成另外一个文件 61 | 62 | #### 02-webpack-config 63 | 64 | 1. 配置webpack.config.js 65 | 2. 运行`webpack` 66 | 67 | ```js 68 | var path = require('path') 69 | 70 | module.exports = { 71 | // 入口文件配置 72 | entry: "./src/app.js", 73 | 74 | // 出口文件配置项 75 | output: { 76 | // 输出的路径,webpack2起就规定必须是绝对路径 77 | path: path.join(__dirname, 'dist'), 78 | // 输出文件名字 79 | filename: "bundle.js" 80 | } 81 | } 82 | ``` 83 | 84 | #### 03-webpack-dev-server 85 | 86 | 默认为--inline模式 87 | 88 | 1. 运行:`npm init -y` 89 | 2. 运行:`npm i webpack-dev-server@2.9.7 webpack@3.11.0 -D` 90 | ```js 91 | var path = require('path') 92 | 93 | module.exports = { 94 | // 入口文件配置 95 | entry: "./src/app.js", 96 | 97 | // 输出配置 98 | output: { 99 | // 输出的路径 100 | path: path.join(__dirname, 'dist'), 101 | // 静态资源在服务器上运行时的访问路径,可以直接http://localhost:8080/dist/bundle.js访问到服务器中的bundle.js文件 102 | publicPath: '/dist', 103 | // 输出文件名字 104 | filename: "bundle.js" 105 | } 106 | } 107 | ``` 108 | 3. index.html中修改 `` 109 | 110 | 4. 运行:`webpack-dev-server` 111 | 5. 运行:`webpack-dev-server --inline --hot --open --port 8090` 112 | 6. 配置script:`"dev": "webpack-dev-server --inline --hot --open --port 8090"` 113 | 7. `npm run dev` 114 | 115 | #### 04-webpack-css 116 | 117 | 1. 安装`npm install css-loader style-loader --save-dev` 118 | 119 | ```js 120 | module: { 121 | rules: [ 122 | // 配置的是用来解析.css文件的loader(style-loader和css-loader) 123 | { 124 | // 1.0 用正则匹配当前访问的文件的后缀名是 .css 125 | test: /\.css$/, 126 | use: ['style-loader', 'css-loader'] //webpack底层调用这些包的顺序是从右到左 127 | } 128 | ] 129 | } 130 | ``` 131 | 132 | #### 05-webpack-less&webpack-sass 133 | 134 | `npm install less less-loader sass-loader node-sass --save-dev` 135 | 136 | ```js 137 | { 138 | test: /\.less$/, 139 | use: [{ 140 | loader: 'style-loader' 141 | }, { 142 | loader: 'css-loader' 143 | }, { 144 | loader: 'less-loader' 145 | }] 146 | }, 147 | ``` 148 | 149 | ```js 150 | { 151 | test: /\.scss$/, 152 | use: [{ 153 | loader: 'style-loader' 154 | }, { 155 | loader: 'css-loader' 156 | }, { 157 | loader: 'sass-loader' 158 | }] 159 | } 160 | ``` 161 | 162 | 163 | #### 06-webpack-图片&字体 164 | 165 | 1. `npm install file-loader url-loader --save-dev` 166 | 167 | url-loader封装了file-loader 168 | 169 | ```js 170 | { 171 | test: /\.(png|jpg|gif)/, 172 | use: [{ 173 | loader: 'url-loader', 174 | options: { 175 | // limit表示如果图片大于50000byte,就以路径形式展示,小于的话就用base64格式展示 176 | limit: 50000 177 | } 178 | }] 179 | } 180 | ``` 181 | 182 | #### 07-webpack-html 183 | 184 | 1. `npm install html-webpack-plugin --save-dev` 185 | 186 | 2. 如果添加了title,需要在模板中添加`<%= htmlWebpackPlugin.options.title %>` 187 | 188 | ```js 189 | // 注意需要注释掉publicPath,不然会冲突 190 | 191 | var HtmlWebpackPlugin = require('html-webpack-plugin') 192 | 193 | plugins: [ 194 | new HtmlWebpackPlugin({ 195 | filename: 'index.html', 196 | template: 'template.html' 197 | }) 198 | ] 199 | ``` 200 | 201 | #### 08-webpack-babel 202 | 203 | 1. `npm install babel-core babel-loader babel-preset-env --save-dev` 204 | 205 | 注意: 206 | 207 | webpack 1.x | babel-loader <= 6.x 208 | 209 | webpack 2.x | babel-loader >= 7.x (推荐) (^6.2.10 也能用, 但是会出现不推荐使用的警告) 210 | 211 | webpack 3.x | babel-loader >= 7.1 212 | 213 | ```js 214 | { 215 | test: /\.js$/, 216 | // Webpack2建议尽量避免exclude,更倾向于使用include 217 | // exclude: /(node_modules)/, // node_modules下面的.js文件会被排除 218 | include: [path.resolve(__dirname, 'src')] 219 | use: { 220 | loader: 'babel-loader', 221 | // options里面的东西可以放到.babelrc文件中去 222 | options: { 223 | presets: ['env'] 224 | } 225 | } 226 | } 227 | 228 | // .babelrc文件内的配置 229 | { 230 | "presets":["env"] 231 | } 232 | ``` 233 | 234 | 235 | -------------------------------------------------------------------------------- /笔记(汇总)/Vue基础-day05.md: -------------------------------------------------------------------------------- 1 | Vue基础-day05 2 | === 3 | 4 | 5 | 6 | - [单文件组件](#单文件组件) 7 | - [结合webpack处理单文件组件](#结合webpack处理单文件组件) 8 | - [配置webpack相关loader](#配置webpack相关loader) 9 | - [使用vue文件创建vue组件](#使用vue文件创建vue组件) 10 | - [引入组件,并将组件渲染到页面](#引入组件并将组件渲染到页面) 11 | - [路由配置](#路由配置) 12 | - [vue-cli 脚手架工具](#vue-cli-脚手架工具) 13 | - [element-ui](#element-ui) 14 | - [项目相关](#项目相关) 15 | - [团队角色](#团队角色) 16 | - [开发流程](#开发流程) 17 | - [技术选型](#技术选型) 18 | - [前端](#前端) 19 | - [后端](#后端) 20 | - [项目业务分析](#项目业务分析) 21 | - [项目初始化](#项目初始化) 22 | 23 | 24 | 25 | ## 单文件组件 26 | 27 | [单文件组件](https://cn.vuejs.org/v2/guide/single-file-components.html) 28 | 29 | ### 结合webpack处理单文件组件 30 | 31 | #### 配置webpack相关loader 32 | 33 | 1. `npm install vue --save` 34 | 2. `npm install vue-loader vue-template-compiler --save-dev` 35 | 36 | 37 | ```js 38 | { 39 | test: /\.vue$/, 40 | loader: 'vue-loader' 41 | } 42 | 43 | // 如果使用的是webpack1.x,还需要安装 `babel-plugin-transform-runtime`,并添加一下配置;如果是webpack2.x以上请忽略一下配置 44 | { 45 | test: /\.js$/, 46 | include: [path.resolve(__dirname, 'src')], 47 | use: { 48 | loader: 'babel-loader', 49 | // options里面的东西可以放到.babelrc文件中去 50 | options: { 51 | presets: ['env'] 52 | // plugins: ['transform-runtime'] 53 | } 54 | } 55 | } 56 | 57 | ``` 58 | 59 | #### 使用vue文件创建vue组件 60 | 61 | ```html 62 | 63 | 64 | 67 | 76 | 81 | ``` 82 | 83 | #### 引入组件,并将组件渲染到页面 84 | 85 | ```js 86 | // app.js 87 | import Vue from 'vue' 88 | import App from './App.vue' 89 | 90 | new Vue({ 91 | el: '#app', 92 | render: h=> h(App) 93 | }) 94 | ``` 95 | 96 | #### 路由配置 97 | 98 | 1. `npm install vue-router --save` 99 | 100 | ```js 101 | // app.js 102 | import Vue from 'vue' 103 | import App from './App.vue' 104 | 105 | import Login from './Login.vue' 106 | 107 | // 1. 引入vue-router 108 | import VueRouter from 'vue-router' 109 | 110 | // 2. 表示使用路由插件 111 | Vue.use(VueRouter) 112 | 113 | //3. 配置路由规则 114 | var router = new VueRouter({ 115 | routes: [ 116 | { name: 'login', path: '/login', component: Login } 117 | ] 118 | }) 119 | 120 | new Vue({ 121 | el: '#app', 122 | // 挂载路由 123 | router, 124 | // 这是个渲染函数,指定渲染组件 125 | render: h => h(App) 126 | }) 127 | ``` 128 | 129 | ## vue-cli 脚手架工具 130 | 131 | vue-cli是官方的一个脚手架工具,所谓脚手架呢就是一个架子,什么架子呢?项目结构的架子,里面有一些最基本的结构配置。利用vue-cli呢,我们可以生成这样的一个脚手架,所以呢它就被称为vue脚手架工具。 132 | 133 | `npm install vue-cli -g` 134 | 135 | `vue init webpack admin` 136 | 137 | ## element-ui 138 | 139 | 安装:`npm i element-ui -S` 140 | 141 | [element-ui使用](http://element-cn.eleme.io/2.0/#/zh-CN/component/quickstart) 142 | 143 | ## 项目相关 144 | 145 | [电商后台管理系统](http://47.96.21.88/#/login) (不要随便删) 146 | 147 | ### 团队角色 148 | 149 | - 产品经理 150 | - 项目经理 151 | - UI/UE 152 | - 前端 153 | - 后端(php/java/python/Node.js/.net) 154 | - 测试(单元测试、黑盒测试、白盒测试、集成测试、压力测试) 155 | - DBA 数据库管理员 156 | - 实施/运维 负责程序的上线和运行监控 157 | - 全栈工程师 158 | 159 | ### 开发流程 160 | 161 | - 需求分析 162 | - 概要设计 163 | - 详细设计 164 | - 编码 165 | - 测试 166 | - 上线 167 | - 运维-迭代更新 168 | 169 | ### 技术选型 170 | 171 | #### 前端 172 | 173 | - vue 174 | - vue-router 175 | - axios 176 | - Element-UI 177 | - webpack 178 | 179 | #### 后端 180 | 181 | - node.js 182 | - express 183 | - mysql 184 | 185 | ### 项目业务分析 186 | 187 | - 电商业务 188 | + 对外网站(用户购买) 189 | + 后台管理端(用于运营人员) 190 | + 移动Web 191 | + APP 192 | + 数据分析(用户行为分析) 193 | + 数据统计系统(财务) 194 | 195 | ### 项目初始化 196 | 197 | - styles 198 | - element.scss 用于覆盖element中的样式 199 | - reset.scss 用于重置一些标签的默认样式 200 | - index.scss 引入其他scss文件,写一些通用样式 201 | - 安装处理sass相关的loader 202 | - views 203 | 204 | 205 | [码云](https://gitee.com/login) 206 | 1. 码云上创建一个空的项目(不能选readme文件选项) 207 | 2. 创建本地的git仓库`git init` 208 | 3. 将本地仓库关联到远端 209 | 4. `git add .` 210 | 5. `git commit -m 'init project'` 211 | 6. `git push` (这里有可能报错,按提示 git push --set-upstream origin master)(会提示输入码云的账户密码 ) 212 | 7. 创建并切换到新分支`git checkout -b xx分支` 213 | 8. `git add .` 214 | 9. `git commit -m "xxxx"` 215 | 10. `git push` (可能会报错,按照提示push) 216 | 11. `git checkout master` 217 | 12. `git merge xx分支` 218 | 13. `git branch -d xx分支` 219 | 14. `git add .` 220 | 15. `git commit -m "xxx"` 221 | 16. `git push` -------------------------------------------------------------------------------- /笔记(汇总)/Vue项目.md: -------------------------------------------------------------------------------- 1 | Vue项目 2 | === 3 | 4 | 5 | 6 | - [登录](#登录) 7 | - [登录页面](#登录页面) 8 | - [表单校验](#表单校验) 9 | - [登录状态保存](#登录状态保存) 10 | - [axios拦截器](#axios拦截器) 11 | - [导航守卫](#导航守卫) 12 | - [首页布局](#首页布局) 13 | - [侧边栏部分](#侧边栏部分) 14 | - [头部部分](#头部部分) 15 | - [中间内容部分](#中间内容部分) 16 | - [Vuex](#vuex) 17 | - [Vuex是什么](#vuex是什么) 18 | - [Vuex使用场景](#vuex使用场景) 19 | - [Vuex 核心内容](#vuex-核心内容) 20 | - [使用vuex](#使用vuex) 21 | - [用户管理](#用户管理) 22 | - [用户列表](#用户列表) 23 | - [权限管理](#权限管理) 24 | - [权限列表](#权限列表) 25 | - [角色列表](#角色列表) 26 | - [商品管理](#商品管理) 27 | - [商品分类](#商品分类) 28 | - [商品列表](#商品列表) 29 | 30 | 31 | 32 | ******** 33 | 34 | [项目接口文档](http://47.96.21.88:8082/) 35 | 36 | [项目地址](http://47.96.21.88/#/login) 37 | 38 | ## 登录 39 | 40 | ### 登录页面 41 | 42 | ```scss 43 | .login { 44 | position: fixed; 45 | width: 100%; 46 | height: 100%; 47 | background-color: #2f4050; 48 | 49 | .container { 50 | position: absolute; 51 | left: 0; 52 | right: 0; 53 | width: 400px; 54 | padding: 0px 40px 15px 40px; 55 | margin: 200px auto; 56 | background: white; 57 | .avatar { 58 | position: relative; 59 | left: 50%; 60 | width: 120px; 61 | height: 120px; 62 | margin-left: -60px; 63 | margin-top: -60px; 64 | box-sizing: border-box; 65 | border-radius: 50%; 66 | border: 10px solid #fff; 67 | box-shadow: 0 1px 5px #ccc; 68 | overflow: hidden; 69 | } 70 | .login-btn { 71 | width: 100%; 72 | } 73 | } 74 | } 75 | ``` 76 | 77 | ### 表单校验 78 | 79 | ### 登录状态保存 80 | 81 | HTTP请求是无状态的 82 | 83 | - cookie 84 | - 保存在客户端 85 | - 数据量小(很多站点对cookie的大小和数量都进行了限制) 86 | - 不安全(别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,也可能被拦截) 87 | - session 88 | - 服务器端 89 | - 安全 90 | - session可以依赖cookie,也可以不依赖使用url 91 | - 访问量增多,占用服务器资源,如果服务器挂了,所有保存的信息都没了 92 | - token 93 | - 服务器不存用户状态,定义通用算法 94 | - 客户端第一次登录之后,服务器会生成一个token,返回给客户端 95 | - 后续所有请求都会带着token 96 | - 服务器根据算法校验token的合法性 97 | 98 | ### axios拦截器 99 | 100 | [axios](https://github.com/axios/axios) --> Interceptors 101 | 102 | ```js 103 | // 添加请求拦截器 104 | axios.interceptors.request.use(function (config) { 105 | // 将token给到一个前后台约定好的key中,作为请求发送 106 | let token = localStorage.getItem('mytoken') 107 | if (token) { 108 | config.headers['Authorization'] = token 109 | } 110 | return config 111 | }, function (error) { 112 | // Do something with request error 113 | return Promise.reject(error) 114 | }) 115 | ``` 116 | 117 | ### 导航守卫 118 | 119 | [导航守卫](https://router.vuejs.org/zh-cn/advanced/navigation-guards.html) 120 | 121 | ```js 122 | router.beforeEach((to, from, next) => { 123 | let token = localStorage.getItem('mytoken') 124 | // 如果已经登录,那我不干涉你,让你随便访问 125 | if (token) { 126 | next() 127 | } else { 128 | if (to.path !== '/login') { 129 | // 如果没有登录,但你访问其他需要登录的页面,那我就让你跳到登录页面去 130 | next({path: '/login'}) 131 | } else { 132 | // 如果没有登录,但你访问的login,那就不干涉你,让你访问 133 | next() 134 | } 135 | } 136 | }) 137 | ``` 138 | 139 | ## 首页布局 140 | 141 | ### 侧边栏部分 142 | 143 | ### 头部部分 144 | 145 | ### 中间内容部分 146 | 147 | ```scss 148 | .home { 149 | height: 100%; 150 | background-color: #E5E5E5; 151 | .el-menu-admin:not(.el-menu--collapse) { 152 | width: 200px; 153 | min-height: 400px; 154 | } 155 | .el-container { 156 | height: 100%; 157 | } 158 | .el-aside { 159 | background-color: #545c64; 160 | } 161 | .el-header { 162 | display: flex; 163 | justify-content: space-between; 164 | align-items: center; 165 | background-color: #009688; 166 | } 167 | .logo { 168 | height:60px; 169 | background: url(../assets/logo.png); 170 | background-size: cover; 171 | background-color: white; 172 | } 173 | .toggle-btn { 174 | padding: 0 10px; 175 | margin-left: -20px; 176 | font-size: 36px; 177 | line-height: 60px; 178 | color: white; 179 | cursor: pointer; 180 | &:hover { 181 | background-color: #00635a; 182 | } 183 | } 184 | .system-title { 185 | font-size: 28px; 186 | color: white; 187 | } 188 | .welcome, { 189 | color: white; 190 | } 191 | } 192 | ``` 193 | 194 | ## Vuex 195 | 196 | ### Vuex是什么 197 | 198 | Vuex是一个针对Vue.js开发的状态管理模式。说简单点儿就是一个工具,可以管理(修改或设置)所有组件用到的数据,而不需要借助之前的event bus或者props在组件间传值。 199 | 200 | ### Vuex使用场景 201 | 202 | 大型单页应用程序,存在多组件共享数据的时候,需要用到 203 | 204 | ### Vuex 核心内容 205 | 206 | ![vuex](./img/vuex.png) 207 | 208 | store (一个容器对象,存储Vuex中的state,mutations,actions,getters等) 209 | - state (一个保存数据的对象,对象中的数据可以供所有组件使用) 210 | ```js 211 | // 1. 定义 212 | const state = { 213 | count: 0 214 | } 215 | 216 | // 2. 获取state中的值 217 | this.$store.state.count 218 | 219 | // mapState 辅助函数获取多个state的值 220 | import { mapState } from 'vuex' 221 | computed: mapState({ 222 | // 箭头函数可使代码更简练 223 | count: state => state.count, 224 | // 传字符串参数 'count' 等同于 `state => state.count` 225 | countAlias: 'count', 226 | }) 227 | computed: mapState([ 228 | // 映射 this.count 为 store.state.count 229 | 'count' 230 | ]) 231 | 232 | // 3. 与组件的计算属性混合使用 233 | computed: { 234 | localComputed () { /* ... */ }, 235 | // 使用对象展开运算符将此对象混入到外部对象中 236 | ...mapState({ 237 | // ... 238 | }) 239 | } 240 | ``` 241 | - mutations(一个对象,保存的是更改state的函数,也只有它能更改state中的值,触发方式this.$store.commit('函数名',参数)) 242 | ```js 243 | // 1. 定义 244 | const mutations = { 245 | increment (state) { 246 | state.count++ 247 | } 248 | } 249 | 250 | // 2. 触发 251 | this.$store.commit('increment') 252 | 253 | // 3. 传递参数,通常参数应该是一个对象 254 | mutations: { 255 | increment (state, n) { 256 | state.count += n 257 | } 258 | } 259 | this.$store.commit('increment', 10) 260 | 261 | // 4. 在组件的方法中使用 262 | methods: { 263 | ...mapMutations([ 264 | 'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')` 265 | 266 | // `mapMutations` 也支持载荷: 267 | 'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)` 268 | ]), 269 | ...mapMutations({ 270 | add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')` 271 | }) 272 | } 273 | ``` 274 | - actions(一个对象,保存的是触发mutations的函数,让mutations去修改state中的值) 275 | ```js 276 | // 1. 定义 277 | const actions = { 278 | increment: ({ commit }) => commit('increment') 279 | } 280 | 281 | // 2. 触发 282 | this.$store.dispatch('increment') 283 | 284 | // 3. 参数支持 285 | this.$store.dispatch('incrementAsync', { 286 | amount: 10 287 | }) 288 | 289 | // 4. 组件的方法中使用 290 | methods: { 291 | ...mapActions([ 292 | 'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')` 293 | 294 | // `mapActions` 也支持载荷: 295 | 'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)` 296 | ]), 297 | ...mapActions({ 298 | add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')` 299 | }) 300 | } 301 | ``` 302 | - getters(一个对象,保存的是一些类似与计算属性的函数,可以通过他们得到任何依赖于state的新的数据) 303 | ```js 304 | // 1. 定义 305 | const getters = { 306 | evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd' 307 | } 308 | 309 | // 2. 使用 310 | this.$store.getters.evenOrOdd 311 | 312 | // 3. 使用其他getters作为参数 313 | getters: { 314 | // ... 315 | doneTodosCount: (state, getters) => { 316 | return getters.doneTodos.length 317 | } 318 | } 319 | 320 | // 4. 组件内使用 321 | export default { 322 | // ... 323 | computed: { 324 | // 使用对象展开运算符将 getter 混入 computed 对象中 325 | ...mapGetters([ 326 | 'doneTodosCount', 327 | 'anotherGetter', 328 | // ... 329 | ]) 330 | } 331 | } 332 | ``` 333 | 334 | ### 使用vuex 335 | 336 | `npm install vuex -S` 337 | 338 | ```js 339 | 340 | // store.js 341 | import Vue from 'vue' 342 | import Vuex from 'vuex' 343 | 344 | Vue.use(Vuex) 345 | const state = {} 346 | const mutations = {} 347 | const actions = {} 348 | const getters = {} 349 | export default new Vuex.Store({ 350 | state, 351 | getters, 352 | actions, 353 | mutations 354 | }) 355 | 356 | // app.js 357 | import store from './store' 358 | 359 | new Vue({ 360 | el: '#app', 361 | store, 362 | render: h => h(Counter) 363 | }) 364 | ``` 365 | 366 | ## 用户管理 367 | 368 | ### 用户列表 369 | ```scss 370 | /* 覆盖element导航菜单的样式 */ 371 | .el-breadcrumb { 372 | background-color: #D3DCE6; 373 | height: 45px; 374 | font-size: 15px; 375 | padding-left: 10px; 376 | line-height: 45px; 377 | margin-bottom: 15px; 378 | } 379 | ``` 380 | 381 | ```scss 382 | .user { 383 | .search-input { 384 | width: 300px; 385 | } 386 | .page { 387 | padding: 5px 0; 388 | background-color: #D3DCE6; 389 | } 390 | } 391 | ``` 392 | 393 | ```js 394 | // 添加用户的表单验证 395 | rules: { 396 | username: [ 397 | { required: true, message: '请输入用户名', trigger: 'blur' } 398 | ], 399 | password: [ 400 | { required: true, message: '请输入密码', trigger: 'blur' } 401 | ], 402 | email: [ 403 | { required: true, message: '请输入邮箱地址', trigger: 'blur' }, 404 | { type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur,change' } 405 | ], 406 | mobile: [ 407 | { required: true, message: '电话不能为空' } 408 | ] 409 | } 410 | ``` 411 | 412 | ## 权限管理 413 | 414 | ### 权限列表 415 | 416 | ```js 417 | getSeletedRights (role) { 418 | let lastRole, 419 | if (role.children && role.children.length !== 0) { 420 | role.children.map(item => { 421 | this.getSeletedRights(item) 422 | }) 423 | } else { 424 | lastRole = role 425 | this.seletedRights.push(lastRole.id) 426 | } 427 | } 428 | 429 | grantRightSubmit () { 430 | let treeData = this.$refs.tree.getCheckedNodes() 431 | treeData = treeData.map((item) => { 432 | return item.id + ',' + item.pid 433 | }) 434 | treeData = treeData.join(',').split(',') 435 | let rightIds = [...new Set(treeData)] 436 | grantRight(this.currentRole.id, {rids: rightIds.join(',')}).then(res => { 437 | console.log(res) 438 | }) 439 | } 440 | ``` 441 | 442 | ### 角色列表 443 | 444 | ## 商品管理 445 | 446 | ### 商品分类 447 | 448 | ### 商品列表 449 | -------------------------------------------------------------------------------- /笔记(汇总)/img/day01/MVVM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day01/MVVM.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day01/为什么学习vue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day01/为什么学习vue.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day01/回车添加数据.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day01/回车添加数据.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day01/案例效果图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day01/案例效果图.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day01/添加数据.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day01/添加数据.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day02/jsonp跨域原理解析.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day02/jsonp跨域原理解析.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day02/transition结合css实现过渡.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day02/transition结合css实现过渡.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day02/响应报文.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day02/响应报文.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day02/请求报文.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day02/请求报文.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/template创建组件.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/template创建组件.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/vue-router传参.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/vue-router传参.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/vue-router传参页面.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/vue-router传参页面.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/vue.extend和vuecomponent创建组件.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/vue.extend和vuecomponent创建组件.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/vuecomponent创建组件.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/vuecomponent创建组件.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/webpack是什么.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/webpack是什么.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/动态组件.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/动态组件.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/动态组件页面.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/动态组件页面.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/子组件传值给父组件.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/子组件传值给父组件.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/子组件传值给父组件页面.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/子组件传值给父组件页面.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/父子组件.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/父子组件.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/父组件传值给子组件.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/父组件传值给子组件.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/父组件传值给子组件页面.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/父组件传值给子组件页面.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/组件中指令和事件的使用.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/组件中指令和事件的使用.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/路由入门.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/路由入门.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/路由入门页面.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/路由入门页面.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/路由嵌套.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/路由嵌套.png -------------------------------------------------------------------------------- /笔记(汇总)/img/day03/路由嵌套页面.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/day03/路由嵌套页面.png -------------------------------------------------------------------------------- /笔记(汇总)/img/vuex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/img/vuex.png -------------------------------------------------------------------------------- /笔记(汇总)/vue基础大纲.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianchengLee/vue-cms20/39b7e9443881bbfe4c8c21e1db8f0437b3b72a87/笔记(汇总)/vue基础大纲.xmind --------------------------------------------------------------------------------