Commit d07ccf95 authored by 郭铭瑶's avatar 郭铭瑶 🤘

初始化项目

parent fac76674
{
"presets": [
["env", {
"modules": false,
"useBuiltIns": "entry",
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": [
"transform-vue-jsx",
"transform-runtime",
["import", {
"libraryName": "view-design",
"libraryDirectory": "src/components"
}]
]
}
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
/build/
/config/
/dist/
/*.js
// https://eslint.org/docs/user-guide/configuring
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint'
},
env: {
browser: true,
},
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
extends: ['plugin:vue/essential'],
// required to lint *.vue files
plugins: [
'vue'
],
// add your custom rules here
rules: {
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
"indent": [
"error",
2
],
'linebreak-style': 'off',
"quotes": [
"error",
"single",
],
"semi": [
"error",
"never",
],
"no-console": 0,
}
}
.DS_Store
node_modules/
/dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
"plugins": {
"postcss-import": {},
"postcss-url": {},
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {}
}
}
# wuye-monitor # dashboard
物业督查实时监控系统 > A Vue.js project
\ No newline at end of file
## Build Setup
``` bash
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
# build for production and view the bundle analyzer report
npm run build --report
```
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
// 用于打包时在dist目录中输出electron.js和package.json
const fs = require('fs')
const path = require('path')
class BuildElectronPlugin {
apply(compiler) {
compiler.plugin('emit', (compilation, callback) => {
const filename = path.join(__dirname, '../electron.js')
const outFilename = (filename.split('/')).pop()
new Promise((resolve, reject) => {
fs.readFile(filename, (err, data) => {
if (err) {
reject(err)
} else {
resolve(data)
}
})
}).then(res => {
const jsonText = `{"main": "${outFilename}"}`
compilation.assets[outFilename.toString()] = {
source () {
return res;
},
size () {
return fs.statSync(filename).size;
}
}
compilation.assets['package.json'] = {
source () {
return jsonText
},
size () {
return jsonText.length
}
}
})
callback();
});
}
}
module.exports = BuildElectronPlugin;
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'production'
const ora = require('ora')
const rm = require('rimraf')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const config = require('../config')
const webpackConfig = require('./webpack.prod.conf')
const spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, (err, stats) => {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})
'use strict'
const chalk = require('chalk')
const semver = require('semver')
const packageConfig = require('../package.json')
const shell = require('shelljs')
function exec (cmd) {
return require('child_process').execSync(cmd).toString().trim()
}
const versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version),
versionRequirement: packageConfig.engines.node
}
]
if (shell.which('npm')) {
versionRequirements.push({
name: 'npm',
currentVersion: exec('npm --version'),
versionRequirement: packageConfig.engines.npm
})
}
module.exports = function () {
const warnings = []
for (let i = 0; i < versionRequirements.length; i++) {
const mod = versionRequirements[i]
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
warnings.push(mod.name + ': ' +
chalk.red(mod.currentVersion) + ' should be ' +
chalk.green(mod.versionRequirement)
)
}
}
if (warnings.length) {
console.log('')
console.log(chalk.yellow('To use this template, you must update following to modules:'))
console.log()
for (let i = 0; i < warnings.length; i++) {
const warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}
'use strict'
const path = require('path')
const config = require('../config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const packageConfig = require('../package.json')
exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
const cssLoader = {
loader: 'css-loader',
options: {
sourceMap: options.sourceMap
}
}
const postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
publicPath: '../../',
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
/**
* 下面的stylus配置便于可全局使用stylus定义的变量
*/
const stylusOptions = {
import: [
path.join(__dirname, '../src/assets/css/variables.styl')
],
path: [
path.join(__dirname, '../src/assets'),
path.join(__dirname, '../')
]
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus', stylusOptions),
styl: generateLoaders('stylus', stylusOptions)
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
const output = []
const loaders = exports.cssLoaders(options)
for (const extension in loaders) {
const loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
exports.createNotifierCallback = () => {
const notifier = require('node-notifier')
return (severity, errors) => {
if (severity !== 'error') return
const error = errors[0]
const filename = error.file && error.file.split('!').pop()
notifier.notify({
title: packageConfig.name,
message: severity + ': ' + error.name,
subtitle: filename || '',
icon: path.join(__dirname, 'logo.png')
})
}
}
'use strict'
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
const sourceMapEnabled = isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap
module.exports = {
loaders: utils.cssLoaders({
sourceMap: sourceMapEnabled,
extract: isProduction
}),
cssSourceMap: sourceMapEnabled,
cacheBusting: config.dev.cacheBusting,
transformToRequire: {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
}
}
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: ['babel-polyfill', './src/main.js']
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
'#': resolve('static'),
}
},
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /view-design.src.*?js$/,
loader: 'babel-loader',
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{
test: /\.styl(us)?$/,
use: [
'vue-style-loader',
'css-loader',
'stylus-loader'
]
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool,
// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay
? { warnings: false, errors: true }
: false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll,
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.dev.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
module.exports = new Promise((resolve, reject) => {
portfinder.basePort = process.env.PORT || config.dev.port
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// publish the new Port, necessary for e2e tests
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port
// Add FriendlyErrorsPlugin
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
},
onErrors: config.dev.notifyOnErrors
? utils.createNotifierCallback()
: undefined
}))
resolve(devWebpackConfig)
}
})
})
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
// const BuildElectronPlugin = require('./build-electron-plugin')
const env = require('../config/prod.env')
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// new BuildElectronPlugin(),
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
// Use Eslint Loader?
// If true, your code will be linted during bundling and
// linting errors and warnings will be shown in the console.
useEslint: true,
// If true, eslint errors and warnings will also be shown in the error overlay
// in the browser.
showEslintErrorsInOverlay: false,
/**
* Source Maps
*/
// https://webpack.js.org/configuration/devtool/#development
devtool: 'cheap-module-eval-source-map',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
cssSourceMap: true
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: './',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
}
}
'use strict'
module.exports = {
NODE_ENV: '"production"'
}
const {app, BrowserWindow} = require('electron')
const url = require('url')
const path = require('path')
let win
function createWindow() {
// const file = 'index.html'
win = new BrowserWindow({})
win.maximize()
win.setResizable(false)
// win.loadURL(url.format({
// pathname: path.join(__dirname, file),
// protocol: 'file:',
// slashes: true,
// }))
// win.webContents.openDevTools()
win.loadFile('./index.html')
win.on('closed', () => {
win = null
})
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (win = null) {
createWindow()
}
})
<!DOCTYPE html>
<html id="html">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
<title>物业督查实时监控系统</title>
<style>
html {
font-size: 1.6vh;
}
</style>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "national-dashboard",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "yaominguo <missgmy@yahoo.com>",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"electron": "electron electron.js",
"lint": "eslint --fix --ext .js,.vue src",
"build": "node build/build.js",
"build:mac": "node build/build.js && electron-packager ./dist dashboard --platform=mas --electron-version=6.1.0 --overwrite",
"build:win": "node build/build.js && electron-packager ./dist dashboard --platform=win32 --electron-version=6.1.0 --overwrite"
},
"dependencies": {
"animate.css": "^3.7.2",
"axios": "^0.19.0",
"babel-polyfill": "^6.26.0",
"countup.js": "^2.0.4",
"echarts": "^4.4.0",
"odometer": "^0.4.8",
"qs": "^6.9.1",
"view-design": "^4.0.2",
"vue": "^2.5.2",
"vue-countup-v2": "^4.0.0",
"vue-odometer": "^1.0.2",
"vue-router": "^3.0.1",
"vue-seamless-scroll": "^1.1.17"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-eslint": "^8.2.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.1",
"babel-plugin-import": "^1.12.2",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"electron": "^3.0.11",
"electron-packager": "^13.0.0",
"eslint": "^4.15.0",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-vue": "^4.0.0",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"node-notifier": "^5.1.2",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"stylus": "^0.54.7",
"stylus-loader": "^3.0.2",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
<template>
<div id="app">
<!-- <transition name="custom-classes-transition" enter-active-class="animated fadeIn" leave-active-class="animated fadeOut"> -->
<router-view :key="$route.fullPath"/>
<!-- </transition> -->
</div>
</template>
<script>
export default {
name: 'App',
// data() {
// return {
// routes: ['farming', 'fishing'],
// cur: 0,
// timer: null,
// timeOuter: null,
// seconds: 1000 * 10
// }
// },
// mounted() {
// // this.$router.push({
// // name: this.routes[this.cur]
// // })
// this.$router.replace({
// name: this.routes[this.cur]
// })
// this.setTimer()
// document.body.addEventListener('mousemove', this.removeTimer)
// },
// beforeDestroy() {
// clearInterval(this.timer)
// document.body.removeEventListener('mousemove')
// },
// methods: {
// setTimer() {
// this.timer = setInterval(() => {
// this.cur += 1
// if (this.cur >= this.routes.length) {
// this.cur = 0
// }
// this.$router.push({
// name: this.routes[this.cur]
// })
// }, this.seconds)
// },
// removeTimer() {
// clearTimeout(this.timeOuter)
// clearInterval(this.timer)
// this.timer = null
// this.timeOuter = setTimeout(this.setTimer, this.seconds / 10)
// },
// },
}
</script>
<style lang="stylus">
@import './assets/css/variables.styl'
@import './assets/css/reset.styl'
@font-face
font-family DIN
src url(./assets/font/DIN-Medium.otf)
@font-face
font-family Microsoft YaHei UI
src url(./assets/font/Microsoft-YaHei-UI-Bold.ttf)
@font-face
font-family Pangmenzhengdao
src url(./assets/font/pangmenzhengdao.ttf)
html, body
background-color #000 !important
width 100%
height 100%
user-select none
#app
font-family DIN, 'Avenir', Helvetica, Arial, sans-serif
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
width 100%
height 100%
font-size 1rem
overflow: hidden
color $fontColor
/* 设置滚动条的样式 */
::-webkit-scrollbar {
width: 0.5rem;
}
// /* 滚动槽 */
// ::-webkit-scrollbar-track {
// -webkit-box-shadow: inset006pxrgba(0,0,0,0.3);
// /* border-radius: 10px; */
// }
/* 滚动条滑块 */
::-webkit-scrollbar-thumb {
/* border-radius: 10px; */
background:rgba(91, 213, 255, 0.2)
-webkit-box-shadow:inset006pxrgba(0,0,0,0.5);
}
::-webkit-scrollbar-thumb:window-inactive {
background:rgba(91, 213, 255, 0.2)
}
</style>
$color-main = #5BD5FF
#app
.ivu-select-selection
.ivu-select-dropdown
font-size 0.8rem
background-color $color-map(0.8)
border-radius 0
border 0.1rem solid $color-main
// color $color-main
color #fff
padding 0
.ivu-select-arrow
color $color-main
.ivu-select-selected-value
font-size 0.8rem
.ivu-select-item
.ivu-dropdown-item
font-size 1rem !important
text-align center
color #fff
&:hover
&.ivu-select-item-selected
color #fff
background $color-map(1)
// color $color-main
// background #fff
$font-yahei = Microsoft YaHei UI, 'Avenir', Helvetica, Arial, sans-serif
$font-pang = Pangmenzhengdao, 'Avenir', Helvetica, Arial, sans-serif
$font-din = DIN, 'Avenir', Helvetica, Arial, sans-serif
$color-map(opacity = 0.3)
rgba(91, 213, 255, opacity)
$color-green = #71C012
$gd-layout(gap = 1rem)
width 100%
height 100%
background-size cover
background-position center
background-color #061627
position relative
display grid
grid-gap gap
padding 1rem
$fontColor = #2c3e50
$edgeColor = #2ee4f5
$cardBg = rgba(19, 78, 115, 0.4)
$cardBorder = 0.1rem solid #1c425f
$cardFontColor = #0eb2ee
import MonitorBrief from './monitor-brief.vue'
export default (Vue) => {
Vue.component('m-brief', MonitorBrief)
}
<template>
<div class="brief-container">
<span class="label">{{label}}</span>
<m-count class="count" :value="value"/>
<span>{{unit}}</span>
</div>
</template>
<script>
export default {
name: 'MonitorBrief',
props: {
label: {
type: String,
default: '',
},
count: {
type: Number,
default: 0,
},
unit: {
type: String,
default: '',
}
},
computed: {
value() {
return this.count
}
}
}
</script>
<style lang="stylus" scoped>
.brief-container
display inline-block
color #fff
font-size 0.8rem
.label
color $cardFontColor
margin-right 0.5rem
.count
font-size 1.4rem
font-weight bold
</style>
import MonitorCard from './monitor-card.vue'
export default (Vue) => {
Vue.component('m-card', MonitorCard)
}
<template>
<div class="monitor-card">
<div v-if="mode == 1" class="card-wrapper">
<div class="card-title">
<span class="s"/>
<span class="m"/>
<p>{{title}}</p>
<span class="m"/>
<span class="s"/>
</div>
<div class="edge left-top"/>
<div class="edge right-top"/>
<div class="edge left-bottom"/>
<div class="edge right-bottom"/>
<div class="edge shadow left"/>
<div class="edge shadow right"/>
<slot />
</div>
<div v-else-if="mode == 2" class="map-card-wrapper">
<div class="card-title">{{title}}</div>
<div class="card-content">
<div class="edge left-bottom"/>
<div class="edge right-bottom"/>
<slot />
</div>
</div>
</div>
</template>
<script>
export default {
name: 'MonitorCard',
props: {
title: {
type: String,
default: '标题',
},
mode: {
type: [String, Number],
default: '1',
}
}
}
</script>
<style lang="stylus" scoped>
$edgeWidth = 0
$size()
height 100%
width 100%
.monitor-card
$size()
.card-wrapper
$size()
background $cardBg
// border $cardBorder
box-shadow inset 0 0 0.8rem rgba(100,200,255,0.5)
padding 0.5rem 1rem
position relative
>.card-title
display flex
align-items center
color $cardFontColor
border-bottom $cardBorder
padding-bottom 0.5rem
font-size 1.2rem
font-weight 460
p
margin 0 0.5rem
span
display inline-block
background $edgeColor
margin 0 0.1rem
&.s
width 0.2rem
height 1rem
opacity 0.5
&.m
width 0.3rem
height 1.2rem
>.edge
position absolute
width 1rem
height 1rem
border: 0.12rem solid $edgeColor
&.left-top
border-right-color transparent
border-bottom-color transparent
top $edgeWidth
left $edgeWidth
&.right-top
border-left-color transparent
border-bottom-color transparent
top $edgeWidth
right $edgeWidth
&.left-bottom
border-right-color transparent
border-top-color transparent
bottom $edgeWidth
left $edgeWidth
&.right-bottom
border-left-color transparent
border-top-color transparent
bottom $edgeWidth
right $edgeWidth
&.shadow
background $edgeColor
height 24%
width 0.1rem
border none
top 0
bottom 0
margin auto
&.left
left 0
box-shadow 1px 0px 6px 1px $edgeColor
&.right
right 0
box-shadow -1px 0px 6px 1px $edgeColor
.map-card-wrapper
$size()
.card-title
color #fff
font-size 1.4rem
font-family $font-pang
.card-content
background $color-map(0.1)
border-top 0.12rem solid $edgeColor
height calc(100% - 2rem)
position relative
>.edge
position absolute
width 1rem
height 1rem
border: 0.12rem solid $edgeColor
&.left-bottom
border-right-color transparent
border-top-color transparent
bottom $edgeWidth
left $edgeWidth
&.right-bottom
border-left-color transparent
border-top-color transparent
bottom $edgeWidth
right $edgeWidth
</style>
import MonitorChart from './monitor-chart.vue'
export default (Vue) => {
Vue.component('m-chart', MonitorChart)
}
<template>
<div class="chart" ref="chart"/>
</template>
<script>
export default {
name: 'CommonChart',
props: {
data: {
type: Array,
default() {
return []
},
},
showLegend: {
type: Boolean,
default: true,
},
options: {
type: Object,
default() {
return {
colors: null,
grid: {},
legend: {},
tooltip: {},
xAxis: {},
yAxis: {},
}
}
},
},
mounted() {
if (this.data.length > 0) {
this.$nextTick(this.init)
}
},
methods: {
init() {
const chart = this.$echarts.init(this.$refs.chart)
chart.setOption(this.config)
}
},
computed: {
config() {
const options = {}
const colors = this.options.colors || ['#21640D', '#2F8B14', '#71C012', '#FFCE34', '#F47C1F']
options.grid = Object.assign(this.defaultOptions.grid, this.options.grid)
options.tooltip = Object.assign(this.defaultOptions.tooltip, this.options.tooltip)
if(this.showLegend) {
options.legend = Object.assign(this.defaultOptions.legend, this.options.legend)
if (this.options.series.type === 'pie') {
options.color = this.options.color || colors
options.series = [this.options.series]
options.series[0].data = options.legend.data = this.data
return options
}
options.legend.data = this.data.map(item => item.name)
}
options.xAxis = Object.assign(this.defaultOptions.xAxis, this.options.xAxis)
if(Array.isArray(this.options.yAxis) && this.options.yAxis.length > 0) {
options.yAxis = this.options.yAxis.map((item, index) => {
return Object.assign(this.defaultOptions.yAxis, item)
})
} else {
options.yAxis = Object.assign(this.defaultOptions.yAxis, this.options.yAxis || {})
}
options.series = this.data.map((item, index) => {
let color = colors[index]
let shadow = {}
if (Array.isArray(color)) { // 如果颜色是数组则渐变
const shadowColor = color[0] || '#0076FF'
color = new this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [
{offset: 0, color: color[0]},
{offset: 1, color: color[1]}
])
shadow = {
shadowColor: shadowColor,
shadowBlur: 6,
}
}
const result = {
name: item.name,
barWidth: '50%',
itemStyle: { color, ...shadow },
data: item.data || []
}
if (Array.isArray(this.options.series) && this.options.series.length > 0) {
// 双y轴设置一样的间隔
const y1 = [], y2 = []
this.options.series.forEach((el, i) => {
if (el.yAxisIndex) {
y2.push(...this.data[i].data)
} else {
y1.push(...this.data[i].data)
}
const y1Max = Math.max.apply(null, y1)
const y2Max = Math.max.apply(null, y2)
options.yAxis[0] = Object.assign({...options.yAxis[0]}, {min:0, max: y1Max, interval:y1Max / 5})
options.yAxis[1] = Object.assign({...options.yAxis[1]}, {min:0, max: y2Max, interval:y2Max / 5})
})
return Object.assign(result, this.options.series[index])
} else {
return Object.assign(result, this.options.series || {})
}
return result
})
return options
},
defaultOptions() {
return {
grid: {
top: '25%',
left: '3%',
right: '3%',
bottom: '5px',
width: 'auto',
height: 'auto',
containLabel: true,
},
legend: {
top: '5%',
left: '6%',
width: '100%',
data: [],
itemWidth: 15,
textStyle: {
color: '#ccc',
fontSize: this.fontSize,
},
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
xAxis: {
type: 'category',
data: [],
axisLabel: {
textStyle: {
color: '#ccc',
},
fontSize: this.fontSize,
},
axisLine: {
lineStyle: {
color: 'rgba(91,213,255,0.3)'
}
},
splitLine: {
show: true,
lineStyle: {
color: 'rgba(91,213,255,0.3)'
}
}
},
yAxis: {
nameTextStyle: {
color: '#fff',
fontSize: this.fontSize,
},
type: 'value',
splitLine: {
show: true,
lineStyle: {
color: 'rgba(91,213,255,0.3)'
}
},
axisLabel: {
textStyle: {
color: '#ccc',
},
fontSize: this.fontSize,
},
axisLine: {
lineStyle: {
color: 'rgba(91,213,255,0.3)'
}
},
},
}
},
fontSize() {
// return Math.floor(window.innerWidth / 100) - 1
return Math.floor(screen.height * 1.48 / 100)
},
},
watch: {
data(cur, past) {
if (cur && cur !== past && cur.length > 0) {
this.init()
}
}
},
}
</script>
<style lang="stylus" scoped>
.chart
height 100%
width 100%
</style>
import MonitorCount from './monitor-count.vue'
export default (Vue) => {
Vue.component('m-count', MonitorCount)
}
<template>
<ICountUp
:delay="delay"
:endVal="value"
:options="config"
@ready="onReady"
/>
</template>
<script>
import ICountUp from 'vue-countup-v2'
export default {
name: 'MonitorCount',
components: {
ICountUp,
},
props: {
delay: {
type: Number,
default: 500,
},
value: {
type: Number,
default: 0,
},
decimal: { // 默认保留2位小数点
type: Number,
default: 2,
},
options: {
type: Object,
default() {
return {
useEasing: true,
useGrouping: true,
separator: ',',
decimal: '.',
prefix: '',
suffix: '',
}
}
},
autoUpdate: {
type: Boolean,
default: false,
},
updateDuration: {
type: Number,
default: 1,
},
},
computed: {
config() {
return Object.assign(this.options, {decimalPlaces: this.decimal})
}
},
methods: {
onReady(instance, countup) {
if (!this.autoUpdate) return
setTimeout(() => {
instance.reset()
instance.update(instance.endVal)
}, 1000 * 60 * this.updateDuration)
},
}
}
</script>
import MonitorFlip from './monitor-flip.vue'
export default (Vue) => {
Vue.component('m-flip', MonitorFlip)
}
<template>
<IOdometer
class="monitor-flip"
:value="num"
/>
</template>
<script>
import IOdometer from 'vue-odometer'
export default {
name: 'MonitorFlip',
components: {
IOdometer,
},
props: {
value: {
type: Number,
default: 0,
},
},
data() {
return {
num: 0,
}
},
mounted() {
this.$nextTick(() => {
this.num = this.value
})
},
}
</script>
<style lang="stylus" scoped>
.monitor-flip
font-family $font-din
</style>
<style lang="stylus">
@import 'odometer/themes/odometer-theme-default.css'
.monitor-flip
.odometer-digit
background linear-gradient($color-map() 47%, transparent 50%, $color-map() 53%)
margin-right 0.4rem
padding 0 0.4rem
.odometer-digit-inner
padding 0 0.4rem
</style>
import MonitorProgress from './monitor-progress'
export default (Vue) => {
Vue.component('m-progress', MonitorProgress)
}
<template>
<div class="monitor-progress" :style="style">
<div class="progress-container" :style="containerStyle">
<div class="progress-bar"/>
<div class="progress-bg" :style="bgStyle"/>
</div>
<b v-if="!hideInfo" class="progress-info" :style="infoStyle">
<m-count :value="percent"/>%
</b>
</div>
</template>
<script>
export default {
name: 'MonitorProgress',
props: {
percent: {
type: Number,
default: 0,
},
color: {
type: String | Array,
default: '#0176fe',
},
size: {
type: Number,
default: 14,
},
'hide-info': {
type: Boolean,
default: false,
},
'text-inside': {
type: Boolean,
default: false,
}
},
computed: {
style() {
const size = Math.round(this.size / 10)
const result = {
padding: `${(size / 5).toFixed(1)}rem ${(size / 4.5).toFixed(1)}rem`,
}
if (!this.hideInfo && !this.textInside) {
result.width = '85%'
} else {
if (this.percent >= 95) {
result.width = '85%'
} else {
result.width = '100%'
}
}
return result
},
containerStyle() {
return {
height: `${(this.size / 10).toFixed(1)}rem`,
width: `${this.percent >= 100 ? 100 : this.percent}%`,
}
},
bgStyle() {
if ('string' === typeof this.color) {
return {
background: this.color
}
} else {
return {
background: `linear-gradient(90deg, ${this.color[0]}, ${this.color[1]})`
}
}
},
infoStyle() {
let info = {
left: '102%'
}
if (this.textInside && this.percent < 95) {
info = {
left: `${this.percent + 1}%`,
}
}
return {
...info,
fontSize: `${(this.size * 0.7 / 10).toFixed(1)}rem`,
color: 'string' === typeof this.color ? this.color : this.color[1],
}
},
}
}
</script>
<style lang="stylus" scoped>
$radius = 2rem
.monitor-progress
position relative
border-radius $radius
background rgba(0,0,0,0.18)
box-shadow inset 0 0 0.2rem 0 #000
.progress-container
width 0
position relative
border-radius $radius
transition width 2s ease
div
position: absolute
top 0
left 0
width 100%
height 100%
border-radius $radius
&.progress-bar
z-index 1
opacity 0.2
background-size 17rem
background-image repeating-linear-gradient(45deg, #fff, #fff 0.8rem, transparent 0.8rem, transparent 1.2rem)
animation rolling 20s linear infinite running
.progress-info
display flex
align-items center
justify-content center
position absolute
left 0
top 0
height 100%
transition left 2s ease
text-shadow 0 0 0.6rem rgba(255,255,255,0.5)
@keyframes rolling
to
background-position-x 17rem
</style>
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import 'babel-polyfill'
import Vue from 'vue'
import App from './App'
import router from './router'
import echarts from 'echarts'
import {Button, Divider, Progress, Select, Option, Circle, Icon, Dropdown, DropdownMenu, DropdownItem} from 'view-design'
import animate from 'animate.css'
import ajax from '@/server/ajax'
import api from '@/server/api'
import MonitorCard from '@/components/MonitorCard'
import MonitorChart from '@/components/MonitorChart'
import MonitorCount from '@/components/MonitorCount'
import MonitorFlip from '@/components/MonitorFlip'
import MonitorBrief from '@/components/MonitorBrief'
import MonitorProgress from '@/components/MonitorProgress'
import 'view-design/dist/styles/iview.css'
Vue.config.productionTip = false
Vue.prototype.$echarts = echarts
Vue.prototype.$ajax = ajax
Vue.prototype.$api = api
Vue.use(animate)
Vue.use(MonitorCard)
Vue.use(MonitorCount)
Vue.use(MonitorFlip)
Vue.use(MonitorBrief)
Vue.use(MonitorProgress)
Vue.use(MonitorChart)
Vue.component('Button', Button)
Vue.component('Divider', Divider)
Vue.component('Progress', Progress)
Vue.component('Select', Select)
Vue.component('Option', Option)
Vue.component('i-circle', Circle)
Vue.component('Icon', Icon)
Vue.component('Dropdown', Dropdown)
Vue.component('DropdownMenu', DropdownMenu)
Vue.component('DropdownItem', DropdownItem)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
import Vue from 'vue'
import Router from 'vue-router'
const Main = () => import('@/views/main')
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'main',
component: Main,
},
]
})
import axios from 'axios'
import qs from 'qs'
import api from './api'
const Axios = axios.create({
baseURL: api.BASE_URL,
timeout: 50000,
})
Axios.interceptors.request.use(config => {
// 启动loading,添加token
// config.headers.Authorization = token
return config
}, error => {
return Promise.reject(error)
})
Axios.interceptors.response.use(response => {
// TODO 返回的数据status判断错误操作等……
return response.data
}, error => {
return Promise.resolve(error.response)
})
export default {
post(url, data) {
return Axios({
method: 'POST',
url,
data: qs.stringify(data),
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
}
}).then(res => res)
},
get(url, params) {
return Axios({
method: 'GET',
url,
params, // get 请求时带的参数
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json;charset=UTF-8',
}
}).then(res => res)
}
}
let IMG_URL = ''
let FILE_URL = ''
switch (process.env.NODE_ENV) {
case 'production':
IMG_URL = 'http://10.221.1.181:8080/dist/static/'
FILE_URL = '/quanguo/static/'
break
default:
IMG_URL = 'http://localhost:8080/static/'
FILE_URL = '/static/'
};
export default {
BASE_URL: 'http://sunmonster.vicp.cc:41318/pudong/',
IMG_URL,
FILE_URL,
GET_SMART_INFO: '/api/discoverInfo',
GET_SMART_DETAIL: '/api/discoverDetail',
GET_TS_LIST: '/api/findUnCaseTsList',
GET_BX_LIST: '/api/findUnCaseBxList',
GET_COMPANY_CYCLE: '/api/findCycle',
GET_CREDIT_HIGH: '/api/findCreditHigh',
GET_CREDIT_MIDDLE: '/api/findCreditMiddle',
GET_CREDIT_LOW: '/api/findCreditLow',
}
/** 公共方法 */
export default {
/**
* 在深层数据结构中取值(为了替代类似 res && res.data && res.data.content这种写法)
* @param {Object} obj [必填-需要取值的目标对象(例:res)]
* @param {String} path [必填-数据结构路径(例:'data.content')]
* @param {Any} defaultValue [可选-如果取不到值则默认返回该值]
*/
confirm(obj, path, defaultValue = null) {
if (!obj || typeof(obj) != 'object' || !path || typeof(path) != 'string') return
const reducer = (accumulator, currentValue) =>
(accumulator && accumulator[currentValue]) ?
accumulator[currentValue] :
defaultValue
path = path.split('.')
return path.reduce(reducer, obj)
},
/**
* ----- 柯里化版本 (为了不再重复输入obj这个参数) -----
* 在深层数据结构中取值(为了替代类似 res && res.data && res.data.content这种写法)
* @param {Object} obj [必填-需要取值的目标对象(例:res)]
*/
confirm_currying(obj) {
if (!obj || typeof(obj) != 'object') return
return (path, defaultValue = null) => {
if (!path || typeof(path) != 'string') return
const reducer = (accumulator, currentValue) =>
(accumulator && accumulator[currentValue]) ?
accumulator[currentValue] :
defaultValue
path = path.split('.')
return path.reduce(reducer, obj)
}
},
/**
* 判断一维数组中是否存在某个值
* @param {String} value 需要校验的字符串
* @param {Array} validList 被查找的一维数组
* @return {Boolean} 是否存在的结果
*/
oneOf(value, validList) {
for (let i = 0; i < validList.length; i++) {
if (value === validList[i]) {
return true
}
}
return false
},
/**
* 转换为金钱格式(千分位且保留两位小数)
* @param {Number | String} num [需转换的数字或字符串]
*/
toMoney(num) {
if (!num) {
return 0.00
}
num = this.toFloat(num).toFixed(2)
const arr = num.toString().split('.')
let int = (arr[0] || 0).toString(),
result = ''
while (int.length > 3) {
result = ',' + int.slice(-3) + result
int = int.slice(0, int.length - 3)
}
if (int) {
result = int + result
}
return `${result}.${arr[1]}`
},
/**
* 手机号码校验
* @param {String} num [需校验的手机号码]
*/
checkPhone(num) {
if (!num) return false
const filter = /^1[3-9][0-9]{9}$/
return filter.test(num)
},
/**
* 固定电话号码校验
* @param {String} num [需校验的固话]
*/
checkTel(num) {
if (!num) return false
const filter = /^(?:0[1-9][0-9]{1,2}-)?[2-8][0-9]{6,7}$/
return filter.test(num)
},
/**
* 身份证号码校验
* @param {String} num [需校验的身份证号码]
*/
checkID(num) {
if (!num) return false
const filter = /(^\d{15}$)|(^\d{17}([0-9]|X)$)/
return filter.test(num)
},
/**
* 数字校验(整数或者小数)
* @param {String} num [需校验的数字]
*/
checkNumber(num) {
if (!num && num != 0) return false
const filter = /^[0-9]+\.{0,1}[0-9]{0,2}$/
return filter.test(num)
},
/**
* 邮编校验(整数或者小数)
* @param {String} num [需校验的数字]
*/
checkZipCode(num) {
if (!num && num != 0) return false
const filter = /^[0-9]{6}$/
return filter.test(num)
},
/**
* 文本校验(只能为中文、英文、数字组合,不允许其他特殊符号)
* @param {String} txt [需校验的文本]
*/
checkContent(txt) {
const filter = /^[\u4E00-\u9FA5A-Za-z0-9]+$/
return filter.test(txt)
},
/**
* 密码校验(6位以上数字字母的组合)
* @param {String} txt [需校验的文本]
*/
checkPassword(num) {
if (!num && num != 0) return false
const filter = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,}$/
return filter.test(num)
},
/**
* 获取URL执行参数值
* @param {String} variable 地址参数名
* @return false 未找到;
*/
getQueryVariable(variable) {
var query = window.location.search.substring(1)
var vars = query.split('&')
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=')
if (pair[0] == variable) {
return pair[1]
}
}
},
/**
* 获取当前年
*
*/
getCurrentYear() {
var date = new Date
return date.getFullYear()
},
/**
* 接收带时分秒的时间格式,返回去掉时分秒的时间格式
* @param {String} val
*/
strTime(val) {
if (val === undefined || val == null) return
val = val.toString()
if (val == null || val == '') {
return ''
} else {
return val.slice(0, val.indexOf(' '))
}
},
/**
* 判断传入参数的类型,以字符串的形式返回
* @obj:数据
**/
dataType(obj) {
if (obj === null) return 'Null'
if (obj === undefined) return 'Undefined'
return Object.prototype.toString.call(obj).slice(8, -1)
},
/**
* 处理对象参数值,排除对象参数值为”“、null、undefined,并返回一个新对象
**/
dealObjectValue(obj) {
var param = {}
if (obj === null || obj === undefined || obj === '') return param
for (var key in obj) {
if (this.dataType(obj[key]) === 'Object') {
param[key] = dealObjectValue(obj[key])
} else if (obj[key] !== null && obj[key] !== undefined && obj[key] !== '') {
param[key] = obj[key]
}
}
return param
},
/**
* 判断是否是ie并返回版本号
*/
IEVersion() {
const userAgent = navigator.userAgent //取得浏览器的userAgent字符串
const isIE = userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1 //判断是否IE<11浏览器
const isEdge = userAgent.indexOf('Edge') > -1 && !isIE //判断是否IE的Edge浏览器
const isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf('rv:11.0') > -1
if(isIE) {
const reIE = new RegExp('MSIE (\\d+\\.\\d+);')
reIE.test(userAgent)
const fIEVersion = parseFloat(RegExp['$1'])
if(fIEVersion == 7) {
return 7
} else if(fIEVersion == 8) {
return 8
} else if(fIEVersion == 9) {
return 9
} else if(fIEVersion == 10) {
return 10
} else {
return 6//IE版本<=7
}
} else if(isEdge) {
return 'edge'//edge
} else if(isIE11) {
return 11 //IE11
}else{
return -1//不是ie浏览器
}
},
/**
* 输入数字转换成大写字母,比如 输入 0 输出 'A'
* @param {Number} num 输入的数字
*/
numToLetter(num) {
if (!num && num != 0) return null
return (Number(num) + 10).toString(36).toUpperCase()
}
}
<template>
<div>
</div>
</template>
<script>
export default {
name: 'Main',
}
</script>
<style lang="stylus" scoped>
</style>
{
"nation": {
"area": [
{"name": 2014, "value": 1489501, "unit": "公顷"},
{"name": 2015, "value": 1501629, "unit": "公顷"},
{"name": 2016, "value": 1484001, "unit": "公顷"},
{"name": 2017, "value": 1682689, "unit": "公顷"},
{"name": 2018, "value": 2028262, "unit": "公顷"}
],
"water": [
{"name":2014, "value": 29357591, "unit": "吨"},
{"name":2015, "value": 30622735, "unit": "吨"},
{"name":2016, "value": 28778881, "unit": "吨"},
{"name":2017, "value": 29052930, "unit": "吨"},
{"name":2018, "value": 29598384, "unit": "吨"}
],
"farm": [
{"name":2014, "value":1456719, "unit": "吨"},
{"name":2015, "value":1558187, "unit": "吨"},
{"name":2016, "value":1628361, "unit": "吨"},
{"name":2017, "value":1947507, "unit": "吨"},
{"name":2018, "value":2333269, "unit": "吨"}
]
},
"province": [
{"name": "北京", "area": [
{"name": 2014, "value":0},
{"name": 2015, "value":4},
{"name": 2016, "value":0},
{"name": 2017, "value":0},
{"name": 2018, "value":0}
], "water": [
{"name": 2014, "value":50871},
{"name": 2015, "value":45043},
{"name": 2016, "value":37423},
{"name": 2017, "value":33082},
{"name": 2018, "value":25962}
], "farm": [
{"name": 2014, "value": 0},
{"name": 2015, "value":1},
{"name": 2016, "value":0},
{"name": 2017, "value": 0},
{"name": 2018, "value": 0}
]},
{"name": "天津", "area": [
{"name": 2014, "value":1067},
{"name": 2015, "value":2993},
{"name": 2016, "value":2783},
{"name": 2017, "value":2784},
{"name": 2018, "value":3285}
], "water": [
{"name": 2014, "value":319311},
{"name": 2015, "value":313012},
{"name": 2016, "value":259368},
{"name": 2017, "value":269198},
{"name": 2018, "value":272228}
], "farm": [
{"name": 2014, "value": 320},
{"name": 2015, "value":438},
{"name": 2016, "value":421},
{"name": 2017, "value": 515},
{"name": 2018, "value": 638}
]},
{"name": "河北", "area": [
{"name": 2014, "value":1903},
{"name": 2015, "value":1228},
{"name": 2016, "value":1100},
{"name": 2017, "value":1483},
{"name": 2018, "value":2423}
], "water": [
{"name": 2014, "value":430667},
{"name": 2015, "value":433425},
{"name": 2016, "value":329400},
{"name": 2017, "value":304175},
{"name": 2018, "value":286351}
], "farm": [
{"name": 2014, "value": 876},
{"name": 2015, "value":455},
{"name": 2016, "value":249},
{"name": 2017, "value": 569},
{"name": 2018, "value": 1249}
]},
{"name": "山西", "area": [
{"name": 2014, "value":266},
{"name": 2015, "value":266},
{"name": 2016, "value":266},
{"name": 2017, "value":267},
{"name": 2018, "value":266}
], "water": [
{"name": 2014, "value":50188},
{"name": 2015, "value":51353},
{"name": 2016, "value":51138},
{"name": 2017, "value":50905},
{"name": 2018, "value":45451}
], "farm": [
{"name": 2014, "value": 140},
{"name": 2015, "value":140},
{"name": 2016, "value":140},
{"name": 2017, "value": 140},
{"name": 2018, "value": 140}
]},
{"name": "内蒙古", "area": [
{"name": 2014, "value":3235},
{"name": 2015, "value":2906},
{"name": 2016, "value":4185},
{"name": 2017, "value":4504},
{"name": 2018, "value":6326}
], "water": [
{"name": 2014, "value":118031},
{"name": 2015, "value":124161},
{"name": 2016, "value":128995},
{"name": 2017, "value":127827},
{"name": 2018, "value":118179}
], "farm": [
{"name": 2014, "value": 435},
{"name": 2015, "value":474},
{"name": 2016, "value":494},
{"name": 2017, "value": 235},
{"name": 2018, "value": 301}
]},
{"name": "辽宁", "area": [
{"name": 2014, "value":104962},
{"name": 2015, "value":81544},
{"name": 2016, "value":60588},
{"name": 2017, "value":51773},
{"name": 2018, "value":51509}
], "water": [
{"name": 2014, "value":904206},
{"name": 2015, "value":936990},
{"name": 2016, "value":830200},
{"name": 2017, "value":830000},
{"name": 2018, "value":798728}
], "farm": [
{"name": 2014, "value": 68428},
{"name": 2015, "value":53089},
{"name": 2016, "value":53129},
{"name": 2017, "value": 47101},
{"name": 2018, "value": 52109}
]},
{"name": "吉林", "area": [
{"name": 2014, "value":5897},
{"name": 2015, "value":8187},
{"name": 2016, "value":12564},
{"name": 2017, "value":25278},
{"name": 2018, "value":33171}
], "water": [
{"name": 2014, "value":169468},
{"name": 2015, "value":175546},
{"name": 2016, "value":181200},
{"name": 2017, "value":201046},
{"name": 2018, "value":214790}
], "farm": [
{"name": 2014, "value": 906},
{"name": 2015, "value":1499},
{"name": 2016, "value":2411},
{"name": 2017, "value": 5256},
{"name": 2018, "value": 7740}
]},
{"name": "黑龙江", "area": [
{"name": 2014, "value":15065},
{"name": 2015, "value":31898},
{"name": 2016, "value":23593},
{"name": 2017, "value":33345},
{"name": 2018, "value":47000}
], "water": [
{"name": 2014, "value":459396},
{"name": 2015, "value":485199},
{"name": 2016, "value":503300},
{"name": 2017, "value":535662},
{"name": 2018, "value":577220}
], "farm": [
{"name": 2014, "value": 4287},
{"name": 2015, "value":4317},
{"name": 2016, "value":4658},
{"name": 2017, "value": 5585},
{"name": 2018, "value": 7580}
]},
{"name": "上海", "area": [
{"name": 2014, "value":12},
{"name": 2015, "value":24},
{"name": 2016, "value":43},
{"name": 2017, "value":62},
{"name": 2018, "value":75}
], "water": [
{"name": 2014, "value":157468},
{"name": 2015, "value":151289},
{"name": 2016, "value":125800},
{"name": 2017, "value":122750},
{"name": 2018, "value":94293}
], "farm": [
{"name": 2014, "value": 3},
{"name": 2015, "value":110},
{"name": 2016, "value":166},
{"name": 2017, "value": 185},
{"name": 2018, "value": 219}
]},
{"name": "江苏", "area": [
{"name": 2014, "value":117676},
{"name": 2015, "value":109758},
{"name": 2016, "value":110758},
{"name": 2017, "value":131802},
{"name": 2018, "value":241058}
], "water": [
{"name": 2014, "value":3357919},
{"name": 2015, "value":3403218},
{"name": 2016, "value":3303816},
{"name": 2017, "value":3281006},
{"name": 2018, "value":3252943}
], "farm": [
{"name": 2014, "value": 207721},
{"name": 2015, "value":197876},
{"name": 2016, "value":189709},
{"name": 2017, "value": 188631},
{"name": 2018, "value": 249994}
]},
{"name": "浙江", "area": [
{"name": 2014, "value":75424},
{"name": 2015, "value":83060},
{"name": 2016, "value":77164},
{"name": 2017, "value":73134},
{"name": 2018, "value":46434}
], "water": [
{"name": 2014, "value":977452},
{"name": 2015, "value":1019515},
{"name": 2016, "value":1051271},
{"name": 2017, "value":1107271},
{"name": 2018, "value":1133036}
], "farm": [
{"name": 2014, "value": 301796},
{"name": 2015, "value":339186},
{"name": 2016, "value":343931},
{"name": 2017, "value": 286614},
{"name": 2018, "value": 134876}
]},
{"name": "安徽", "area": [
{"name": 2014, "value":52894},
{"name": 2015, "value":54882},
{"name": 2016, "value":64661},
{"name": 2017, "value":84769},
{"name": 2018, "value":150636}
], "water": [
{"name": 2014, "value":1908408},
{"name": 2015, "value":1987873},
{"name": 2016, "value":1862600},
{"name": 2017, "value":1901124},
{"name": 2018, "value":1990499}
], "farm": [
{"name": 2014, "value": 79173},
{"name": 2015, "value":83069},
{"name": 2016, "value":100273},
{"name": 2017, "value": 102347},
{"name": 2018, "value": 218811}
]},
{"name": "福建", "area": [
{"name": 2014, "value":18623},
{"name": 2015, "value":18492},
{"name": 2016, "value":15600},
{"name": 2017, "value":15335},
{"name": 2018, "value":15914}
], "water": [
{"name": 2014, "value":837089},
{"name": 2015, "value":888147},
{"name": 2016, "value":711802},
{"name": 2017, "value":752232},
{"name": 2018, "value":800880}
], "farm": [
{"name": 2014, "value": 15449},
{"name": 2015, "value":15538},
{"name": 2016, "value":12303},
{"name": 2017, "value": 12688},
{"name": 2018, "value": 15850}
]},
{"name": "江西", "area": [
{"name": 2014, "value":63429},
{"name": 2015, "value":64112},
{"name": 2016, "value":34972},
{"name": 2017, "value":50397},
{"name": 2018, "value":66996}
], "water": [
{"name": 2014, "value":2276781},
{"name": 2015, "value":2378446},
{"name": 2016, "value":2194139},
{"name": 2017, "value":2279506},
{"name": 2018, "value":2335443}
], "farm": [
{"name": 2014, "value": 67922},
{"name": 2015, "value":68092},
{"name": 2016, "value":68402},
{"name": 2017, "value": 81565},
{"name": 2018, "value": 97950}
]},
{"name": "山东", "area": [
{"name": 2014, "value":595},
{"name": 2015, "value":1738},
{"name": 2016, "value":1819},
{"name": 2017, "value":2020},
{"name": 2018, "value":2298}
], "water": [
{"name": 2014, "value":1464056},
{"name": 2015, "value":1463072},
{"name": 2016, "value":1263770},
{"name": 2017, "value":1224573},
{"name": 2018, "value":1170526}
], "farm": [
{"name": 2014, "value": 2242},
{"name": 2015, "value":2497},
{"name": 2016, "value":2061},
{"name": 2017, "value": 2230},
{"name": 2018, "value": 6580}
]},
{"name": "河南", "area": [
{"name": 2014, "value":762},
{"name": 2015, "value":1335},
{"name": 2016, "value":1289},
{"name": 2017, "value":15820},
{"name": 2018, "value":33709}
], "water": [
{"name": 2014, "value":868330},
{"name": 2015, "value":972600},
{"name": 2016, "value":895500},
{"name": 2017, "value":835250},
{"name": 2018, "value":875496}
], "farm": [
{"name": 2014, "value": 554},
{"name": 2015, "value":1347},
{"name": 2016, "value":1659},
{"name": 2017, "value": 7436},
{"name": 2018, "value": 19260}
]},
{"name": "湖北", "area": [
{"name": 2014, "value":192600},
{"name": 2015, "value":200863},
{"name": 2016, "value":253863},
{"name": 2017, "value":334890},
{"name": 2018, "value":393171}
], "water": [
{"name": 2014, "value":4124940},
{"name": 2015, "value":4367861},
{"name": 2016, "value":4518227},
{"name": 2017, "value":4361261},
{"name": 2018, "value":4402981}
], "farm": [
{"name": 2014, "value": 219866},
{"name": 2015, "value":256611},
{"name": 2016, "value":289592},
{"name": 2017, "value": 516984},
{"name": 2018, "value": 690722}
]},
{"name": "湖南", "area": [
{"name": 2014, "value":165616},
{"name": 2015, "value":171369},
{"name": 2016, "value":181934},
{"name": 2017, "value":221524},
{"name": 2018, "value":300148}
], "water": [
{"name": 2014, "value":2373876},
{"name": 2015, "value":2484837},
{"name": 2016, "value":2288600},
{"name": 2017, "value":2320384},
{"name": 2018, "value":2379514}
], "farm": [
{"name": 2014, "value": 69498},
{"name": 2015, "value":81388},
{"name": 2016, "value":98209},
{"name": 2017, "value": 190218},
{"name": 2018, "value": 298049}
]},
{"name": "广东", "area": [
{"name": 2014, "value":3375},
{"name": 2015, "value":3364},
{"name": 2016, "value":3038},
{"name": 2017, "value":3293},
{"name": 2018, "value":3643}
], "water": [
{"name": 2014, "value":3731574},
{"name": 2015, "value":3865638},
{"name": 2016, "value":3646338},
{"name": 2017, "value":3696884},
{"name": 2018, "value":3817456}
], "farm": [
{"name": 2014, "value": 2808},
{"name": 2015, "value":2440},
{"name": 2016, "value":2300},
{"name": 2017, "value": 2920},
{"name": 2018, "value": 1674}
]},
{"name": "广西", "area": [
{"name": 2014, "value":45155},
{"name": 2015, "value":45415},
{"name": 2016, "value":46344},
{"name": 2017, "value":47670},
{"name": 2018, "value":45414}
], "water": [
{"name": 2014, "value":1444993},
{"name": 2015, "value":1523681},
{"name": 2016, "value":1128329},
{"name": 2017, "value":1184068},
{"name": 2018, "value":1282698}
], "farm": [
{"name": 2014, "value": 15716},
{"name": 2015, "value":16900},
{"name": 2016, "value":18329},
{"name": 2017, "value": 19929},
{"name": 2018, "value": 25275}
]},
{"name": "海南", "area": [
{"name": 2014, "value":0},
{"name": 2015, "value":0},
{"name": 2016, "value":0},
{"name": 2017, "value":0},
{"name": 2018, "value":69}
], "water": [
{"name": 2014, "value":462111},
{"name": 2015, "value":405869},
{"name": 2016, "value":347905},
{"name": 2017, "value":345751},
{"name": 2018, "value":366861}
], "farm": [
{"name": 2014, "value": 0},
{"name": 2015, "value":0},
{"name": 2016, "value":0},
{"name": 2017, "value": 0},
{"name": 2018, "value": 212}
]},
{"name": "重庆", "area": [
{"name": 2014, "value":37345},
{"name": 2015, "value":36785},
{"name": 2016, "value":34271},
{"name": 2017, "value":33719},
{"name": 2018, "value":35295}
], "water": [
{"name": 2014, "value":423076},
{"name": 2015, "value":460505},
{"name": 2016, "value":470917},
{"name": 2017, "value":496187},
{"name": 2018, "value":510746}
], "farm": [
{"name": 2014, "value": 8351},
{"name": 2015, "value":8332},
{"name": 2016, "value":8249},
{"name": 2017, "value": 8177},
{"name": 2018, "value": 9376}
]},
{"name": "四川", "area": [
{"name": 2014, "value":306928},
{"name": 2015, "value":308938},
{"name": 2016, "value":308529},
{"name": 2017, "value":309643},
{"name": 2018, "value":312230}
], "water": [
{"name": 2014, "value":1266189},
{"name": 2015, "value":1327202},
{"name": 2016, "value":1364653},
{"name": 2017, "value":1453613},
{"name": 2018, "value":1489358}
], "farm": [
{"name": 2014, "value": 310612},
{"name": 2015, "value":330956},
{"name": 2016, "value":350853},
{"name": 2017, "value": 377784},
{"name": 2018, "value": 383431}
]},
{"name": "贵州", "area": [
{"name": 2014, "value":151009},
{"name": 2015, "value":153126},
{"name": 2016, "value":125550},
{"name": 2017, "value":121055},
{"name": 2018, "value":119624}
], "water": [
{"name": 2014, "value":196040},
{"name": 2015, "value":235860},
{"name": 2016, "value":234900},
{"name": 2017, "value":243262},
{"name": 2018, "value":226382}
], "farm": [
{"name": 2014, "value": 36005},
{"name": 2015, "value":43977},
{"name": 2016, "value":37494},
{"name": 2017, "value": 41626},
{"name": 2018, "value": 45581}
]},
{"name": "云南", "area": [
{"name": 2014, "value":113417},
{"name": 2015, "value":111392},
{"name": 2016, "value":112544},
{"name": 2017, "value":112349},
{"name": 2018, "value":111947}
], "water": [
{"name": 2014, "value":535132},
{"name": 2015, "value":638960},
{"name": 2016, "value":548206},
{"name": 2017, "value":575233},
{"name": 2018, "value":606376}
], "farm": [
{"name": 2014, "value": 41569},
{"name": 2015, "value":48553},
{"name": 2016, "value":42739},
{"name": 2017, "value": 48068},
{"name": 2018, "value": 64543}
]},
{"name": "西藏", "area": [
{"name": 2014, "value":0},
{"name": 2015, "value":0},
{"name": 2016, "value":0},
{"name": 2017, "value":0},
{"name": 2018, "value":0}
], "water": [
{"name": 2014, "value":61},
{"name": 2015, "value":61},
{"name": 2016, "value":80},
{"name": 2017, "value":71},
{"name": 2018, "value":43}
], "farm": [
{"name": 2014, "value": 0},
{"name": 2015, "value":0},
{"name": 2016, "value":0},
{"name": 2017, "value": 0},
{"name": 2018, "value": 0}
]},
{"name": "陕西", "area": [
{"name": 2014, "value":859},
{"name": 2015, "value":3147},
{"name": 2016, "value":3155},
{"name": 2017, "value":3155},
{"name": 2018, "value":3155}
], "water": [
{"name": 2014, "value":133320},
{"name": 2015, "value":147960},
{"name": 2016, "value":151780},
{"name": 2017, "value":155830},
{"name": 2018, "value":155835}
], "farm": [
{"name": 2014, "value": 170},
{"name": 2015, "value":174},
{"name": 2016, "value":160},
{"name": 2017, "value": 160},
{"name": 2018, "value": 160}
]},
{"name": "甘肃", "area": [
{"name": 2014, "value":0},
{"name": 2015, "value":6},
{"name": 2016, "value":2},
{"name": 2017, "value":3},
{"name": 2018, "value":0}
], "water": [
{"name": 2014, "value":14476},
{"name": 2015, "value":14932},
{"name": 2016, "value":15333},
{"name": 2017, "value":15441},
{"name": 2018, "value":14136}
], "farm": [
{"name": 2014, "value": 1},
{"name": 2015, "value":1},
{"name": 2016, "value":1},
{"name": 2017, "value": 1},
{"name": 2018, "value": 1}
]},
{"name": "青海", "area": [
{"name": 2014, "value":0},
{"name": 2015, "value":0},
{"name": 2016, "value":0},
{"name": 2017, "value":0},
{"name": 2018, "value":0}
], "water": [
{"name": 2014, "value":9037},
{"name": 2015, "value":10578},
{"name": 2016, "value":12050},
{"name": 2017, "value":16073},
{"name": 2018, "value":17116}
], "farm": [
{"name": 2014, "value": 0},
{"name": 2015, "value":0},
{"name": 2016, "value":0},
{"name": 2017, "value": 0},
{"name": 2018, "value": 0}
]},
{"name": "宁夏", "area": [
{"name": 2014, "value":11387},
{"name": 2015, "value":4797},
{"name": 2016, "value":2890},
{"name": 2017, "value":1757},
{"name": 2018, "value":2166}
], "water": [
{"name": 2014, "value":162244},
{"name": 2015, "value":169335},
{"name": 2016, "value":174175},
{"name": 2017, "value":180460},
{"name": 2018, "value":176555}
], "farm": [
{"name": 2014, "value": 1871},
{"name": 2015, "value":697},
{"name": 2016, "value":371},
{"name": 2017, "value": 505},
{"name": 2018, "value": 897}
]},
{"name": "新疆", "area": [
{"name": 2014, "value":0},
{"name": 2015, "value":0},
{"name": 2016, "value":496},
{"name": 2017, "value":858},
{"name": 2018, "value":300}
], "water": [
{"name": 2014, "value":130881},
{"name": 2015, "value":140567},
{"name": 2016, "value":147666},
{"name": 2017, "value":152805},
{"name": 2018, "value":160302}
], "farm": [
{"name": 2014, "value": 0},
{"name": 2015, "value":30},
{"name": 2016, "value":58},
{"name": 2017, "value": 38},
{"name": 2018, "value": 51}
]}
]
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment