├── .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 └── test.env.js ├── images └── vue-demo.png ├── index.html ├── package-lock.json ├── package.json ├── src ├── App.vue ├── assets │ ├── avactor.png │ ├── fonts │ │ ├── demo.css │ │ ├── demo_index.html │ │ ├── iconfont.css │ │ ├── iconfont.eot │ │ ├── iconfont.js │ │ ├── iconfont.svg │ │ ├── iconfont.ttf │ │ ├── iconfont.woff │ │ └── iconfont.woff2 │ ├── login.jpg │ ├── login_pass.png │ ├── login_user.png │ ├── right-arrow-sel.png │ └── right-arrow.png ├── components │ ├── addTable.vue │ ├── crop.vue │ ├── multiCheckCom.vue │ ├── selectBox.vue │ └── tabs.vue ├── main.js ├── page │ ├── Home.vue │ ├── Login.vue │ ├── dataVisual │ │ ├── ComEcharts.vue │ │ ├── Map.vue │ │ └── SpeEcharts.vue │ ├── fileImg │ │ ├── FileCloud.vue │ │ ├── UploadFile.vue │ │ └── UploadImg.vue │ ├── richText │ │ ├── CustomEditor.vue │ │ └── TextEditor.vue │ └── tableClassify │ │ ├── ComTable.vue │ │ ├── Drag.vue │ │ ├── MergeTable.vue │ │ ├── MultiCheck.vue │ │ └── SpeTable.vue ├── router │ └── index.js ├── store │ ├── index.js │ └── modules │ │ └── comTable.js └── utils │ ├── api.js │ ├── check.js │ ├── config │ ├── cloud.js │ └── index.js │ ├── fileUpdate.js │ ├── mixin │ └── chart.js │ └── request.js ├── static ├── .gitkeep ├── comTable.json ├── css │ └── common.css └── favicon.png └── test └── unit ├── .eslintrc ├── jest.conf.js ├── setup.js └── specs └── HelloWorld.spec.js /.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"], 12 | "env": { 13 | "test": { 14 | "presets": ["env", "stage-2"], 15 | "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.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 | /test/unit/coverage/ 8 | 9 | # Editor directories and files 10 | .idea 11 | .vscode 12 | *.suo 13 | *.ntvs* 14 | *.njsproj 15 | *.sln 16 | -------------------------------------------------------------------------------- /.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-demo 2 | 3 | > vue+vue-router+vuex+element+vue-split-table+vue-multiple-check 4 | > 是一个初学者上手项目的不错demo 5 | > 持续更新中 6 | 7 | ## star 8 | ^_^欢迎star,你的star是我更新的动力^_^ 9 | 10 | ## Build Setup 11 | 12 | ![demo vue](https://github.com/lanzhsh/vue-demo/blob/master/images/vue-demo.png) 13 | 14 | ``` bash 15 | # install dependencies 16 | npm install 17 | 18 | # serve with hot reload at localhost:8080 19 | npm run dev 20 | 21 | # build for production with minification 22 | npm run build 23 | 24 | # build for production and view the bundle analyzer report 25 | npm run build --report 26 | 27 | # run unit tests 28 | npm run unit 29 | 30 | # run all tests 31 | npm test 32 | ``` 33 | 34 | For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 35 | -------------------------------------------------------------------------------- /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/lanzhsh/vue-demo/fa286f0b2c94898fc7f192d370267dcff9972495/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 | 'vue$': 'vue/dist/vue.esm.js', 29 | '@': resolve('src'), 30 | } 31 | }, 32 | module: { 33 | rules: [ 34 | { 35 | test: /\.vue$/, 36 | loader: 'vue-loader', 37 | options: vueLoaderConfig 38 | }, 39 | { 40 | test: /\.js$/, 41 | loader: 'babel-loader', 42 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] 43 | }, 44 | { 45 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 46 | loader: 'url-loader', 47 | options: { 48 | limit: 10000, 49 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 50 | } 51 | }, 52 | { 53 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 54 | loader: 'url-loader', 55 | options: { 56 | limit: 10000, 57 | name: utils.assetsPath('media/[name].[hash:7].[ext]') 58 | } 59 | }, 60 | { 61 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 62 | loader: 'url-loader', 63 | options: { 64 | limit: 10000, 65 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 66 | } 67 | }, 68 | { 69 | test: /\.sass$/, 70 | loaders: ['style', 'css', 'sass'] 71 | } 72 | ] 73 | }, 74 | node: { 75 | // prevent webpack from injecting useless setImmediate polyfill because Vue 76 | // source contains it (although only uses it if it's native). 77 | setImmediate: false, 78 | // prevent webpack from injecting mocks to Node native modules 79 | // that does not make sense for the client 80 | dgram: 'empty', 81 | fs: 'empty', 82 | net: 'empty', 83 | tls: 'empty', 84 | child_process: 'empty' 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /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 = process.env.NODE_ENV === 'testing' 15 | ? require('../config/test.env') 16 | : require('../config/prod.env') 17 | 18 | const webpackConfig = merge(baseWebpackConfig, { 19 | module: { 20 | rules: utils.styleLoaders({ 21 | sourceMap: config.build.productionSourceMap, 22 | extract: true, 23 | usePostCSS: true 24 | }) 25 | }, 26 | devtool: config.build.productionSourceMap ? config.build.devtool : false, 27 | output: { 28 | path: config.build.assetsRoot, 29 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 30 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 31 | }, 32 | plugins: [ 33 | // http://vuejs.github.io/vue-loader/en/workflow/production.html 34 | new webpack.DefinePlugin({ 35 | 'process.env': env 36 | }), 37 | new UglifyJsPlugin({ 38 | uglifyOptions: { 39 | compress: { 40 | warnings: false 41 | } 42 | }, 43 | sourceMap: config.build.productionSourceMap, 44 | parallel: true 45 | }), 46 | // extract css into its own file 47 | new ExtractTextPlugin({ 48 | filename: utils.assetsPath('css/[name].[contenthash].css'), 49 | // Setting the following option to `false` will not extract CSS from codesplit chunks. 50 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack. 51 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, 52 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110 53 | allChunks: true, 54 | }), 55 | // Compress extracted CSS. We are using this plugin so that possible 56 | // duplicated CSS from different components can be deduped. 57 | new OptimizeCSSPlugin({ 58 | cssProcessorOptions: config.build.productionSourceMap 59 | ? { safe: true, map: { inline: false } } 60 | : { safe: true } 61 | }), 62 | // generate dist index.html with correct asset hash for caching. 63 | // you can customize output by editing /index.html 64 | // see https://github.com/ampedandwired/html-webpack-plugin 65 | new HtmlWebpackPlugin({ 66 | filename: process.env.NODE_ENV === 'testing' 67 | ? 'index.html' 68 | : config.build.index, 69 | template: 'index.html', 70 | inject: true, 71 | minify: { 72 | removeComments: true, 73 | collapseWhitespace: true, 74 | removeAttributeQuotes: true 75 | // more options: 76 | // https://github.com/kangax/html-minifier#options-quick-reference 77 | }, 78 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 79 | chunksSortMode: 'dependency' 80 | }), 81 | // keep module.id stable when vendor modules does not change 82 | new webpack.HashedModuleIdsPlugin(), 83 | // enable scope hoisting 84 | new webpack.optimize.ModuleConcatenationPlugin(), 85 | // split vendor js into its own file 86 | new webpack.optimize.CommonsChunkPlugin({ 87 | name: 'vendor', 88 | minChunks (module) { 89 | // any required modules inside node_modules are extracted to vendor 90 | return ( 91 | module.resource && 92 | /\.js$/.test(module.resource) && 93 | module.resource.indexOf( 94 | path.join(__dirname, '../node_modules') 95 | ) === 0 96 | ) 97 | } 98 | }), 99 | // extract webpack runtime and module manifest to its own file in order to 100 | // prevent vendor hash from being updated whenever app bundle is updated 101 | new webpack.optimize.CommonsChunkPlugin({ 102 | name: 'manifest', 103 | minChunks: Infinity 104 | }), 105 | // This instance extracts shared chunks from code splitted chunks and bundles them 106 | // in a separate chunk, similar to the vendor chunk 107 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk 108 | new webpack.optimize.CommonsChunkPlugin({ 109 | name: 'app', 110 | async: 'vendor-async', 111 | children: true, 112 | minChunks: 3 113 | }), 114 | 115 | // copy custom static assets 116 | new CopyWebpackPlugin([ 117 | { 118 | from: path.resolve(__dirname, '../static'), 119 | to: config.build.assetsSubDirectory, 120 | ignore: ['.*'] 121 | } 122 | ]) 123 | ] 124 | }) 125 | 126 | if (config.build.productionGzip) { 127 | const CompressionWebpackPlugin = require('compression-webpack-plugin') 128 | 129 | webpackConfig.plugins.push( 130 | new CompressionWebpackPlugin({ 131 | asset: '[path].gz[query]', 132 | algorithm: 'gzip', 133 | test: new RegExp( 134 | '\\.(' + 135 | config.build.productionGzipExtensions.join('|') + 136 | ')$' 137 | ), 138 | threshold: 10240, 139 | minRatio: 0.8 140 | }) 141 | ) 142 | } 143 | 144 | if (config.build.bundleAnalyzerReport) { 145 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 146 | webpackConfig.plugins.push(new BundleAnalyzerPlugin()) 147 | } 148 | 149 | module.exports = webpackConfig 150 | -------------------------------------------------------------------------------- /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 | '/api': { 15 | target: 'http://127.0.0.1:7001', 16 | changeOrigin: true, 17 | pathRewrite: { 18 | '^/api': 'api' 19 | } 20 | }, 21 | }, 22 | 23 | // Various Dev Server settings 24 | host: '0.0.0.0', // can be overwritten by process.env.HOST 25 | port: 5220, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 26 | autoOpenBrowser: true, 27 | errorOverlay: true, 28 | notifyOnErrors: true, 29 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 30 | 31 | 32 | /** 33 | * Source Maps 34 | */ 35 | 36 | // https://webpack.js.org/configuration/devtool/#development 37 | devtool: 'cheap-module-eval-source-map', 38 | 39 | // If you have problems debugging vue-files in devtools, 40 | // set this to false - it *may* help 41 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 42 | cacheBusting: true, 43 | 44 | cssSourceMap: true 45 | }, 46 | 47 | build: { 48 | // Template for index.html 49 | index: path.resolve(__dirname, '../dist/index.html'), 50 | 51 | // Paths 52 | assetsRoot: path.resolve(__dirname, '../dist'), 53 | assetsSubDirectory: 'static', 54 | assetsPublicPath: '/', 55 | 56 | /** 57 | * Source Maps 58 | */ 59 | 60 | productionSourceMap: false, 61 | // https://webpack.js.org/configuration/devtool/#production 62 | devtool: '#source-map', 63 | 64 | // Gzip off by default as many popular static hosts such as 65 | // Surge or Netlify already gzip all static assets for you. 66 | // Before setting to `true`, make sure to: 67 | // npm install --save-dev compression-webpack-plugin 68 | productionGzip: false, 69 | productionGzipExtensions: ['js', 'css'], 70 | 71 | // Run the build command with an extra argument to 72 | // View the bundle analyzer report after build finishes: 73 | // `npm run build --report` 74 | // Set to `true` or `false` to always turn it on or off 75 | bundleAnalyzerReport: process.env.npm_config_report 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /config/test.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const devEnv = require('./dev.env') 4 | 5 | module.exports = merge(devEnv, { 6 | NODE_ENV: '"testing"' 7 | }) 8 | -------------------------------------------------------------------------------- /images/vue-demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanzhsh/vue-demo/fa286f0b2c94898fc7f192d370267dcff9972495/images/vue-demo.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | vue-demo 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lan-vue-demo", 3 | "version": "1.0.0", 4 | "description": "A Vue.js project", 5 | "author": "1451411033@qq.com <1451411033@qq.com>", 6 | "private": true, 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "start": "npm run dev", 10 | "unit": "jest --config test/unit/jest.conf.js --coverage", 11 | "test": "npm run unit", 12 | "build": "node build/build.js" 13 | }, 14 | "dependencies": { 15 | "axios": "^0.18.0", 16 | "blueimp-md5": "^2.10.0", 17 | "cos-js-sdk-v5": "^0.5.5", 18 | "echarts": "^4.1.0", 19 | "element-ui": "^2.4.0", 20 | "jquery": "^1.12.4", 21 | "querystring": "^0.2.0", 22 | "vue": "^2.5.2", 23 | "vue-multiple-check": "^1.0.4", 24 | "vue-router": "^3.0.1", 25 | "vue-split-table": "^1.0.0", 26 | "vue2-editor": "^2.6.6", 27 | "vuedraggable": "^2.16.0", 28 | "vuex": "^3.0.1", 29 | "vuex-persistedstate": "^2.5.4" 30 | }, 31 | "devDependencies": { 32 | "autoprefixer": "^7.1.2", 33 | "babel-core": "^6.22.1", 34 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 35 | "babel-jest": "^21.0.2", 36 | "babel-loader": "^7.1.1", 37 | "babel-plugin-dynamic-import-node": "^1.2.0", 38 | "babel-plugin-syntax-jsx": "^6.18.0", 39 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", 40 | "babel-plugin-transform-runtime": "^6.22.0", 41 | "babel-plugin-transform-vue-jsx": "^3.5.0", 42 | "babel-preset-env": "^1.3.2", 43 | "babel-preset-stage-2": "^6.22.0", 44 | "chalk": "^2.0.1", 45 | "copy-webpack-plugin": "^4.0.1", 46 | "css-loader": "^0.28.0", 47 | "extract-text-webpack-plugin": "^3.0.0", 48 | "file-loader": "^1.1.4", 49 | "friendly-errors-webpack-plugin": "^1.6.1", 50 | "html-webpack-plugin": "^2.30.1", 51 | "jest": "^22.0.4", 52 | "jest-serializer-vue": "^0.3.0", 53 | "node-notifier": "^5.1.2", 54 | "node-sass": "^4.9.0", 55 | "optimize-css-assets-webpack-plugin": "^3.2.0", 56 | "ora": "^1.2.0", 57 | "portfinder": "^1.0.13", 58 | "postcss-import": "^11.0.0", 59 | "postcss-loader": "^2.0.8", 60 | "postcss-url": "^7.2.1", 61 | "rimraf": "^2.6.0", 62 | "sass-loader": "^7.0.1", 63 | "semver": "^5.3.0", 64 | "shelljs": "^0.7.6", 65 | "uglifyjs-webpack-plugin": "^1.1.1", 66 | "url-loader": "^0.5.8", 67 | "vue-jest": "^1.0.2", 68 | "vue-loader": "^13.3.0", 69 | "vue-style-loader": "^3.0.1", 70 | "vue-template-compiler": "^2.5.2", 71 | "webpack": "^3.6.0", 72 | "webpack-bundle-analyzer": "^2.9.0", 73 | "webpack-dev-server": "^2.9.1", 74 | "webpack-merge": "^4.1.0" 75 | }, 76 | "engines": { 77 | "node": ">= 6.0.0", 78 | "npm": ">= 3.0.0" 79 | }, 80 | "browserslist": [ 81 | "> 1%", 82 | "last 2 versions", 83 | "not ie <= 8" 84 | ] 85 | } 86 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 63 | -------------------------------------------------------------------------------- /src/assets/avactor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanzhsh/vue-demo/fa286f0b2c94898fc7f192d370267dcff9972495/src/assets/avactor.png -------------------------------------------------------------------------------- /src/assets/fonts/demo.css: -------------------------------------------------------------------------------- 1 | /* Logo 字体 */ 2 | @font-face { 3 | font-family: "iconfont logo"; 4 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834'); 5 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'), 6 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'), 7 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'), 8 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg'); 9 | } 10 | 11 | .logo { 12 | font-family: "iconfont logo"; 13 | font-size: 160px; 14 | font-style: normal; 15 | -webkit-font-smoothing: antialiased; 16 | -moz-osx-font-smoothing: grayscale; 17 | } 18 | 19 | /* tabs */ 20 | .nav-tabs { 21 | position: relative; 22 | } 23 | 24 | .nav-tabs .nav-more { 25 | position: absolute; 26 | right: 0; 27 | bottom: 0; 28 | height: 42px; 29 | line-height: 42px; 30 | color: #666; 31 | } 32 | 33 | #tabs { 34 | border-bottom: 1px solid #eee; 35 | } 36 | 37 | #tabs li { 38 | cursor: pointer; 39 | width: 100px; 40 | height: 40px; 41 | line-height: 40px; 42 | text-align: center; 43 | font-size: 16px; 44 | border-bottom: 2px solid transparent; 45 | position: relative; 46 | z-index: 1; 47 | margin-bottom: -1px; 48 | color: #666; 49 | } 50 | 51 | 52 | #tabs .active { 53 | border-bottom-color: #f00; 54 | color: #222; 55 | } 56 | 57 | .tab-container .content { 58 | display: none; 59 | } 60 | 61 | /* 页面布局 */ 62 | .main { 63 | padding: 30px 100px; 64 | width: 960px; 65 | margin: 0 auto; 66 | } 67 | 68 | .main .logo { 69 | color: #333; 70 | text-align: left; 71 | margin-bottom: 30px; 72 | line-height: 1; 73 | height: 110px; 74 | margin-top: -50px; 75 | overflow: hidden; 76 | *zoom: 1; 77 | } 78 | 79 | .main .logo a { 80 | font-size: 160px; 81 | color: #333; 82 | } 83 | 84 | .helps { 85 | margin-top: 40px; 86 | } 87 | 88 | .helps pre { 89 | padding: 20px; 90 | margin: 10px 0; 91 | border: solid 1px #e7e1cd; 92 | background-color: #fffdef; 93 | overflow: auto; 94 | } 95 | 96 | .icon_lists { 97 | width: 100% !important; 98 | overflow: hidden; 99 | *zoom: 1; 100 | } 101 | 102 | .icon_lists li { 103 | width: 100px; 104 | margin-bottom: 10px; 105 | margin-right: 20px; 106 | text-align: center; 107 | list-style: none !important; 108 | cursor: default; 109 | } 110 | 111 | .icon_lists li .code-name { 112 | line-height: 1.2; 113 | } 114 | 115 | .icon_lists .icon { 116 | display: block; 117 | height: 100px; 118 | line-height: 100px; 119 | font-size: 42px; 120 | margin: 10px auto; 121 | color: #333; 122 | -webkit-transition: font-size 0.25s linear, width 0.25s linear; 123 | -moz-transition: font-size 0.25s linear, width 0.25s linear; 124 | transition: font-size 0.25s linear, width 0.25s linear; 125 | } 126 | 127 | .icon_lists .icon:hover { 128 | font-size: 100px; 129 | } 130 | 131 | .icon_lists .svg-icon { 132 | /* 通过设置 font-size 来改变图标大小 */ 133 | width: 1em; 134 | /* 图标和文字相邻时,垂直对齐 */ 135 | vertical-align: -0.15em; 136 | /* 通过设置 color 来改变 SVG 的颜色/fill */ 137 | fill: currentColor; 138 | /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示 139 | normalize.css 中也包含这行 */ 140 | overflow: hidden; 141 | } 142 | 143 | .icon_lists li .name, 144 | .icon_lists li .code-name { 145 | color: #666; 146 | } 147 | 148 | /* markdown 样式 */ 149 | .markdown { 150 | color: #666; 151 | font-size: 14px; 152 | line-height: 1.8; 153 | } 154 | 155 | .highlight { 156 | line-height: 1.5; 157 | } 158 | 159 | .markdown img { 160 | vertical-align: middle; 161 | max-width: 100%; 162 | } 163 | 164 | .markdown h1 { 165 | color: #404040; 166 | font-weight: 500; 167 | line-height: 40px; 168 | margin-bottom: 24px; 169 | } 170 | 171 | .markdown h2, 172 | .markdown h3, 173 | .markdown h4, 174 | .markdown h5, 175 | .markdown h6 { 176 | color: #404040; 177 | margin: 1.6em 0 0.6em 0; 178 | font-weight: 500; 179 | clear: both; 180 | } 181 | 182 | .markdown h1 { 183 | font-size: 28px; 184 | } 185 | 186 | .markdown h2 { 187 | font-size: 22px; 188 | } 189 | 190 | .markdown h3 { 191 | font-size: 16px; 192 | } 193 | 194 | .markdown h4 { 195 | font-size: 14px; 196 | } 197 | 198 | .markdown h5 { 199 | font-size: 12px; 200 | } 201 | 202 | .markdown h6 { 203 | font-size: 12px; 204 | } 205 | 206 | .markdown hr { 207 | height: 1px; 208 | border: 0; 209 | background: #e9e9e9; 210 | margin: 16px 0; 211 | clear: both; 212 | } 213 | 214 | .markdown p { 215 | margin: 1em 0; 216 | } 217 | 218 | .markdown>p, 219 | .markdown>blockquote, 220 | .markdown>.highlight, 221 | .markdown>ol, 222 | .markdown>ul { 223 | width: 80%; 224 | } 225 | 226 | .markdown ul>li { 227 | list-style: circle; 228 | } 229 | 230 | .markdown>ul li, 231 | .markdown blockquote ul>li { 232 | margin-left: 20px; 233 | padding-left: 4px; 234 | } 235 | 236 | .markdown>ul li p, 237 | .markdown>ol li p { 238 | margin: 0.6em 0; 239 | } 240 | 241 | .markdown ol>li { 242 | list-style: decimal; 243 | } 244 | 245 | .markdown>ol li, 246 | .markdown blockquote ol>li { 247 | margin-left: 20px; 248 | padding-left: 4px; 249 | } 250 | 251 | .markdown code { 252 | margin: 0 3px; 253 | padding: 0 5px; 254 | background: #eee; 255 | border-radius: 3px; 256 | } 257 | 258 | .markdown strong, 259 | .markdown b { 260 | font-weight: 600; 261 | } 262 | 263 | .markdown>table { 264 | border-collapse: collapse; 265 | border-spacing: 0px; 266 | empty-cells: show; 267 | border: 1px solid #e9e9e9; 268 | width: 95%; 269 | margin-bottom: 24px; 270 | } 271 | 272 | .markdown>table th { 273 | white-space: nowrap; 274 | color: #333; 275 | font-weight: 600; 276 | } 277 | 278 | .markdown>table th, 279 | .markdown>table td { 280 | border: 1px solid #e9e9e9; 281 | padding: 8px 16px; 282 | text-align: left; 283 | } 284 | 285 | .markdown>table th { 286 | background: #F7F7F7; 287 | } 288 | 289 | .markdown blockquote { 290 | font-size: 90%; 291 | color: #999; 292 | border-left: 4px solid #e9e9e9; 293 | padding-left: 0.8em; 294 | margin: 1em 0; 295 | } 296 | 297 | .markdown blockquote p { 298 | margin: 0; 299 | } 300 | 301 | .markdown .anchor { 302 | opacity: 0; 303 | transition: opacity 0.3s ease; 304 | margin-left: 8px; 305 | } 306 | 307 | .markdown .waiting { 308 | color: #ccc; 309 | } 310 | 311 | .markdown h1:hover .anchor, 312 | .markdown h2:hover .anchor, 313 | .markdown h3:hover .anchor, 314 | .markdown h4:hover .anchor, 315 | .markdown h5:hover .anchor, 316 | .markdown h6:hover .anchor { 317 | opacity: 1; 318 | display: inline-block; 319 | } 320 | 321 | .markdown>br, 322 | .markdown>p>br { 323 | clear: both; 324 | } 325 | 326 | 327 | .hljs { 328 | display: block; 329 | background: white; 330 | padding: 0.5em; 331 | color: #333333; 332 | overflow-x: auto; 333 | } 334 | 335 | .hljs-comment, 336 | .hljs-meta { 337 | color: #969896; 338 | } 339 | 340 | .hljs-string, 341 | .hljs-variable, 342 | .hljs-template-variable, 343 | .hljs-strong, 344 | .hljs-emphasis, 345 | .hljs-quote { 346 | color: #df5000; 347 | } 348 | 349 | .hljs-keyword, 350 | .hljs-selector-tag, 351 | .hljs-type { 352 | color: #a71d5d; 353 | } 354 | 355 | .hljs-literal, 356 | .hljs-symbol, 357 | .hljs-bullet, 358 | .hljs-attribute { 359 | color: #0086b3; 360 | } 361 | 362 | .hljs-section, 363 | .hljs-name { 364 | color: #63a35c; 365 | } 366 | 367 | .hljs-tag { 368 | color: #333333; 369 | } 370 | 371 | .hljs-title, 372 | .hljs-attr, 373 | .hljs-selector-id, 374 | .hljs-selector-class, 375 | .hljs-selector-attr, 376 | .hljs-selector-pseudo { 377 | color: #795da3; 378 | } 379 | 380 | .hljs-addition { 381 | color: #55a532; 382 | background-color: #eaffea; 383 | } 384 | 385 | .hljs-deletion { 386 | color: #bd2c00; 387 | background-color: #ffecec; 388 | } 389 | 390 | .hljs-link { 391 | text-decoration: underline; 392 | } 393 | 394 | /* 代码高亮 */ 395 | /* PrismJS 1.15.0 396 | https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */ 397 | /** 398 | * prism.js default theme for JavaScript, CSS and HTML 399 | * Based on dabblet (http://dabblet.com) 400 | * @author Lea Verou 401 | */ 402 | code[class*="language-"], 403 | pre[class*="language-"] { 404 | color: black; 405 | background: none; 406 | text-shadow: 0 1px white; 407 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 408 | text-align: left; 409 | white-space: pre; 410 | word-spacing: normal; 411 | word-break: normal; 412 | word-wrap: normal; 413 | line-height: 1.5; 414 | 415 | -moz-tab-size: 4; 416 | -o-tab-size: 4; 417 | tab-size: 4; 418 | 419 | -webkit-hyphens: none; 420 | -moz-hyphens: none; 421 | -ms-hyphens: none; 422 | hyphens: none; 423 | } 424 | 425 | pre[class*="language-"]::-moz-selection, 426 | pre[class*="language-"] ::-moz-selection, 427 | code[class*="language-"]::-moz-selection, 428 | code[class*="language-"] ::-moz-selection { 429 | text-shadow: none; 430 | background: #b3d4fc; 431 | } 432 | 433 | pre[class*="language-"]::selection, 434 | pre[class*="language-"] ::selection, 435 | code[class*="language-"]::selection, 436 | code[class*="language-"] ::selection { 437 | text-shadow: none; 438 | background: #b3d4fc; 439 | } 440 | 441 | @media print { 442 | 443 | code[class*="language-"], 444 | pre[class*="language-"] { 445 | text-shadow: none; 446 | } 447 | } 448 | 449 | /* Code blocks */ 450 | pre[class*="language-"] { 451 | padding: 1em; 452 | margin: .5em 0; 453 | overflow: auto; 454 | } 455 | 456 | :not(pre)>code[class*="language-"], 457 | pre[class*="language-"] { 458 | background: #f5f2f0; 459 | } 460 | 461 | /* Inline code */ 462 | :not(pre)>code[class*="language-"] { 463 | padding: .1em; 464 | border-radius: .3em; 465 | white-space: normal; 466 | } 467 | 468 | .token.comment, 469 | .token.prolog, 470 | .token.doctype, 471 | .token.cdata { 472 | color: slategray; 473 | } 474 | 475 | .token.punctuation { 476 | color: #999; 477 | } 478 | 479 | .namespace { 480 | opacity: .7; 481 | } 482 | 483 | .token.property, 484 | .token.tag, 485 | .token.boolean, 486 | .token.number, 487 | .token.constant, 488 | .token.symbol, 489 | .token.deleted { 490 | color: #905; 491 | } 492 | 493 | .token.selector, 494 | .token.attr-name, 495 | .token.string, 496 | .token.char, 497 | .token.builtin, 498 | .token.inserted { 499 | color: #690; 500 | } 501 | 502 | .token.operator, 503 | .token.entity, 504 | .token.url, 505 | .language-css .token.string, 506 | .style .token.string { 507 | color: #9a6e3a; 508 | background: hsla(0, 0%, 100%, .5); 509 | } 510 | 511 | .token.atrule, 512 | .token.attr-value, 513 | .token.keyword { 514 | color: #07a; 515 | } 516 | 517 | .token.function, 518 | .token.class-name { 519 | color: #DD4A68; 520 | } 521 | 522 | .token.regex, 523 | .token.important, 524 | .token.variable { 525 | color: #e90; 526 | } 527 | 528 | .token.important, 529 | .token.bold { 530 | font-weight: bold; 531 | } 532 | 533 | .token.italic { 534 | font-style: italic; 535 | } 536 | 537 | .token.entity { 538 | cursor: help; 539 | } 540 | -------------------------------------------------------------------------------- /src/assets/fonts/demo_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IconFont Demo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |

19 | 27 |
28 |
29 |
    30 | 31 |
  • 32 | 33 |
    输入
    34 |
    &#xe698;
    35 |
  • 36 | 37 |
  • 38 | 39 |
    图片
    40 |
    &#xe7ed;
    41 |
  • 42 | 43 |
  • 44 | 45 |
    三竖线
    46 |
    &#xe6ba;
    47 |
  • 48 | 49 |
  • 50 | 51 |
    数据
    52 |
    &#xe693;
    53 |
  • 54 | 55 |
  • 56 | 57 |
    表格
    58 |
    &#xe60a;
    59 |
  • 60 | 61 |
  • 62 | 63 |
    三横线
    64 |
    &#xe601;
    65 |
  • 66 | 67 |
  • 68 | 69 |
    全屏
    70 |
    &#xe669;
    71 |
  • 72 | 73 |
  • 74 | 75 |
    富文本
    76 |
    &#xe600;
    77 |
  • 78 | 79 |
80 |
81 |

Unicode 引用

82 |
83 | 84 |

Unicode 是字体在网页端最原始的应用方式,特点是:

85 |
    86 |
  • 兼容性最好,支持 IE6+,及所有现代浏览器。
  • 87 |
  • 支持按字体的方式去动态调整图标大小,颜色等等。
  • 88 |
  • 但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。
  • 89 |
90 |
91 |

注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用,如果有需求建议使用symbol 的引用方式

92 |
93 |

Unicode 使用步骤如下:

94 |

第一步:拷贝项目下面生成的 @font-face

95 |
@font-face {
 97 |   font-family: 'iconfont';
 98 |   src: url('iconfont.eot');
 99 |   src: url('iconfont.eot?#iefix') format('embedded-opentype'),
100 |       url('iconfont.woff2') format('woff2'),
101 |       url('iconfont.woff') format('woff'),
102 |       url('iconfont.ttf') format('truetype'),
103 |       url('iconfont.svg#iconfont') format('svg');
104 | }
105 | 
106 |

第二步:定义使用 iconfont 的样式

107 |
.iconfont {
109 |   font-family: "iconfont" !important;
110 |   font-size: 16px;
111 |   font-style: normal;
112 |   -webkit-font-smoothing: antialiased;
113 |   -moz-osx-font-smoothing: grayscale;
114 | }
115 | 
116 |

第三步:挑选相应图标并获取字体编码,应用于页面

117 |
118 | <span class="iconfont">&#x33;</span>
120 | 
121 |
122 |

"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

123 |
124 |
125 |
126 |
127 |
    128 | 129 |
  • 130 | 131 |
    132 | 输入 133 |
    134 |
    .icon-icon 135 |
    136 |
  • 137 | 138 |
  • 139 | 140 |
    141 | 图片 142 |
    143 |
    .icon-tupian 144 |
    145 |
  • 146 | 147 |
  • 148 | 149 |
    150 | 三竖线 151 |
    152 |
    .icon-sanhengxian 153 |
    154 |
  • 155 | 156 |
  • 157 | 158 |
    159 | 数据 160 |
    161 |
    .icon-shuju 162 |
    163 |
  • 164 | 165 |
  • 166 | 167 |
    168 | 表格 169 |
    170 |
    .icon-biaoge 171 |
    172 |
  • 173 | 174 |
  • 175 | 176 |
    177 | 三横线 178 |
    179 |
    .icon-sidebar-toggle 180 |
    181 |
  • 182 | 183 |
  • 184 | 185 |
    186 | 全屏 187 |
    188 |
    .icon-quanping 189 |
    190 |
  • 191 | 192 |
  • 193 | 194 |
    195 | 富文本 196 |
    197 |
    .icon-fuwenben 198 |
    199 |
  • 200 | 201 |
202 |
203 |

font-class 引用

204 |
205 | 206 |

font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。

207 |

与 Unicode 使用方式相比,具有如下特点:

208 |
    209 |
  • 兼容性良好,支持 IE8+,及所有现代浏览器。
  • 210 |
  • 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
  • 211 |
  • 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
  • 212 |
  • 不过因为本质上还是使用的字体,所以多色图标还是不支持的。
  • 213 |
214 |

使用步骤如下:

215 |

第一步:引入项目下面生成的 fontclass 代码:

216 |
<link rel="stylesheet" href="./iconfont.css">
217 | 
218 |

第二步:挑选相应图标并获取类名,应用于页面:

219 |
<span class="iconfont icon--xxx"></span>
220 | 
221 |
222 |

" 223 | iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

224 |
225 |
226 |
227 |
228 |
    229 | 230 |
  • 231 | 234 |
    输入
    235 |
    #icon-icon
    236 |
  • 237 | 238 |
  • 239 | 242 |
    图片
    243 |
    #icon-tupian
    244 |
  • 245 | 246 |
  • 247 | 250 |
    三竖线
    251 |
    #icon-sanhengxian
    252 |
  • 253 | 254 |
  • 255 | 258 |
    数据
    259 |
    #icon-shuju
    260 |
  • 261 | 262 |
  • 263 | 266 |
    表格
    267 |
    #icon-biaoge
    268 |
  • 269 | 270 |
  • 271 | 274 |
    三横线
    275 |
    #icon-sidebar-toggle
    276 |
  • 277 | 278 |
  • 279 | 282 |
    全屏
    283 |
    #icon-quanping
    284 |
  • 285 | 286 |
  • 287 | 290 |
    富文本
    291 |
    #icon-fuwenben
    292 |
  • 293 | 294 |
295 |
296 |

Symbol 引用

297 |
298 | 299 |

这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章 300 | 这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:

301 |
    302 |
  • 支持多色图标了,不再受单色限制。
  • 303 |
  • 通过一些技巧,支持像字体那样,通过 font-size, color 来调整样式。
  • 304 |
  • 兼容性较差,支持 IE9+,及现代浏览器。
  • 305 |
  • 浏览器渲染 SVG 的性能一般,还不如 png。
  • 306 |
307 |

使用步骤如下:

308 |

第一步:引入项目下面生成的 symbol 代码:

309 |
<script src="./iconfont.js"></script>
310 | 
311 |

第二步:加入通用 CSS 代码(引入一次就行):

312 |
<style>
313 | .icon {
314 |   width: 1em;
315 |   height: 1em;
316 |   vertical-align: -0.15em;
317 |   fill: currentColor;
318 |   overflow: hidden;
319 | }
320 | </style>
321 | 
322 |

第三步:挑选相应图标并获取类名,应用于页面:

323 |
<svg class="icon" aria-hidden="true">
324 |   <use xlink:href="#icon-xxx"></use>
325 | </svg>
326 | 
327 |
328 |
329 | 330 |
331 |
332 | 351 | 352 | 353 | -------------------------------------------------------------------------------- /src/assets/fonts/iconfont.css: -------------------------------------------------------------------------------- 1 | @font-face {font-family: "iconfont"; 2 | src: url('iconfont.eot?t=1546584768167'); /* IE9 */ 3 | src: url('iconfont.eot?t=1546584768167#iefix') format('embedded-opentype'), /* IE6-IE8 */ 4 | url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAd8AAsAAAAADdAAAAcwAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCEAgqNUIpqATYCJAMkCxQABCAFhG0HfRuLC1GUUFIE2VfYlOFeJACoCMkCE1FHxiXL1gl7BlTxm7DhATcAAILnqT/rz31VjxVUOgN6BSjpEZjukf1lLzY/8+XZTwruJkuka6dfCyqYoErfdLq4fYCHm3SDbpKv+/t/w/8v1OII1uwANOEgtZp3Utca8AQ8gsvMaMPkFfBRN5Wu3zVpUYlsmOwc4/8DZZX6/9+r+n7O+ZYJNm8GByUYwDlXWwx1UblAPT0+5gbbIC1YhbUG0m2XODzMuhgCRFQiB6Jz19ZeYEJDtYKmGVMlFphsNnQITQiMns+B2shOXAJnk/MmsEP9ffmDZhKAg6ugl+o/qU4AlT+DX/5Sa/KLGaFy5PLzAJfDQAENAGiQ3b6+rShd00DVRX6VmjEALPurWvhZfo5+nvrztve735/88C0PfsY1GcKCJeSfPECAh4uPRlA4IB5UFzvgc/IB/IyQmXqBBQ/6CBZc6KfCgg/9HljQ0B+EljT6x/CgmAdy9OAAEKKzAEATgNMI9t1QYmcyPi5KxsyumiAeLxVQQR+VjqsRCzVE2aDA6uIaxQtV6KrVrPVC84fZLC0WDwwDoXYOGCC+dpbbayQObylf6XqfiK+Olw8WHZov4cQ2yz2F4oHx9eTh+zaqf178bpnCsc0PiEAmYh5uPm8eljLetOP1uEPmv25J9bs8cT6Z0R8tS969MBaRb2/OgPt3a/fvGfCeaY8iQUjnV6t6IncGDDpAVKfjieMG90/nb/G1xP08pLqrN9RN4eNnS3/6iQ+SH71V2smpOfWbfeXrT/9l7sdzvaXW5Gij4bx4oGcUhEcGmUBZzmIJo5gG03OmGd2o0ox9+zoG+akKnqSMP+KniiPGrVPhWi5C6S1ij8OCzeGml/LXDBEFAbKwEDmmBpw05oviDgREZkNSWMYosXy+QclAjVgqpmTwFlPe7atRu2mzJKV4RKiKZgwozIruzdDlCA0LqIQxaWWFx5MQxw5lieWJ17jF0AWwP0Z283wNIy7xMCnDFao9hB4GDp0d3gF/dT+sUei9rxVRNsP3CBAB8+y9EtZhY7R8NGX8jog6S2SeGGZsHIlgjEmSQDPdPMHUAmN6JthoN7QLTAVWIm0sh/UC5KcRzwaRlQJTMe77NjOE/fWKkmkL3A3DG29in9k+vZsbcwfeJqUckcDbzF6vsG0g3f231017oqycZf9ywbqLX4bq5hS/PlG85Mly4V68zdGBzS+MXSianJU/LpH7Dlfr9rFed6FkPrMpPZ6iH7TBy0xORpt29n6tqLc0qd5qzQaI/d5k5p3mb0JDK3RZ+Ohr85Unm1V/Wj5nw5O59zUfbjzd/MfgcIUh5jbkpYWVJ5O/n5zcmbq76n3yHFfJ95M3y9VcYsMyW75d/nJL1FumEvRmEhIzPZXEf9JqiQmZ3kWfO2miRXSAp5+rKupQYQkI1U9AUe9r4lvF+idLXQ+/GiFGXA1Xw8/C9+QtDZVvdz6p8Vyt+K2CzsVvU/0ntupIovKNiGuxxBDT1Vpxi6O/TXPr1yWfy2V/o/Z0245VWna+eXPlDfjxyltuORBnmt9cZhlm/4/74zQNY5eK/QvPV6A4BJjTu7yvSl+MfJYnzxfUtr3+5x+zGmpgtZhki5f/hGQJKhWEOdGULEfVDGLTxdtfp52t86IwAwI30eRlFOnDs/7inb9Tr4uV7GpeDqyaDP0+daIG1dzO81rP9x5nm01NlrtZQOLb4OxWsn+Jb1tQ5WwDqSKc6JuM+AqHE/Yf8W0NqlzIOLKIC7fcp3gB/q75fe8JdtrURBmqKUn4aOPW5AmfbLZ1fNXf+KpJE9oEm5tur2HV1e0bO35V85WwbByw3+z5B/K0mf/gyOEbrF4DkH+We6ojIP8CerotAPCyOM8fTrdGT1Y5yD9Ur6ruAFCHnVfI5i/yQLX9f9Oo1f/1jXhUqb1tgmr9z2R+/8lPs9XPq7J4snwcBPuyRt6yf7ZFTwpBVG8ltYf6OUGMm2T3kf8/BSukGJNxgIhNg390qIDn+epLliqTAwElTXDwqQiKgBqYxhuAi6EFeAS0g4j6NBxuSIPQIjoE6rGCgGA5Ag4JnhEjYLkGTOPPwKUU38DDioKIQkmf0FBLpkad5kEWQ4HmZmmFVz0id2KL1twNJb+LRValSu+HyKck6cJGTZzFBuiBKI9dfFNSEcYiLSLVTdeTy0GXS6W9SHVAHufJGHvt+Y0n+e2ax6tuYKETCAgLlvkFaDhmBRV4VDyIC2Msrp/vBiLhxwULCpnyJdgPBOFDWTpNIXkUxMAadJ5YU9al08cUEkXgg0eEFhmEils31B89EBfLqdB4/ddzAOHB5CGnyHixk38YJ8bV5ZVvcE/rRUAEPVsojijR4oonvgQSSoQegXbDgoVehfVY54uMDD3SjPmi+vlT/A6/YdxUVpUgOX+qADkW5WJVklzQNHch6/EqHsk0aeE09HDcCgA=') format('woff2'), 5 | url('iconfont.woff?t=1546584768167') format('woff'), 6 | url('iconfont.ttf?t=1546584768167') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ 7 | url('iconfont.svg?t=1546584768167#iconfont') format('svg'); /* iOS 4.1- */ 8 | } 9 | 10 | .iconfont { 11 | font-family: "iconfont" !important; 12 | font-size: 16px; 13 | font-style: normal; 14 | -webkit-font-smoothing: antialiased; 15 | -moz-osx-font-smoothing: grayscale; 16 | } 17 | 18 | .icon-icon:before { 19 | content: "\e698"; 20 | } 21 | 22 | .icon-tupian:before { 23 | content: "\e7ed"; 24 | } 25 | 26 | .icon-sanhengxian:before { 27 | content: "\e6ba"; 28 | } 29 | 30 | .icon-shuju:before { 31 | content: "\e693"; 32 | } 33 | 34 | .icon-biaoge:before { 35 | content: "\e60a"; 36 | } 37 | 38 | .icon-sidebar-toggle:before { 39 | content: "\e601"; 40 | } 41 | 42 | .icon-quanping:before { 43 | content: "\e669"; 44 | } 45 | 46 | .icon-fuwenben:before { 47 | content: "\e600"; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /src/assets/fonts/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanzhsh/vue-demo/fa286f0b2c94898fc7f192d370267dcff9972495/src/assets/fonts/iconfont.eot -------------------------------------------------------------------------------- /src/assets/fonts/iconfont.js: -------------------------------------------------------------------------------- 1 | !function(i){var t,h='',c=(t=document.getElementsByTagName("script"))[t.length-1].getAttribute("data-injectcss");if(c&&!i.__iconfont__svg__cssinject__){i.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(t){console&&console.log(t)}}!function(t){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(t,0);else{var c=function(){document.removeEventListener("DOMContentLoaded",c,!1),t()};document.addEventListener("DOMContentLoaded",c,!1)}else document.attachEvent&&(e=t,l=i.document,n=!1,o=function(){n||(n=!0,e())},(h=function(){try{l.documentElement.doScroll("left")}catch(t){return void setTimeout(h,50)}o()})(),l.onreadystatechange=function(){"complete"==l.readyState&&(l.onreadystatechange=null,o())});var e,l,n,o,h}(function(){var t,c,e,l,n,o;(t=document.createElement("div")).innerHTML=h,h=null,(c=t.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",e=c,(l=document.body).firstChild?(n=e,(o=l.firstChild).parentNode.insertBefore(n,o)):l.appendChild(e))})}(window); -------------------------------------------------------------------------------- /src/assets/fonts/iconfont.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Created by iconfont 9 | 10 | 11 | 12 | 13 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/assets/fonts/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanzhsh/vue-demo/fa286f0b2c94898fc7f192d370267dcff9972495/src/assets/fonts/iconfont.ttf -------------------------------------------------------------------------------- /src/assets/fonts/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanzhsh/vue-demo/fa286f0b2c94898fc7f192d370267dcff9972495/src/assets/fonts/iconfont.woff -------------------------------------------------------------------------------- /src/assets/fonts/iconfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanzhsh/vue-demo/fa286f0b2c94898fc7f192d370267dcff9972495/src/assets/fonts/iconfont.woff2 -------------------------------------------------------------------------------- /src/assets/login.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanzhsh/vue-demo/fa286f0b2c94898fc7f192d370267dcff9972495/src/assets/login.jpg -------------------------------------------------------------------------------- /src/assets/login_pass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanzhsh/vue-demo/fa286f0b2c94898fc7f192d370267dcff9972495/src/assets/login_pass.png -------------------------------------------------------------------------------- /src/assets/login_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanzhsh/vue-demo/fa286f0b2c94898fc7f192d370267dcff9972495/src/assets/login_user.png -------------------------------------------------------------------------------- /src/assets/right-arrow-sel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanzhsh/vue-demo/fa286f0b2c94898fc7f192d370267dcff9972495/src/assets/right-arrow-sel.png -------------------------------------------------------------------------------- /src/assets/right-arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanzhsh/vue-demo/fa286f0b2c94898fc7f192d370267dcff9972495/src/assets/right-arrow.png -------------------------------------------------------------------------------- /src/components/addTable.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 64 | 65 | -------------------------------------------------------------------------------- /src/components/crop.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 373 | 374 | 525 | -------------------------------------------------------------------------------- /src/components/multiCheckCom.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 239 | 240 | -------------------------------------------------------------------------------- /src/components/selectBox.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 243 | 244 | -------------------------------------------------------------------------------- /src/components/tabs.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import App from './App' 5 | import ElementUI from 'element-ui'; 6 | import 'element-ui/lib/theme-chalk/index.css'; 7 | import router from './router'; 8 | import echarts from 'echarts'; 9 | import axios from 'axios'; 10 | import store from './store'; 11 | import QS from 'querystring'; 12 | import api from '@/utils/api'; 13 | import request from '@/utils/request'; 14 | 15 | Vue.use(ElementUI); 16 | 17 | Vue.prototype.$echarts = echarts; 18 | Vue.prototype.$QS = QS; 19 | Vue.prototype.$api = api; 20 | Vue.prototype.$request = request; 21 | //设置axios拦截器 22 | axios.interceptors.request.use(config => { 23 | config.headers.token = window.sessionStorage.token //jsCookie.get('cityCode') 24 | return config 25 | }); 26 | axios.interceptors.response.use((response) => { 27 | //处理data 28 | return response; 29 | }, 30 | error=>{ 31 | { // 这里是返回状态码不为200时候的错误处理 32 | if (err && err.response) { 33 | switch (err.response.status) { 34 | case 400: 35 | err.message = '请求错误' 36 | break 37 | 38 | case 401: 39 | err.message = '未授权,请登录' 40 | break 41 | 42 | case 403: 43 | err.message = '拒绝访问' 44 | break 45 | 46 | case 404: 47 | err.message = `请求地址出错: ${err.response.config.url}` 48 | break 49 | 50 | case 408: 51 | err.message = '请求超时' 52 | break 53 | 54 | case 500: 55 | err.message = '服务器内部错误' 56 | break 57 | 58 | case 501: 59 | err.message = '服务未实现' 60 | break 61 | 62 | case 502: 63 | err.message = '网关错误' 64 | break 65 | 66 | case 503: 67 | err.message = '服务不可用' 68 | break 69 | 70 | case 504: 71 | err.message = '网关超时' 72 | break 73 | 74 | case 505: 75 | err.message = 'HTTP版本不受支持' 76 | break 77 | 78 | default: 79 | } 80 | } 81 | 82 | return Promise.reject(err); 83 | } 84 | }); 85 | 86 | //导航钩子守卫 87 | router.beforeEach((to, from, next) => { 88 | let token = sessionStorage.getItem('userName'); 89 | let path = to.path 90 | if (path === '/login') { 91 | next() 92 | return 93 | } 94 | if (token) { 95 | next(); 96 | } else { 97 | // next({ 98 | // path: '/login' 99 | // }) 100 | next(); 101 | } 102 | }) 103 | 104 | Vue.config.productionTip = false 105 | 106 | /* eslint-disable no-new */ 107 | new Vue({ 108 | el: '#app', 109 | router, 110 | store, 111 | components: { App }, 112 | template: '' 113 | }) 114 | -------------------------------------------------------------------------------- /src/page/Home.vue: -------------------------------------------------------------------------------- 1 | 52 | 53 | 147 | 148 | -------------------------------------------------------------------------------- /src/page/Login.vue: -------------------------------------------------------------------------------- 1 | 50 | 51 | 127 | 128 | 188 | -------------------------------------------------------------------------------- /src/page/dataVisual/ComEcharts.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 22 | 23 | 24 | 57 | -------------------------------------------------------------------------------- /src/page/dataVisual/Map.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 23 | 24 | 59 | -------------------------------------------------------------------------------- /src/page/dataVisual/SpeEcharts.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 20 | 21 | 22 | 748 | -------------------------------------------------------------------------------- /src/page/fileImg/FileCloud.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 59 | 60 | -------------------------------------------------------------------------------- /src/page/fileImg/UploadFile.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 48 | 49 | -------------------------------------------------------------------------------- /src/page/fileImg/UploadImg.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 47 | 48 | -------------------------------------------------------------------------------- /src/page/richText/CustomEditor.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 53 | 54 | -------------------------------------------------------------------------------- /src/page/richText/TextEditor.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 29 | 30 | -------------------------------------------------------------------------------- /src/page/tableClassify/ComTable.vue: -------------------------------------------------------------------------------- 1 | 49 | 50 | 59 | 60 | 61 | 182 | -------------------------------------------------------------------------------- /src/page/tableClassify/Drag.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 75 | 76 | -------------------------------------------------------------------------------- /src/page/tableClassify/MergeTable.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /src/page/tableClassify/MultiCheck.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 67 | 68 | -------------------------------------------------------------------------------- /src/page/tableClassify/SpeTable.vue: -------------------------------------------------------------------------------- 1 | 91 | 92 | 101 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | //路由懒加载 4 | const Login=()=>import('@/page/Login') 5 | const Home=()=>import('@/page/Home') 6 | 7 | //数据可视化 8 | const Map=()=>import('@/page/dataVisual/Map') 9 | const ComEcharts=()=>import('@/page/dataVisual/ComEcharts') 10 | const SpeEcharts=()=>import('@/page/dataVisual/SpeEcharts') 11 | 12 | //表格分类 13 | const ComTable=()=>import('@/page/tableClassify/ComTable') 14 | const SpeTable=()=>import('@/page/tableClassify/SpeTable') 15 | const MergeTable=()=>import('@/page/tableClassify/MergeTable') 16 | const Drag=()=>import('@/page/tableClassify/Drag') 17 | const MultiCheck=()=>import('@/page/tableClassify/MultiCheck') 18 | 19 | //富文本 20 | const TextEditor=()=>import('@/page/richText/TextEditor') 21 | const CustomEditor=()=>import('@/page/richText/CustomEditor') 22 | 23 | //文件和图片上传 24 | const FileCloud=()=>import('@/page/fileImg/FileCloud') 25 | const UploadFile=()=>import('@/page/fileImg/UploadFile') 26 | const UploadImg=()=>import('@/page/fileImg/UploadImg') 27 | 28 | Vue.use(Router) 29 | 30 | export default new Router({ 31 | mode: 'history', 32 | routes: [ 33 | { 34 | path: '/', 35 | name: 'home', 36 | component: Home, 37 | children:[ 38 | //数据可视化 39 | {path:'/map',name:'map',component:Map}, 40 | {path:'/comEcharts',name:'comEcharts',component:ComEcharts}, 41 | {path:'/speEcharts',name:'speEcharts',component:SpeEcharts}, 42 | 43 | //表格 44 | {path:'/comTable',name:'comTable',component:ComTable}, 45 | {path:'/speTable',name:'speTable',component:SpeTable}, 46 | {path:'/mergeTable',name:'mergeTable',component:MergeTable}, 47 | {path:'/drag',name:'drag',component:Drag}, 48 | {path:'/multiCheck',name:'multiCheck',component:MultiCheck}, 49 | 50 | //文本 51 | {path:'/textEditor',name:'textEditor',component:TextEditor}, 52 | {path:'/customEditor',name:'customEditor',component:CustomEditor}, 53 | 54 | //文件 55 | {path:'/fileCloud',name:'fileCloud',component:FileCloud}, 56 | {path:'/uploadFile',name:'uploadFile',component:UploadFile}, 57 | {path:'/uploadImg',name:'uploadImg',component:UploadImg}, 58 | ] 59 | }, 60 | { 61 | path:'/login',name:'login',component:Login 62 | }, 63 | ] 64 | }) 65 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import createPersistedState from 'vuex-persistedstate' 4 | import comTable from './modules/comTable' 5 | Vue.use(Vuex) 6 | 7 | export default new Vuex.Store({ 8 | modules: { 9 | comTable 10 | }, 11 | plugins: [createPersistedState({ storage: window.sessionStorage })] 12 | }) 13 | -------------------------------------------------------------------------------- /src/store/modules/comTable.js: -------------------------------------------------------------------------------- 1 | import api from '@/utils/api'; 2 | import request from '@/utils/request'; 3 | 4 | // initial state 5 | const state = { 6 | tableData: [], 7 | } 8 | 9 | // getters 10 | const getters = { 11 | allTableData: state => state.tableData, 12 | } 13 | 14 | // actions 15 | const actions = { 16 | getAllData ({ commit }) { 17 | request({ 18 | url:api.tableData, 19 | method:"GET", 20 | params:{}, 21 | }).then(res=>{ 22 | console.log('res值为',res); 23 | //这里特别坑爹,axios读取本地的json转化为字符串了,所以要通过eval转化为对象 24 | commit('setTableData', eval('('+res.data+')').tabData); 25 | }) 26 | } 27 | } 28 | 29 | // mutations 30 | const mutations = { 31 | setTableData (state,tableData) { 32 | state.tableData = tableData 33 | } 34 | } 35 | 36 | export default { 37 | state, 38 | getters, 39 | actions, 40 | mutations 41 | } -------------------------------------------------------------------------------- /src/utils/api.js: -------------------------------------------------------------------------------- 1 | const API={ 2 | login:"/api/loginOut", 3 | tableData:"/static/comTable.json", 4 | } 5 | 6 | 7 | export default API; 8 | -------------------------------------------------------------------------------- /src/utils/check.js: -------------------------------------------------------------------------------- 1 | const dateToFormat = (date) =>{ 2 | date.toLocaleString("en-US", { 3 | hour12: false 4 | }).replace(/\b\d\b/g, '0$&').replace(new RegExp('/', 'gm'), '-') 5 | }; 6 | const forMatToDate = (date) =>{ 7 | let dateArr = date.split(':'); 8 | return new Date(2017, 10, 19, dateArr[0], dateArr[1], dateArr[2]) 9 | }; 10 | const obtainNowDate =()=>{ 11 | let date = new Date(); 12 | let year = date.getFullYear(); 13 | let month = date.getMonth() + 1; 14 | let day = date.getDate(); 15 | let hours = date.getHours(); 16 | let minu = date.getMinutes(); 17 | let second = date.getSeconds(); 18 | let arr = [month, day, hours, minu, second]; 19 | arr.forEach(item =>{ 20 | item < 10?"0"+ item : item 21 | }) 22 | return year + '-' + arr[0] + '-' + arr[1] + ' ' + arr[2] + ':' + arr[3] + ':' + arr[4] 23 | }; 24 | const returnTimestamp = (strTime) => { 25 | let middleDate = new Date(Number(strTime)); 26 | return middleDate.toLocaleString('zh-CN', { 27 | hour12: false 28 | }).replace(/\b\d\b/g, '0$&').replace(new RegExp('/', 'gm'), '-') 29 | }; 30 | const compareOneLessTwo = (dateOne, dateTwo) =>{ 31 | return Number(dateOne.replace(/\-/g, "")) < Number(dateTwo.replace(/\-/g, "")) 32 | }; 33 | const judgeArr = (arr) =>{ 34 | if (Array.isArray(arr)) { 35 | return true 36 | } 37 | }; 38 | const removeRepeatArr = (arr) =>{ 39 | return Array.from(new Set(arr)) 40 | }; 41 | const orderAscendArr = (arr) =>{ 42 | arr.sort((a, b) =>{ 43 | return a - b 44 | }) 45 | }; 46 | const allArrSatisfact = (arr, compare, value) =>{ 47 | return arr.every((arr) =>{ 48 | return arr + compare + value 49 | }) 50 | }; 51 | const judgeNum = (num) =>{ 52 | if (typeof num1 == 'number') { 53 | return true 54 | } else { 55 | return false 56 | } 57 | }; 58 | const judgeNumOrLetter = (data) =>{ 59 | let reg = /^[0-9a-zA-Z]*$/g; 60 | if (reg.test(data)) { 61 | return true 62 | } 63 | }; 64 | const trimLeftOrRight = (str) =>{   65 | return str.replace(/(^s)|(s$)/g, "") 66 | }; 67 | const isObjectEqual=(oneData, twoData) =>{ 68 | let twoFlag=JSON.stringify(oneData)===JSON.stringify(twoData); 69 | if(twoFlag){ 70 | return true; 71 | }else{ 72 | return false; 73 | } 74 | } 75 | 76 | export{ 77 | dateToFormat, 78 | forMatToDate, 79 | obtainNowDate, 80 | returnTimestamp, 81 | compareOneLessTwo, 82 | judgeArr, 83 | removeRepeatArr, 84 | orderAscendArr, 85 | allArrSatisfact, 86 | judgeNum, 87 | judgeNumOrLetter, 88 | trimLeftOrRight, 89 | isObjectEqual 90 | } -------------------------------------------------------------------------------- /src/utils/config/cloud.js: -------------------------------------------------------------------------------- 1 | let TenBUCKET,TenUrl; 2 | 3 | if(location.hostname.indexOf('dev-')!=-1 4 | ||location.hostname.indexOf('test-')!=-1){ 5 | TenBUCKET='resource-125578';//配置腾讯云的Bucket 6 | TenUrl='https://resource.com';//配置腾讯云的路径 7 | }else if(location.hostname=== "prod.com"){ 8 | TenBUCKET='prod-1255821078'; 9 | TenUrl='https://cos.com'; 10 | }else{ 11 | TenBUCKET='resource-125578'; 12 | TenUrl='https://resource.com'; 13 | } 14 | 15 | export{ 16 | TenBUCKET,TenUrl 17 | } -------------------------------------------------------------------------------- /src/utils/config/index.js: -------------------------------------------------------------------------------- 1 | let API_ROOT = '',host=location.host 2 | switch(host){ 3 | case 'pre.my.com': 4 | API_ROOT='pre' 5 | break 6 | case 'test.my.com': 7 | API_ROOT='test' 8 | break 9 | case 'checkout.my.com': 10 | API_ROOT='checkout' 11 | break 12 | case 'business.my.com': 13 | API_ROOT='prod' 14 | break 15 | default: 16 | API_ROOT='http://localhost:5220' 17 | break 18 | } 19 | export { 20 | API_ROOT 21 | } 22 | 23 | export default API_ROOT -------------------------------------------------------------------------------- /src/utils/fileUpdate.js: -------------------------------------------------------------------------------- 1 | import { Message } from 'element-ui'; 2 | import {TenBUCKET,TenUrl} from './config/cloud'; 3 | import $ from 'jquery'; 4 | import COS from 'cos-js-sdk-v5'; 5 | import md5 from 'blueimp-md5'; 6 | import request from '@/utils/request'; 7 | var validate = function (file, type_v) { 8 | 9 | if (!type_v) 10 | var testmsg = file.name.substring(file.name.lastIndexOf('.') + 1) 11 | else 12 | var testmsg = file.type.substring(file.type.lastIndexOf('/') + 1) 13 | const extension = testmsg.toLowerCase() === 'png'; 14 | const extension2 = testmsg.toLowerCase() === 'jpg'; 15 | const extension3 = testmsg.toLowerCase() === 'jpeg'; 16 | const extension4 = testmsg.toLowerCase() === 'gif'; 17 | const isLt2M = file.size / 1024 / 1024 < 2; 18 | if (!extension && !extension2 && !extension3 && !extension4) { 19 | Message({ 20 | message: '上传文件只能是 png、jpg、jpeg、gif格式!', 21 | type: 'warning' 22 | }); 23 | } 24 | if (!isLt2M) { 25 | Message({ 26 | message: '上传文件大小不能超过 2MB!', 27 | type: 'warning' 28 | }); 29 | return false; 30 | } 31 | return extension || extension2 || extension3 || extension4 && isLt2M 32 | } 33 | 34 | var readFile = function (files) { 35 | //读取图片数据 36 | var f = files[0], isRight = true; 37 | var reader = new FileReader(); 38 | reader.onload = function (e) { 39 | var data = e.target.result; 40 | //加载图片获取图片真实宽度和高度 41 | var image = new Image(); 42 | image.onload = function () { 43 | var width = image.width; 44 | var height = image.height; 45 | if (height > 9999 || width > 9999) { 46 | isRight = false; 47 | } 48 | }; 49 | image.src = data; 50 | }; 51 | reader.readAsDataURL(f); 52 | return isRight; 53 | 54 | } 55 | 56 | // folder = 'cover/'; 57 | var addZero = function (val) { 58 | if (val <= 9) { 59 | return '0' + val; 60 | } else { 61 | return val; 62 | } 63 | } 64 | 65 | //配置腾讯云上传url 66 | let URL = 'https://download.aijiatui.com', 67 | Bucket=TenBUCKET, 68 | lecturerId=sessionStorage.getItem('lecturerId'), 69 | Region = 'ap-guangzhou'; 70 | /** 71 | * 文件上传 72 | * @param files 获取到的文件列表 73 | * @param callback 74 | * @param type 1视频 2图片 75 | */ 76 | let client 77 | var fileUpdate = function (folder, files, callback, progress, id, isreload) { 78 | // console.log(files); 79 | //folder将上lecturer 80 | folder=`${lecturerId}/${folder}` 81 | // var extension = validate(files[0]); 82 | 83 | // if (!extension) { 84 | // callback && callback(); 85 | // return; 86 | // }; 87 | 88 | // if (!readFile(files)) { 89 | // Message({ 90 | // message: '图片宽高均不超过9999Px,宽高比不超过1:25!', 91 | // type: 'warning' 92 | // }); 93 | // callback && callback(); 94 | // return; 95 | // }; 96 | var cos = new COS({ 97 | getAuthorization: function (options, callback) { 98 | // 异步获取签名 99 | $.get(URL + '/api/Auth/signature', { 100 | method: (options.Method || 'get').toLowerCase(), 101 | pathname: '/' + (options.Key || '') 102 | }, function (authorization) { 103 | var obj = JSON.parse(authorization); 104 | callback(obj.signature); 105 | }, 'text'); 106 | 107 | // request({ 108 | // url:`${URL}/api/Auth/signature`, 109 | // method:(options.Method || 'get').toLowerCase(), 110 | // }).then(authorization=>{ 111 | // var obj = JSON.parse(authorization); 112 | // callback(obj.signature); 113 | // }) 114 | } 115 | }) 116 | var testmsg = files[0].name.substring(files[0].name.lastIndexOf('.') + 1) 117 | 118 | var date = new Date(); 119 | var name = parseInt(Math.random() * 1000000) + '' + date.getFullYear() + addZero(date.getMonth() + 1) + addZero(date.getDate()) + date.getTime() + files[0].name; 120 | // folder = 'cover/'; 121 | console.log(files); 122 | console.log('folder + name值为',folder + name); 123 | name = md5(name) + '.' + testmsg; 124 | // 分片上传文件 125 | cos.sliceUploadFile({ 126 | Bucket: Bucket, 127 | Region: Region, 128 | Key: `folder + name`, 129 | Body: files[0], 130 | }, function (err, data) { 131 | var res = [{ 132 | pic_url: "" 133 | }]; 134 | 135 | console.log('data值为',data); 136 | if (data.Location && data.statusCode == 200) { 137 | data.Location = `${TenUrl}/${folder + name}` 138 | res[0].pic_url = data.Location; 139 | callback && callback(res) 140 | } 141 | }); 142 | } 143 | 144 | 145 | var fileUpdateCro = function (folder, files, callback, progress, id, isreload) { 146 | //folder将上lecturer 147 | folder=`${lecturerId}/${folder}` 148 | 149 | var cos = new COS({ 150 | getAuthorization: function (options, callback) { 151 | // 异步获取签名 152 | console.log(options); 153 | $.get(URL + '/api/Auth/signature', { 154 | method: (options.Method || 'get').toLowerCase(), 155 | pathname: '/' + (options.Key || '') 156 | }, function (authorization) { 157 | var obj = JSON.parse(authorization); 158 | callback(obj.signature); 159 | }, 'text'); 160 | 161 | // request({ 162 | // url:`${URL}/api/Auth/signature`, 163 | // method:(options.Method || 'get').toLowerCase(), 164 | // }).then(authorization=>{ 165 | // var obj = JSON.parse(authorization); 166 | // callback(obj.signature); 167 | // }) 168 | } 169 | }) 170 | // 文件名 171 | console.log('folder + name值为',folder + name); 172 | console.log('blob值为',files.blob); 173 | var date = new Date(); 174 | var name = parseInt(Math.random() * 1000000) + '' + date.getFullYear() + addZero(date.getMonth() + 1) + addZero(date.getDate()) + date.getTime() + '.' + files.blob.type.split('/')[1]; 175 | name = md5(name) + '.' + files.blob.type.split('/')[1]; 176 | // 分片上传文件 177 | cos.sliceUploadFile({ 178 | Bucket: Bucket, 179 | Region: Region, 180 | Key: folder + name, 181 | Body: files.blob, 182 | }, function (err, data) { 183 | console.log('上传的data值为',data); 184 | var res = ''; 185 | if (data.Location && data.statusCode == 200) { 186 | data.Location = `${TenUrl}/${folder + name}` 187 | res = data.Location; 188 | callback && callback(res) 189 | } 190 | }); 191 | } 192 | 193 | export { 194 | fileUpdate, 195 | fileUpdateCro 196 | } 197 | 198 | 199 | -------------------------------------------------------------------------------- /src/utils/mixin/chart.js: -------------------------------------------------------------------------------- 1 | const initEchart= 2 | { 3 | methods:{ 4 | drawpie(data1, data2, data3,id) { 5 | data1 = data1 === undefined ? 0 : data1; 6 | data2 = data2 === undefined ? 0 : data2; 7 | data3 = data3 === undefined ? 0 : data3; 8 | let myChart = this.$echarts.init(document.getElementById(id)); 9 | myChart.setOption({ 10 | backgroundColor: "#fff", 11 | legend: { 12 | show: true, 13 | orient: "vertical", 14 | // left: "right", 15 | x:'50%', 16 | y:'center', 17 | itemWidth: 14, 18 | itemHeight: 14, 19 | // bottom: "5%", 20 | textStyle: { 21 | fontSize: 14, 22 | color: "#999999" 23 | }, 24 | selectedMode:false, 25 | data: [ 26 | { 27 | name: `${data1.name} ${data1.percent}% ${data1.number}`, 28 | }, 29 | { 30 | name: `${data2.name} ${data2.percent}% ${data2.number}`, 31 | }, 32 | { 33 | name: `${data3.name} ${data3.percent}% ${data3.number}`, 34 | } 35 | ] 36 | }, 37 | series: [ 38 | { 39 | name: "访问来源", 40 | type: "pie", 41 | radius: ["50%", "100%"], 42 | center: ["25%", "50%"], 43 | data: [ 44 | { 45 | value: data1.number, 46 | name: `${data1.name} ${data1.percent}% ${data1.number}`, 47 | itemStyle: { 48 | normal: { 49 | label: { 50 | color: "#447FF7" 51 | } 52 | } 53 | } 54 | }, 55 | { 56 | value: data2.number, 57 | name: `${data2.name} ${data2.percent}% ${data2.number}`, 58 | itemStyle: { 59 | normal: { 60 | label: { 61 | color: "#35D18D" 62 | } 63 | } 64 | } 65 | }, 66 | { 67 | value: data3.number, 68 | name: `${data3.name} ${data3.percent}% ${data3.number}`, 69 | itemStyle: { 70 | normal: { 71 | label: { 72 | color: "#F7D23B" 73 | } 74 | } 75 | } 76 | } 77 | ], 78 | itemStyle: { 79 | emphasis: { 80 | shadowBlur: 10, 81 | shadowOffsetX: 0, 82 | shadowColor: "rgba(0, 0, 0, 0.5)" 83 | }, 84 | normal: { 85 | label: { 86 | show: false, 87 | position: "outer", 88 | formatter: "{d}%", 89 | textStyle: { 90 | fontSize: 12, 91 | color: "#000" 92 | } 93 | }, 94 | labelLine: { 95 | show: false 96 | } 97 | } 98 | } 99 | } 100 | ], 101 | color: ["#447FF7", "#35D18D", "#F7D23B"] 102 | }); 103 | }, 104 | 105 | drawline(dataX, dataY, id) { 106 | // console.log("drawline执行啦"); 107 | dataX = dataX === undefined ? [] : dataX; 108 | dataY = dataY === undefined ? [] : dataY; 109 | let myChart = this.$echarts.init(document.getElementById(id)); 110 | myChart.setOption({ 111 | backgroundColor: "#fff", 112 | grid: { 113 | left: "5%", 114 | right: "8%", 115 | top: "12%", 116 | bottom: "12%", 117 | containLabel: true 118 | }, 119 | xAxis: { 120 | interval: 5000, 121 | type: "category", 122 | axisLabel: { 123 | // interval: 1 124 | }, 125 | data: dataX, 126 | axisLine: { 127 | onZero: false, 128 | lineStyle: { 129 | color: " #F7F8FA" 130 | } 131 | }, 132 | splitLine: { 133 | show: true, 134 | lineStyle: { 135 | color: ["#EDEDED"], 136 | width: 1, 137 | type: "solid" 138 | } 139 | }, 140 | axisTick: { 141 | show: false 142 | } 143 | }, 144 | yAxis: { 145 | 146 | // min: 0, 147 | // max: 100, 148 | type: "value", 149 | splitLine: { 150 | show: true, 151 | lineStyle: { 152 | color: ["#EDEDED"], 153 | width: 1, 154 | type: "solid" 155 | } 156 | }, 157 | axisLabel: { 158 | fontSize: 13 159 | }, 160 | axisLine: { 161 | onZero: false, 162 | lineStyle: { 163 | color: "#EDEDED" 164 | } 165 | }, 166 | axisTick: { 167 | show: false 168 | } 169 | }, 170 | series: [ 171 | { 172 | id: "a", 173 | type: "line", 174 | smooth: true, 175 | symbol: "circle", 176 | symbolSize: 6, 177 | data: dataY, 178 | // showAllSymbol: true, 179 | areaStyle: { 180 | normal: { 181 | color: new this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [ 182 | { offset: 0, color: "rgba(88,195,128,0.2)" }, 183 | { offset: 1, color: "rgba(88,195,128,0.03)" } 184 | ]) 185 | } 186 | }, 187 | itemStyle: { 188 | normal: { 189 | label: { 190 | show: true, 191 | fontSize: 15, 192 | color: "#58C380", 193 | fontWeight: "540", 194 | textBorderColor: "#fff", 195 | textBorderWidth: 2 196 | }, 197 | borderColor: "rgb(255,255,255)", 198 | borderWidth: 1, 199 | color: " #58C380", 200 | lineStyle: { 201 | color: "#58C380", 202 | width: 2 203 | } 204 | } 205 | } 206 | } 207 | ], 208 | textStyle: { 209 | color: "#54657E" 210 | } 211 | }); 212 | }, 213 | 214 | drawbar(dataX, dataY,id) { 215 | console.log('drawBar执行啦12'); 216 | dataX = dataX === undefined ? [] : dataX; 217 | dataY = dataY === undefined ? [] : dataY; 218 | let myChart = this.$echarts.init(document.getElementById(id)); 219 | myChart.setOption({ 220 | backgroundColor: "#fff", 221 | grid: { 222 | left: "-6%", 223 | right: "0%", 224 | bottom: "2%", 225 | top: "2%", 226 | containLabel: true 227 | }, 228 | yAxis: { 229 | show: false, 230 | axisLabel: { 231 | }, 232 | type: "value", 233 | boundaryGap: [0, 0.01], 234 | axisLine: { 235 | lineStyle: { 236 | color: "#d3d3d3" 237 | } 238 | }, 239 | axisTick: { 240 | show: false 241 | }, 242 | splitLine: { 243 | lineStyle: { 244 | color: "rgba(0,0,0,0)" 245 | } 246 | } 247 | }, 248 | xAxis: { 249 | type: "category", 250 | axisLabel: { 251 | interval:0, 252 | // rotate:-20, 253 | // showMaxLabel:true, 254 | textStyle:{ 255 | fontSize:10 256 | } 257 | }, 258 | boundaryGap:true, 259 | data: dataX, 260 | axisLine: { 261 | lineStyle: { 262 | color: "#999999" 263 | } 264 | }, 265 | 266 | axisTick: { 267 | show: false 268 | } 269 | }, 270 | series: [ 271 | { 272 | name: "2011年", 273 | type: "bar", 274 | data: dataY, 275 | barWidth: 21, 276 | itemStyle: { 277 | normal: { 278 | color: '#447FF7', 279 | label: { 280 | show: true, 281 | position: "top" 282 | } 283 | } 284 | } 285 | } 286 | ], 287 | textStyle: { 288 | color: "#54657E" 289 | } 290 | }); 291 | // console.log("执行啦"); 292 | }, 293 | } 294 | 295 | } 296 | 297 | export default initEchart; -------------------------------------------------------------------------------- /src/utils/request.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import baseUrl from "./config/index"; 3 | 4 | //设置axios拦截器 5 | axios.interceptors.request.use(config => { 6 | //在utils/request里面配置了请求头 7 | return config; 8 | }); 9 | axios.interceptors.response.use( 10 | response => { 11 | // console.log("response值为", response); 12 | //处理data 13 | // response=response.data; 14 | return response; 15 | }, 16 | error => { 17 | if (error.response.code === "200") { 18 | this.$notify.warning({ 19 | title: "警告", 20 | message: `登录信息已过期,请重新扫码登录` 21 | }); 22 | // sessionStorage.setItem("loginFlag", false); 23 | // setTimeout(() => { 24 | // this.$router.push({ path: "/login" }); 25 | // }, 1000); 26 | } 27 | return Promise.reject(error); 28 | } 29 | ); 30 | 31 | function request({ url, method = "POST", data = {}, header, ...param }) { 32 | const token = sessionStorage.getItem("token") || ""; 33 | return new Promise((resolve, reject) => { 34 | axios({ 35 | baseURL: baseUrl, 36 | url, 37 | method, 38 | headers: { 39 | "i-manage-token": token, 40 | "X-Requested-With": "XMLHttpRequest", 41 | withCredentials: true 42 | }, 43 | data, 44 | timeOut: 10000, //配置超时10s 45 | ...param 46 | }).then(res => { 47 | resolve(res); 48 | }); 49 | }); 50 | } 51 | 52 | export default request; 53 | -------------------------------------------------------------------------------- /static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanzhsh/vue-demo/fa286f0b2c94898fc7f192d370267dcff9972495/static/.gitkeep -------------------------------------------------------------------------------- /static/comTable.json: -------------------------------------------------------------------------------- 1 | {tabData:[ 2 | { 3 | date:'2017-05-02', 4 | name:'王小虎', 5 | address:'上海市普陀区金沙江路1518弄' 6 | }, 7 | { 8 | date:'2016-06-04', 9 | name:'王小虎', 10 | address: '上海市普陀区金沙江路 1517 弄' 11 | }, 12 | { 13 | date:'2016-05-01', 14 | name:'王小虎', 15 | address:'上海市普陀区金沙江路 1519 弄' 16 | }, 17 | { 18 | date: '2018-05-03', 19 | name: '王小虎', 20 | address: '上海市普陀区金沙江路 1516 弄' 21 | } 22 | ]} -------------------------------------------------------------------------------- /static/css/common.css: -------------------------------------------------------------------------------- 1 | ul,li{ padding:0;margin:0;list-style:none} 2 | p{margin:0} -------------------------------------------------------------------------------- /static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanzhsh/vue-demo/fa286f0b2c94898fc7f192d370267dcff9972495/static/favicon.png -------------------------------------------------------------------------------- /test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "jest": true 4 | }, 5 | "globals": { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/unit/jest.conf.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports = { 4 | rootDir: path.resolve(__dirname, '../../'), 5 | moduleFileExtensions: [ 6 | 'js', 7 | 'json', 8 | 'vue' 9 | ], 10 | moduleNameMapper: { 11 | '^@/(.*)$': '/src/$1' 12 | }, 13 | transform: { 14 | '^.+\\.js$': '/node_modules/babel-jest', 15 | '.*\\.(vue)$': '/node_modules/vue-jest' 16 | }, 17 | snapshotSerializers: ['/node_modules/jest-serializer-vue'], 18 | setupFiles: ['/test/unit/setup'], 19 | mapCoverage: true, 20 | coverageDirectory: '/test/unit/coverage', 21 | collectCoverageFrom: [ 22 | 'src/**/*.{js,vue}', 23 | '!src/main.js', 24 | '!src/router/index.js', 25 | '!**/node_modules/**' 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /test/unit/setup.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | Vue.config.productionTip = false 4 | -------------------------------------------------------------------------------- /test/unit/specs/HelloWorld.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import HelloWorld from '@/components/HelloWorld' 3 | 4 | describe('HelloWorld.vue', () => { 5 | it('should render correct contents', () => { 6 | const Constructor = Vue.extend(HelloWorld) 7 | const vm = new Constructor().$mount() 8 | expect(vm.$el.querySelector('.hello h1').textContent) 9 | .toEqual('Welcome to Your Vue.js App') 10 | }) 11 | }) 12 | --------------------------------------------------------------------------------