Commit 7ba377a8 authored by zengyilun's avatar zengyilun

添加文件

parents
# svi-cli Backstage Template
> 公共后台运维模板,提供给svi-cli脚手架获取.
## Usage / 用法
``` bash
$ npm install -g svi-cli
$ svi init backstage my-project
$ cd my-project
$ npm install
$ npm run dev
```
## Have / 拥有功能
**Menu Tree / 菜单树**
>serviceMonitor __服务监测__
>> serviceAccess _服务访问统计_
>> onlineMonitor _在线监控_
>
>serviceManage __服务管理__
>> resourceCatalog _资源目录管理_
>> serviceRegistration _服务注册申请_
>> serviceApproval _服务注册审批_
>> applicationApproval _平台服务申请审批_
>
>systemsafety __系统安全__
>> userManagement _用户管理_
>> functionManagement _角色管理_
>> systemManagement _系统模块管理_
>
>systemMonitor __系统监控__
>> clickCount _流量统计_
>> systemLog _系统日志_
>
>serverMonitor __服务器监控__
>> serverList _主机监控_
>> monitorChart _监控图表_
>> alarmRules _报警规则_
>> alarmHistory _报警历史_
\ No newline at end of file
module.exports = {
renderFiles: [
'package.json',
'README.md',
'src/router/index.js',
'src/store/index.js',
'src/api/index.js'
],
filters: {
serviceMonitor: {
'vue': 'src/views/ServiceMonitor/**/*',
'router': 'src/router/serviceMonitor.js',
'api': 'src/api/serviceMonitor.js',
'store': ''
},
serviceManage: {
'vue': 'src/views/ServiceManage/**/*',
'router': 'src/router/serviceManage.js',
'api': 'src/api/serviceManage.js',
'store': ''
},
systemMonitor: {
'vue': 'src/views/SystemMonitor/**/*',
'router': 'src/router/systemMonitor.js',
'api': 'src/api/systemMonitor.js',
'store': ''
},
serverMonitor: {
'vue': 'src/views/ServerMonitor/**/*',
'router': 'src/router/serverMonitor.js',
'api': 'src/api/serverMonitor.js',
'store': ''
}
},
prompts: {
name: {
type: 'string',
required: true,
message: 'Project name'
},
description: {
type: 'string',
required: false,
message: 'Project description',
default: 'A vuejs backstage project',
},
author: {
type: 'string',
message: 'Author'
},
serviceManage: {
type: 'confirm',
message: '是否安装包含【服务管理】模块'
},
serviceMonitor: {
type: 'confirm',
message: '是否安装包含【服务监测】模块'
},
systemMonitor: {
type: 'confirm',
message: '是否安装包含【系统监控】模块'
},
serverMonitor: {
type: 'confirm',
message: '是否安装包含【服务器监控】模块'
}
}
}
\ No newline at end of file
{
"name": "backstage",
"version": "0.0.1",
"description": "a svi CLI backstage template.",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"template"
],
"author": "PolanZ",
"license": "MIT"
}
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": [
"transform-vue-jsx",
"transform-runtime",
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
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
/src/utils/
// 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',
'standard'
],
// required to lint *.vue files
plugins: [
'vue'
],
// add your custom rules here
rules: {
// allow async-await
'generator-star-spacing': 'off',
// 缩进忽略
'indent': 'off',
// 忽略\在正则字符串使用
'no-useless-escape': 'off',
// 变量var let const忽略
'no-unused-vars': 'off',
'one-var': 'off',
'no-trailing-spaces': 'off',
// 最多可以空两行(在块里允许开始结束空行)
'no-multiple-empty-lines': ['error', {
'max': 2,
'maxBOF': 1,
'maxEOF': 1
}],
'no-multi-spaces': ['error', {
'ignoreEOLComments': true,
'exceptions': {
'Property': true,
'VariableDeclarator': true,
'ImportDeclaration': true
}
}],
'no-unused-expressions': ['error', {
'allowShortCircuit': true,
'allowTernary': true,
'allowTaggedTemplates': true
}],
// 字符串用单引号
'quotes': ['error', 'single', {
'avoidEscape': true,
'allowTemplateLiterals': true
}],
// 不允许使用分号结束
'semi': ['error', 'never'],
// 函数前空格忽略
'space-before-function-paren': 'off',
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
}
}
.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": {}
}
}
# {{ name }}
> {{ description }}
## 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
```
'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: '../../', // 解决CSS引入静态资源
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
const output = []
const loaders = exports.cssLoaders(options)
for (const extension in loaders) {
const loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
exports.createNotifierCallback = () => {
const notifier = require('node-notifier')
return (severity, errors) => {
if (severity !== 'error') return
const error = errors[0]
const filename = error.file && error.file.split('!').pop()
notifier.notify({
title: packageConfig.name,
message: severity + ': ' + error.name,
subtitle: filename || '',
icon: path.join(__dirname, 'logo.png')
})
}
}
'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: './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'),
}
},
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
'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 env = require('../config/prod.env')
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
'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: 8030, // 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"'
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>运维管理系统</title>
<link rel="stylesheet" href="static/iconfont/iconfont.css">
<link rel="stylesheet" href="//at.alicdn.com/t/font_416347_866yvgagefsnstt9.css">
<script src="static/iconfont/iconfont.js"></script>
</head>
<body class="global">
<div id="app"></div>
<script type="text/javascript" src="./static/js/global.js"></script>
<!-- built files will be auto injected -->
</body>
</html>
{
"name": "{{ name }}",
"version": "1.0.0",
"description": "{{ description }}",
"author": "{{ author }}",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"lint": "eslint --ext .js,.vue src",
"build": "node build/build.js"
},
"dependencies": {
{{#serviceMonitor}}
"echarts": "^3.2.3",
{{/serviceMonitor}}
"axios": "^0.18.0",
"base-64": "^0.1.0",
"element-ui": "^2.3.2",
"esri-loader": "^1.0.0",
"vue": "^2.5.2",
"vue-progressbar": "^0.7.5",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-eslint": "^8.2.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.1",
"babel-plugin-component": "^1.1.0",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"eslint": "^4.15.0",
"eslint-config-standard": "^10.2.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.2.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-vue": "^4.0.0",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"node-notifier": "^5.1.2",
"node-sass": "^4.8.3",
"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",
"sass-loader": "^6.0.7",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"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">
<vue-progress-bar></vue-progress-bar>
<app-header v-if="headerOnoff" @user-center="userCenter"></app-header>
<!-- <modify-pass v-if="modifyOnoff" @close-handle="closeHandle"></modify-pass> -->
<user-center v-if="modifyOnoff" @close-handle="closeHandle"></user-center>
<app-home :header-onoff="headerOnoff"></app-home>
<!-- <router-view></router-view> -->
</div>
</template>
<script>
import appHeader from '@/components/Header.vue'
// import modifyPass from '@/components/ModifyPass.vue'
import appHome from './pages/Home.vue'
import userCenter from '@/components/UserCenter.vue'
export default {
name: 'App',
data () {
return {
headerOnoff: true,
modifyOnoff: false
}
},
components: {
appHeader,
appHome,
// modifyPass,
userCenter
},
computed: {
sideMenu() {
return this.$store.state.sideMenu
}
},
mounted () {
this.$Progress.finish()
if (this.$route.path === '/login' || this.$route.path === '/404' || this.$route.path === '/permission') {
this.headerOnoff = false
} else {
this.headerOnoff = true
}
},
created () {
// [App.vue specific] When App.vue is first loaded start the progress bar
this.$Progress.start()
// hook the progress bar to start before we move router-view
this.$router.beforeEach((to, from, next) => {
// does the page we want to go to have a meta.progress object
if (to.meta.progress !== undefined) {
let meta = to.meta.progress
// parse meta tags
this.$Progress.parseMeta(meta)
}
// start the progress bar
this.$Progress.start()
// continue to next page
next()
})
// hook the progress bar to finish after we've finished moving router-view
this.$router.afterEach((to, from) => {
// finish the progress bar
this.$Progress.finish()
// let router = Object.assign({}, {'name': to.fullPath})
let router = new URLSearchParams()
let userid = null
if (window.localStorage.gisopUserInfo) {
const storageUser = JSON.parse(window.localStorage.gisopUserInfo)
userid = storageUser.info.userguid
}
router.append('pageurl', to.fullPath)
router.append('userguid', userid)
for (let i = 0; i < this.sideMenu.length; i++) {
if (to.fullPath === this.sideMenu[i].pageurl) {
router.append('moduleName', this.sideMenu[i].modulename)
}
}
})
},
watch: {
$route (val) {
if (val.path === '/login' || this.$route.path === '/404' || this.$route.path === '/permission') {
this.headerOnoff = false
} else {
this.headerOnoff = true
}
}
},
methods: {
// 打开设置密码
userCenter () {
this.modifyOnoff = true
},
// 关闭设置密码
closeHandle () {
this.modifyOnoff = false
}
}
}
</script>
<style lang="scss">
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
color: #1f2d3d;
/* .sidebar {
display: flex;
width: 200px;
height: 100%;
overflow: auto;
} */
.container {
display: flex;
flex-direction: column;
flex: 1;
overflow: hidden;
}
.containerIn {
display: flex;
flex-direction: column;
flex: 1;
}
.el-dialog__header {
position: relative;
.close {
width: 30px;
height: 30px;
position: absolute;
right: 20px;
top: 10px;
cursor: pointer;
color: #666;
}
}
}
</style>
import axios from 'axios'
// 携带cookie信息
axios.defaults.withCredentials = true
// 设置全局的请求次数,请求的间隙
axios.defaults.retry = 4
axios.defaults.retryDelay = 1000
// 请求超时拦截,重新请求
axios.interceptors.response.use(undefined, function axiosRetryInterceptor (err) {
var config = err.config
// If config does not exist or the retry option is not set, reject
if (!config || !config.retry) return Promise.reject(err)
// Set the variable for keeping track of the retry count
config.__retryCount = config.__retryCount || 0
// Check if we've maxed out the total number of retries
if (config.__retryCount >= config.retry) {
// Reject with the error
return Promise.reject(err)
}
// Increase the retry count
config.__retryCount += 1
// Create new promise to handle exponential backoff
var backoff = new Promise(function (resolve) {
setTimeout(function () {
resolve()
}, config.retryDelay || 1)
})
// Return the promise in which recalls axios to retry the request
return backoff.then(function () {
return axios(config)
})
})
// API_ROOT in .pubtrc.js
// let root = process.env.NODE_ENV === 'production' ? '{{ API_ROOT }}' : '172.16.10.132:8010'
let root = '172.16.10.132:8010'
let url = 'http://' + root
const config = {
url: url,
gisAnalyzeUrl: url + '/Gis_V2/Gis_analyze', // 服务监测
gisServiceUrl: url + '/Gis_V2/Gis_service', // 服务管理
gisSystemUrl: url + '/Gis_V2/Gis', // 系统安全
gisSysCommon: url + '/Gis_V2/Gis_SysCommon', // 系统监控
gisSerCommon: url + '/monitor', // 服务器监控
// 旧接口
maintenanceUrl: url + '/maintenance',
// 在线监控
wsUrl: 'ws://' + root + '/Gis_V2/webSocket'
}
export default config
import axios from 'axios'
import config from './config'
{{#serviceMonitor}}
import serviceMonitor from './serviceMonitor'
{{/serviceMonitor}}
{{#serviceManage}}
import serviceManage from './serviceManage'
{{/serviceManage}}
{{#systemMonitor}}
import systemMonitor from './systemMonitor'
{{/systemMonitor}}
{{#serverMonitor}}
import serverMonitor from './serverMonitor'
{{/serverMonitor}}
{{#systemSafety}}
import systemSafety from './systemSafety'
{{/systemSafety}}
const CancelToken = axios.CancelToken
const maintenanceApi = config.maintenanceUrl
const wsUrl = config.wsUrl
const Api = {
maintenanceApi: maintenanceApi,
wsUrl: wsUrl,
_doGetPromise (url, params, options) {
const timeout = options && options.timeout ? options.timeout : 60000
return new Promise((resolve, reject) => {
axios.get(url, {
timeout: timeout,
params: params,
cancelToken: new CancelToken(function executor (c) {
})
}).then(response => {
resolve(response.data)
}).catch(response => {
console.error('ajax error:', response)
reject(response)
})
})
},
_doPostPromise (url, formData) {
return new Promise((resolve, reject) => {
axios.post(url, formData, {
emulateJSON: false,
emulateHTTP: false
}).then(res => {
resolve(res.data)
}).catch(res => {
console.log('post error:', res)
reject(res)
})
})
},
{{#serviceMonitor}}
/* --------------服务监控----------- */
...serviceMonitor,
{{/serviceMonitor}}
{{#serviceManage}}
/* --------------服务管理----------- */
...serviceManage,
{{/serviceManage}}
{{#systemMonitor}}
/* --------------系统监控----------- */
...systemMonitor,
{{/systemMonitor}}
{{#serverMonitor}}
/* --------------服务器监控----------- */
...serverMonitor,
{{/serverMonitor}}
/* --------------系统安全----------- */
...systemSafety,
// 图层管理——模块树
getAllZtree () {
return this._doPostPromise(maintenanceApi + '/LayerService/getAllZtree', {})
},
// 图层管理——修改
updateLayerInfo (layerId, layerCode, layerName, layerUrl, layerType, layerDefinitions) {
return this._doPostPromise(maintenanceApi + '/LayerService/updateLayerInfo', {
layerId: layerId,
layerCode: layerCode,
layerName: layerName,
layerUrl: layerUrl,
layerType: layerType,
layerDefinitions: layerDefinitions
})
},
// 图层管理——删除
delLayer (layerId) {
return this._doPostPromise(maintenanceApi + '/LayerService/delLayer', {
layerId: layerId
})
},
// 图层管理——增加分类、增加图层
saveLayerInfo (pid, type, layerCode, layerName, layerUrl, layerType, layerDefinitions) {
return this._doPostPromise(maintenanceApi + '/LayerService/saveLayerInfo', {
pid: pid,
type: type,
layerCode: layerCode,
layerName: layerName,
layerUrl: layerUrl,
layerType: layerType,
layerDefinitions: layerDefinitions
})
}
}
export default Api
import config from './config'
const gisSerCommon = config.gisSerCommon
export default {
// 服务器列表
getselectServersByPage (index, pageSize) {
return this._doGetPromise(gisSerCommon + '/serverinfo/selectServersByPage', {
index: index,
pageSize: pageSize
})
},
/* --------------监控图表----------- */
// 查询CPU使用率
getSelectCpuInfo (flag, timefrom, timeto) {
return this._doGetPromise(gisSerCommon + '/cpuinfo/selectCpuInfo', {
flag: flag,
timefrom: timefrom,
timeto: timeto
})
},
// 查询CPU使用率
getSelectMemoryInfo (flag, timefrom, timeto) {
return this._doGetPromise(gisSerCommon + '/memoryinfo/selectMemoryInfo', {
flag: flag,
timefrom: timefrom,
timeto: timeto
})
},
// 查询磁盘名称
getDisksName (flag, timefrom, timeto) {
return this._doGetPromise(gisSerCommon + '/diskinfo/getDisksName', {
flag: flag,
timefrom: timefrom,
timeto: timeto
})
},
// 查询磁盘使用率
getSelectDiskInfo (flag, timefrom, timeto, diskname) {
return this._doGetPromise(gisSerCommon + '/diskinfo/selectDiskInfo', {
flag: flag,
timefrom: timefrom,
timeto: timeto,
diskname: diskname
})
},
// 查询网络名称
getNetsName (flag, timefrom, timeto) {
return this._doGetPromise(gisSerCommon + '/netinfo/getNetsName', {
flag: flag,
timefrom: timefrom,
timeto: timeto
})
},
// 查询网络情况
getSelectNetInfo (flag, timefrom, timeto, netname) {
return this._doGetPromise(gisSerCommon + '/netinfo/selectNetInfo', {
flag: flag,
timefrom: timefrom,
timeto: timeto,
netname: netname
})
},
// 查询Tcp连接数
getSelectTcpInfo (flag, timefrom, timeto) {
return this._doGetPromise(gisSerCommon + '/tcpinfo/selectTcpInfo', {
flag: flag,
timefrom: timefrom,
timeto: timeto
})
},
// 进程监控
getSelectProcessInfo (flag, timefrom, timeto) {
return this._doGetPromise(gisSerCommon + '/processinfo/selectProcessInfo', {
flag: flag,
timefrom: timefrom,
timeto: timeto
})
},
/* --------------报警规则----------- */
// 查询报警项目规则
getAlarmItem () {
return this._doGetPromise(gisSerCommon + '/alarmrule/getAlarmItem')
},
// 查询主机名称
getServersItem () {
return this._doGetPromise(gisSerCommon + '/serverinfo/getServersItem')
},
// 查询报警规则列表
getselectRuleByPage (index, pageSize, hostid) {
return this._doGetPromise(gisSerCommon + '/alarmrule/selectRuleByPage', {
index: index,
pagesize: pageSize,
hostid: hostid
})
},
// 提交报警规则表单
getAlarmRulesSubmit (formData) {
return this._doPostPromise(gisSerCommon + '/alarmrule/insertAlarmRule', formData)
},
// 查看报警规则
getRuleByID (ruleid) {
return this._doGetPromise(gisSerCommon + '/alarmrule/getRuleByID', {
ruleid: ruleid
})
},
// 修改报警规则
updateRule (formData) {
return this._doPostPromise(gisSerCommon + '/alarmrule/updateRule', formData)
},
// 单条报警规则删除
deleteRule (ruleid) {
return this._doGetPromise(gisSerCommon + '/alarmrule/deleteRule', {
ruleid: ruleid
})
},
// 批量删除规则
deleteRuleBatch (ruleids) {
return this._doGetPromise(gisSerCommon + '/alarmrule/deleteRuleBatch', {
ruleids: ruleids
})
},
// 报警历史列表
selectHistoryByPage (index, pageSize, ruleid, rulename, createtime, createtimeto, flag) {
return this._doGetPromise(gisSerCommon + '/alarmhistory/selectHistoryByPage', {
index: index,
pageSize: pageSize,
ruleid: ruleid,
rulename: rulename,
createtime: createtime,
createtimeto: createtimeto,
flag: flag
})
}
}
import config from './config'
const gisServiceUrl = config.gisServiceUrl
export default {
// 服务访问统计———单个服务目录树
getdirectoryAndServicesTree (directoryid) {
return this._doGetPromise(gisServiceUrl + '/getdirectoryAndServicesTree', {
directoryid: directoryid
})
},
// 在线监控——60s
getOnlineMonitor60s () {
return this._doGetPromise(gisServiceUrl + '/getRedisLogsCount_60s', {})
},
/* --------------服务管理------------ */
// 资源目录管理——获取目录树
getCatalogTree () {
return this._doGetPromise(gisServiceUrl + '/getDirectoryTree', {})
},
// 资源目录管理——新建目录节点
saveCatalogService (formData) {
return this._doPostPromise(gisServiceUrl + '/saveDirectory', formData)
},
// 资源目录管理——修改目录节点
editCatalog (formData) {
return this._doPostPromise(gisServiceUrl + '/updateDirectoryData', formData)
},
// 资源目录管理——删除目录节点
deleteCatalog (ids) {
return this._doGetPromise(gisServiceUrl + '/deleteDirectoryData', {
ids: ids
})
},
// 服务注册——列表查询
getManageRegisterService (index, pageSize, name, directoryid, auditstatus, sdate, edate) {
return this._doGetPromise(gisServiceUrl + '/getServicePage', {
index: index,
pageSize: pageSize,
name: name,
directoryid: directoryid,
auditstatus: auditstatus,
sdate: sdate,
edate: edate
})
},
// 服务注册——表单里删除行操作
deleteManageRegisterService (ids) {
return this._doGetPromise(gisServiceUrl + '/deleteServiceData', {
ids: ids
})
},
// 服务注册——注册
registerManageRegisterService (formData) {
return this._doPostPromise(gisServiceUrl + '/saveService', formData)
},
// 服务注册——点击修改显示内容
showManageRegisterService (entityid) {
return this._doGetPromise(gisServiceUrl + '/showServiceData', {
entityid: entityid
})
},
// 服务注册——修改
editManageRegisterService (formData) {
return this._doPostPromise(gisServiceUrl + '/updateServiceData', formData)
},
// 服务申请审批——列表查询
getApplicationApprovalList (index, pageSize, name, directoryid, auditstatus, sdate, edate, userid) {
return this._doGetPromise(gisServiceUrl + '/getServiceApplyPage', {
index: index,
pageSize: pageSize,
name: name,
directoryid: directoryid,
auditstatus: auditstatus,
sdate: sdate,
edate: edate,
userid: userid
})
},
// 服务申请审批——审批状态
editApplicationApprovalService (formData) {
return this._doPostPromise(gisServiceUrl + '/auditServiceApply', formData)
},
// 服务申请审批——删除
deleteApplicatApprovalService (ids) {
return this._doGetPromise(gisServiceUrl + '/deleteServiceApplyData', {
ids: ids
})
},
// 服务申请审批——查看详细信息
getMoreInformation (entityid, id) {
return this._doGetPromise(gisServiceUrl + '/showServiceApplyData', {
entityid: entityid,
id: id
})
}
}
import config from './config'
const gisAnalyzeUrl = config.gisAnalyzeUrl
export default {
// 服务访问统计——服务访问总数
getServicesCount () {
return this._doGetPromise(gisAnalyzeUrl + '/getServicesCount', {})
},
// 服务访问统计——请求成功和响应失败
getAnalyzeValue (name) {
return this._doGetPromise(gisAnalyzeUrl + '/getAnalyzeValue', {
name: name
})
},
// 服务访问统计——接入系统数
getSysCount () {
return this._doGetPromise(gisAnalyzeUrl + '/getSysCount', {})
},
// 服务访问统计——每天服务访问总量 getAnalyzeList?name=ALLNUM&catalogtype=0&date=20180410
getAccessStTotal (name, catalogtype, sdate, edate) {
return this._doGetPromise(gisAnalyzeUrl + '/getAnalyzeList', {
name: name,
catalogtype: catalogtype,
sdate: sdate,
edate: edate
})
},
// 服务访问统计——访问量前10的服务
getAccessStTop10service (name, sdate, edate) {
return this._doGetPromise(gisAnalyzeUrl + '/getAnalyzeTop_Num', {
name: name,
sdate: sdate,
edate: edate
})
},
// 服务访问统计——单个服务访问总量
getAnalyzeSingleServiceNum (sdate, edate, serviceid) {
return this._doGetPromise(gisAnalyzeUrl + '/getAnalyzeSingleServiceNum', {
sdate: sdate,
edate: edate,
serviceid: serviceid
})
},
// 服务访问统计——单个服务访问耗时
getAnalyzeSingleServiceTime (sdate, edate, serviceid) {
return this._doGetPromise(gisAnalyzeUrl + '/getAnalyzeSingleServiceTime', {
sdate: sdate,
edate: edate,
serviceid: serviceid
})
},
// 服务访问统计——应用系统
getAppTotalaccessbyTime (sdate, edate) {
return this._doGetPromise(gisAnalyzeUrl + '/getAnalyzeSys_Num', {
sdate: sdate,
edate: edate
})
}
}
import config from './config'
const gisSysCommon = config.gisSysCommon
export default {
// 系统日志
getSystemLogByPage (currentPage, pageSize, logLevel, stime, etime) {
return this._doGetPromise(gisSysCommon + '/getSystemLogByPage', {
currentPage: currentPage,
pageSize: pageSize,
logLevel: logLevel,
stime: stime,
etime: etime
})
},
// 流量统计
getClickStatisticsSum (stime, etime) {
return this._doGetPromise(gisSysCommon + '/getClickStatisticSum', {
stime: stime,
etime: etime
})
},
// 查询点pv每天总量
getClickStatisticNumByDate (stime, etime) {
return this._doGetPromise(gisSysCommon + '/getClickStatisticNumByDate', {
stime: stime,
etime: etime
})
},
// 查询点pv前10
getClickStatisticTop10 (stime, etime) {
return this._doGetPromise(gisSysCommon + '/getClickStatisticTop10', {
stime: stime,
etime: etime
})
}
}
import config from './config'
const gisSystemUrl = config.gisSystemUrl
export default {
/* --------------登录接口------------ */
getLoginApi (name, pwd) {
return this._doGetPromise(gisSystemUrl + '/checkuser', {
name: name,
pwd: pwd
})
},
// 判断token是否失效
getLoginIsTimeout (token) {
return this._doGetPromise(gisSystemUrl + '/checkuserOnline', {
token: token
})
},
// 修改密码
modifyUserPassword (userguid, sourcePwd, targetPwd) {
return this._doGetPromise(gisSystemUrl + '/modifyUserPassword', {
userguid: userguid,
source_pwd: sourcePwd,
target_pwd: targetPwd
})
},
// 用户管理——机构树
getOrganTree () {
return this._doGetPromise(gisSystemUrl + '/getOrganTree', {})
},
// 用户管理——添加机构
saveOrganInfo (formData) {
return this._doPostPromise(gisSystemUrl + '/saveOrganInfo', formData)
},
// 用户管理——修改机构
updateOrganData (formData) {
return this._doPostPromise(gisSystemUrl + '/updateOrganData', formData)
},
// 用户管理——删除机构
deleteOrganData (ids) {
return this._doGetPromise(gisSystemUrl + '/deleteOrganData', {
ids: ids
})
},
// 用户管理——查询机构详情
showOrganData (entityid) {
return this._doGetPromise(gisSystemUrl + '/showOrganData', {
entityid: entityid
})
},
// 用户管理——列表查询
getUserServiceList (index, pagesize, regionid, loginname, status) {
return this._doGetPromise(gisSystemUrl + '/getUserPage', {
index: index,
pagesize: pagesize,
regionid: regionid,
loginname: loginname,
status: status
})
},
// 用户管理——添加用户
addUserService (formData) {
return this._doPostPromise(gisSystemUrl + '/saveUserInfo', formData)
},
// 用户管理——展示用户
showUserData (entityid) {
return this._doGetPromise(gisSystemUrl + '/showUserData', {
entityid: entityid
})
},
// 用户管理——修改用户
editUserService (formData) {
return this._doPostPromise(gisSystemUrl + '/updateUserData', formData)
},
// 用户管理——删除用户
deleteUserService (ids) {
return this._doGetPromise(gisSystemUrl + '/deleteData', {
ids: ids
})
},
// 用户管理——获取用户的角色
getRoleSelect (userid, roletype) {
return this._doGetPromise(gisSystemUrl + '/getRoleofuser', {
userid: userid,
roletype: roletype
})
},
// 用户管理——保存用户或机构与角色关系
saveRoleRelaOpr (userid, roleid) {
return this._doGetPromise(gisSystemUrl + '/saveRoleUserRelaOpr', {
userid: userid,
roleid: roleid
})
},
// 角色管理——获取角色列表
getRoleViewList (index, pagesize, rolename, roletype, showType) {
return this._doGetPromise(gisSystemUrl + '/getRolePage', {
index: index,
pagesize: pagesize,
rolename: rolename,
roletype: roletype,
showType: showType
})
},
// 角色管理——添加角色
saveRole (formData) {
return this._doPostPromise(gisSystemUrl + '/saveRoleInfo', formData)
},
// 角色管理——修改角色
editRole (formData) {
return this._doPostPromise(gisSystemUrl + '/updateRoleData', formData)
},
// 角色管理——删除角色
deleteRole (ids) {
return this._doGetPromise(gisSystemUrl + '/deleteRoleData', {
ids: ids
})
},
// 角色管理——功能目录树
getAllCatalog (userid, roletype) {
return this._doGetPromise(gisSystemUrl + '/getModuleTree', {
userid: userid,
roletype: roletype
})
},
// 角色管理——选中功能角色权限
getAllRoleMoudle (roleid, roletype) {
return this._doGetPromise(gisSystemUrl + '/getModuleOfRoles', {
roleid: roleid,
roletype: roletype
})
},
// 系统模块管理——模块树
getTree (userId, roletype) {
return this._doGetPromise(gisSystemUrl + '/getModuleTree', {
userId: userId,
roletype: roletype
})
},
// 角色管理——保存选中功能角色权限
savePermiss (roleid, moduleid) {
return this._doGetPromise(gisSystemUrl + '/saveModuleRoleRelaOpr', {
roleid: roleid,
moduleid: moduleid
})
},
// 系统模块管理——展示数据
showModuleData (entityid) {
return this._doGetPromise(gisSystemUrl + '/showModuleData', {
entityid: entityid
})
},
// 系统模块管理——新建保存
saveMoudle (formData) {
return this._doPostPromise(gisSystemUrl + '/saveModuleInfo', formData)
},
// 系统模块管理——编辑模块
updateMoudle (formData) {
return this._doPostPromise(gisSystemUrl + '/updateModuleData', formData)
},
// 系统模块管理——删除模块
checkDeleteMoudle (ids) {
return this._doGetPromise(gisSystemUrl + '/deleteModuleData', {
ids: ids
})
}
}
@import 'reset.css';
body {
min-width: 1200px;
overflow-x: auto;
overflow-y: auto;
}
/* header */
.header {
display: flex;
align-items: center;
width: 100%;
height: 50px;
background: #fff;
box-sizing: border-box;
.title {
width: 220px;
height: 100%;
float: left;
background-color: #353d48;
transition: background .25s ease-in-out;
&.is-collapse {
background-color: #ffffff;
border-bottom: 1px solid #dfdfe1;
}
.icon-menu {
float: left;
width: 64px;
height: 50px;
line-height: 50px;
text-align: center;
font-size: 18px;
color: #878d9d;
background-color: #353d48;
cursor: pointer;
}
> .logo {
float: right;
margin-right: 40px;
margin-top: 7px;
}
> a {
color: #fff;
font-size: 20px;
font-weight: bold;
line-height: 1;
vertical-align: middle;
}
}
.userImformation{
padding-left: 18px;
display: flex;
justify-content: space-between;
flex: 1;
border-bottom: solid 1px #dfdfe1;
height: 50px;
line-height: 50px;
.yunweiTitle {
font-size: 18px;
color: #363a3d;
}
.changePassword {
line-height: 34px;
font-size: 16px;
color: #fff;
cursor: pointer;
}
}
.user-info {
display: flex;
justify-content: flex-end;
align-items: center;
color: #fff;
margin-left: 40px;
margin-right: 12px;
.changeTheme {
padding: 0 10px;
}
.message {
width: 50px;
height: 49px;
text-align: center;
position: relative;
cursor: pointer;
i {
color: #878d9d;
font-size: 20px;
}
.dot {
width: 10px;
height: 10px;
background: #e02e43;
border-radius: 50%;
position: absolute;
right: 5px;
top: 5px;
}
}
.user-img {
width: 40px;
height: 40px;
border: solid 1px #acafb6;
padding: 1px;
color: #20a0ff;
text-align: center;
line-height: 42px;
cursor: pointer;
border-radius: 50%;
margin: 0 12px;
.user-imgIn {
width: 36px;
height: 36px;
border-radius: 50%;
overflow: hidden;
}
.iconfont {
font-size: 24px;
}
}
.user-more {
font-size: 16px;
margin-right: 8px;
font-weight: bold;
cursor: pointer;
i {
color: #86889d;
font-size: 20px;
}
/* .exit{
margin-left: 10px;
cursor: pointer;
font-weight: normal;
}
.el-dropdown-link {
color: #fff;
&:hover {
opacity: .85;
}
} */
}
}
.el-menu {
background: transparent !important;
border: 0 none;
}
}
.changeThemDialog {
.clr {
display: inline-block;
width: 14px;
height: 14px;
margin-right: 3px;
border: 1px solid #333;
vertical-align: middle;
}
}
/* 面包屑 */
.breadCrumb .el-breadcrumb__separator{
color: #747474;
}
/* 单选目录 */
.radioTree {
>.el-tree-node {
>.el-tree-node__content {
background: rgba(213, 212, 217, 0.1);
}
>.el-tree-node__children{
background: rgba(213, 212, 217, 0.1);
}
}
.el-tree-node__content {
&:hover {
background: #d8d8d8;
}
}
.el-checkbox {
margin-left: 10px;
float: left;
}
.el-tree-node__expand-icon {
float: right;
background: url('../img/right.png') no-repeat center center;
background-size: 70% auto;
width: 36px;
height: 36px;
padding: 0;
margin: 0;
border: none;
}
.el-tree-node__expand-icon.is-leaf {
border: none;
background: none;
}
.el-tree-node__label {
float: left;
}
}
/* 多选目录树 */
.multiselectTree {
.el-tree-node__content {
overflow: hidden;
line-height: 36px;
}
.el-tree-node__expand-icon {
float: right;
background: url('../img/right.png') no-repeat center center;
background-size: 70% auto;
width: 36px;
height: 36px;
padding: 0;
margin: 0;
border: none;
}
.el-tree-node__expand-icon.is-leaf {
border: none;
background: none;
}
.el-checkbox {
margin-left: 10px;
float: left;
}
.el-tree-node__label {
float: left;
}
}
/* 弹窗 */
.el-dialog__header{
text-align: center;
}
.el-dialog__footer{
text-align: center;
}
/* 查询项的样式 */
.searchCommon {
.el-form-item__label {
/* border: solid 1px #8dc9c7; */
border-radius: 4px 0 0 4px;
height: 40px;
box-sizing: border-box;
padding: 0 10px;
border: solid 1px #d5d4d9;
border-right: none;
}
.el-input__inner {
border-radius: 0 4px 4px 0;
}
.select .el-input__inner {
border-left: solid 1px #8dc9c7;
border-radius: 4px;
}
}
/* 范围时间样式 */
.el-time-range-picker {
min-width: 220px;
}
.el-time-panel__footer {
text-align: center;
}
.el-loading-mask {
background-color: rgba(255,255,255,.5);
}
.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content {
background: #d8d8d8;
font-weight: bold;
}
.el-date-editor .el-range-separator {
width: auto !important;
}
/* 用户机构目录 */
.el-tree-node__content {
height: 35px;
}
.el-tree-node__label {
margin-left: 0;
}
@media screen and (max-height: 540px) {
body {
height: 540px;
overflow-y: auto;
}
}
/* 单选框
.el-radio__input.is-checked .el-radio__inner {
background: $primaryColor;
border-color: $primaryColor;
}
.el-radio__input.is-focus {
.el-radio__inner {
border-color: $primaryColor;
}
}
.el-radio__inner:hover {
border-color: $primaryColor;
}
*/
/* 多选框
.el-checkbox__input.is-checked {
.el-checkbox__inner {
background: $primaryColor;
border-color: $primaryColor;
}
}
.el-checkbox__input.is-focus {
.el-checkbox__inner {
border-color: $primaryColor;
}
}
.el-checkbox__input.is-indeterminate {
.el-checkbox__inner {
background: $primaryColor;
border-color: $primaryColor;
}
}
*/
.global {
// 头部
.header {
.el-submenu__title {
padding: 0;
}
.el-submenu__icon-arrow {
display: none;
}
.el-menu--horizontal {
> .el-submenu {
.el-submenu__title {
height: 50px;
line-height: 50px;
}
}
}
}
.el-menu--horizontal {
.el-menu--popup {
min-width: 120px;
}
}
.el-menu--vertical {
.el-menu {
i {
margin-right: 6px;
}
}
}
.bigMenuVertical {
&:not(.el-menu--collapse) {
width: 220px;
}
}
// 树的三角图标
.el-icon-caret-right {
&:before {
display: none;
}
}
}
/* 输入框
.el-select-dropdown__item.selected {
color: $primaryColor;
}
*/
/* .el-table--enable-row-hover .el-table__body tr:hover>td, .el-table__body tr.hover-row > td, .el-table__body tr.hover-row.current-row > td, .el-table__body tr.hover-row.el-table__row--striped > td, .el-table__body tr.hover-row.el-table__row--striped.current-row > td {
background: #ececec;
}
.el-input__inner:focus, .el-textarea__inner:focus, .el-form-item.is-success .el-input__inner:focus, .el-form-item.is-success .el-textarea__inner:focus {
border-color: $infoColor;
}
.el-form-item.is-success .el-input__inner, .el-form-item.is-success .el-textarea__inner {
border-color: #dcdfe6;
} */
.catalogCon .el-input.is-disabled .el-input__inner, .editDialog .el-input.is-disabled .el-input__inner, .editDialog .el-textarea.is-disabled .el-textarea__inner {
color: #606266;
border-color: #e4e7ed;
}
// 用户管理——添加用户
.addeditUserDialog {
.el-cascader, .el-select {
display: block;
}
}
@media screen and (min-width: 1400px) {
.global {
.bigMenuVertical:not(.el-menu--collapse) {
width: 280px;
}
.header {
.title {
width: 280px;
}
}
}
}
@media screen and (max-width: 1400px) {
.global {
.header {
.title {
> .logo {
margin-right: 20px;
}
}
}
}
}
@media screen and (max-width:1366px) {
.global {
.bigMenuVertical:not(.el-menu--collapse) {
width: 220px;
}
.header {
.title {
width: 220px;
> img {
margin-right: 10px;
}
> .logo {
margin-right: 10px;
}
}
}
.multiselectTree {
max-height: 320px;
margin-top: 0;
}
}
}
* {
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
position: relative;
margin: 0;
padding: 0;
font-size: 14px;
font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
/* overflow-y: auto; */
}
/* body {
background-color: #f2f2f2;
} */
h1,h2,h3,h4,h5,h6,p,ul,ol {
margin: 0;
padding: 0;
}
a {
text-decoration: none;
}
ul, ol {
list-style: none;
}
/*
* {
scrollbar-base-color: #eee;
scrollbar-3dlight-color: #eee;
scrollbar-highlight-color: #eee;
scrollbar-track-color: #f1f1f1;
scrollbar-arrow-color: #000;
scrollbar-shadow-color: #eee;
scrollbar-dark-shadow-color: #eee;
box-sizing: border-box;
}
*::-webkit-scrollbar {
width:9px;
height:9px;
}
*::-webkit-scrollbar-button {
display: none;
}
*::-webkit-scrollbar-track-piece {
background-color: #f2f2f2;
}
*::-webkit-scrollbar-thumb {
background-color: #C1C1C1;
border-radius: 10px;
} */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
input[type="number"]{
-moz-appearance: textfield;
}
.clearfix:after {
content: "";
display: block;
clear: both;
height: 0;
}
.clearfix {
zoom: 1;
}
.fl {
float: left;
}
.flr {
float: right;
}
.full_pages {
position: absolute;
width: 100%;
min-height: 100%;
top: 0;
left: 0;
/*right: 0;
bottom: 0;*/
z-index: 11;
}
/* element ui reset or custom */
/* element ui reset or custom end */
/* esri css reset */
.esriSimpleSliderBR, .esriLargeSliderBR {
right: 20px !important;
bottom: 220px !important;
}
/*popup css*/
.esriPopup .esriPopupWrapper {
overflow: hidden;
width: 200px;
/*height: 180px;*/
text-align: left;
}
.esriPopup .sizer {
width: 200px;
}
.esriPopup .contentPane h4 {
font-size: 14px;
padding: 6px;
}
.esriPopup .contentPane ul {
padding: 0 10px;
}
.esriPopup .contentPane li {
padding: 4px 0;
margin-bottom: 4px;
}
.esriPopup .pointer, .esriPopup .outerPointer {
width: 12px;
height: 12px;
}
.esriPopup .outerPointer.left {
left: 14px;
}
.esriPopup .outerPointer.right {
right: 14px;
}
.esriPopup .outerPointer.bottom {
bottom: 14px;
}
.esriPopup .outerPointer.top {
top: 14px;
}
.hotPlace-container .esriSimpleSlider div {
font-size: 16px;
width: 24px;
height: 22px;
line-height: 20px;
}
.map .container {
background-color: #FCFCF8;
}
/* esri css reset end */
/* *** custom component pulgin start ****/
.btn {
display: inline-block;
padding: 4px 12px;
font-size: 14px;
outline: none;
border-width: 0;
background-color: transparent;
cursor: pointer;
}
.btn-default {
color: #333333;
background-color: #ffffff;
}
.btn-default:hover {
background-color: #f2f2f2;
}
/* .btn-default:focus {
background-color: #ddd;
} */
.btn-primary {
color: #ffffff;
background-color: #8abb1a;
}
.btn-primary:hover {
background-color: #709814;
}
/* *** custom component pulgin end ****/
/* transition anmation */
.fade-enter-active {
transition: opacity .1s;
}
.fade-enter, .fade-leave-active {
opacity: 0;
}
.fadeIn-enter-active, .fadeIn-leave {
transform: all .2s ease;
}
.fadeIn-enter, .fadeIn-leave-active {
opacity: 0;
}
.slideInDown-enter-active {
animation: slideInDown .4s;
}
/* .slideInDown-leave-active {
} */
.slideInLeft-enter-active {
display: block;
animation: slideInLeft .35s;
}
.slideInLeft-leave-active {
display: none;
}
.scaleIn-enter-active {
animation: scaleIn .2s;
}
.zoom-in-top-enter-active, .zoom-in-top-leave-active{
opacity: 1;
transform: scaleY(1);
transition:transform .3s cubic-bezier(.23,1,.32,1) .1s, opacity .3s cubic-bezier(.23,1,.32,1) .1s;
transform-origin: center top
}
.zoom-in-top-enter, .zoom-in-top-leave-active{
opacity:0;
transform:scaleY(0)
}
.zoom-in-right-enter-active, .zoom-in-right-leave-active{
opacity: 1;
transform: scaleX(1);
transition:transform .3s cubic-bezier(.23,1,.32,1) .1s, opacity .3s cubic-bezier(.23,1,.32,1) .1s;
transform-origin: center left
}
.zoom-in-right-enter, .zoom-in-right-leave-active{
opacity:0;
transform:scaleX(0)
}
/*.slideInDown {
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
-webkit-animation-name: slideInDown;
animation-name: slideInDown;
}*/
/* animation .css */
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slideInDown {
from {
transform: translate3d(0, -10%, 0);
visibility: visible;
}
to {
transform: translate3d(0, 0, 0);
}
}
@keyframes slideInLeft {
from {
transform: translate3d(10%, 0, 0);
visibility: visible;
}
to {
transform: translate3d(0, 0, 0);
}
}
@keyframes scaleIn {
from {
transform: scale(0);
visibility: visible;
}
to {
transform: scale(1);
}
}
/* transition anmation end */
$--color-primary: #E02E43 !default;
/* header var */
$--header-background-color: #ffffff !default;
$--header-title-background-color: #221d1d !default;
/* sidebar var */
$--sidebar-background-color: #221d1d !default;
$--sidebar-active-background-color: #3b3535 !default;
$--sidebar-icon-color: #898f9f !default;
$--sidebar-text-color: #ffffff !default;
$--sidebar-active-text-color: #ffffff !default;
$--sidebar-submenu-text-color: #898f9f !default;
.global {
// 侧栏菜单
.siderBar {
background: $--sidebar-background-color;
> .el-menu {
background: $--sidebar-background-color;
border-right: none;
.el-menu-item {
color: $--sidebar-text-color;
border-left: solid 2px $--sidebar-background-color;
&:hover, &:focus {
background: $--sidebar-active-background-color;
}
}
.el-menu-item.is-active {
color: $--sidebar-active-text-color;
background: $--sidebar-active-background-color;
border-left: solid 2px $--color-primary;
}
.iconfont {
color: $--sidebar-icon-color;
}
}
.el-submenu {
.el-menu {
background: $--sidebar-background-color;
}
}
.el-submenu__title {
&:hover {
background: $--sidebar-active-background-color;
}
}
.is-opened {
> .el-submenu__title {
background: $--sidebar-background-color;
}
}
.el-submenu__title {
color: $--sidebar-submenu-text-color;
}
.el-menu-item {
color: $--sidebar-text-color;
&:hover {
background: $--sidebar-active-background-color;
}
}
}
.el-menu {
background-color: $--sidebar-background-color;
color: $--sidebar-text-color;
.el-menu-item {
color: $--sidebar-text-color;
&:hover, &:focus {
background: $--sidebar-active-background-color;
}
}
}
}
/* header */
.header {
background-color: $--header-background-color;
.title, {
background-color: $--header-title-background-color;
.icon-menu {
@extend .title;
}
}
}
\ No newline at end of file
This diff is collapsed.
<template>
<div class="barChart" :id="domId" :style="{height:height,width:width}"></div>
</template>
<script>
import echarts from 'echarts'
export default {
props: {
domId: {
type: String,
default: 'barChart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
},
title: String,
legend: Array,
catalog: Array,
data: {
type: Array,
default: () => []
},
lineOnoff: {
type: Boolean,
default: true
},
rendering: {
type: Boolean,
default: true
}
},
data() {
return {
chart: null,
ec: null,
options: {
title: {
text: '访问量前10',
textStyle: {
color: '#333',
fontSize: '16',
fontFamily: '宋体'
},
left: 'center'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
show: true,
formatter: function(data) {
return data[0].name + ':' + data[0].value
}
},
grid: { // 绘图区调整
x: 150, // 左留白
y: 40, // 上留白
x2: 70, // 右留白
y2: 17 // 下留白
},
xAxis: {
show: false,
type: 'value',
boundaryGap: [0, 0],
position: 'bottom'
},
yAxis: {
type: 'category',
data: [], // ['服务1','服务2','服务3','服务4','服务5','服务6','服务7','服务8','服务9','服务10'],
axisLine: { show: false }, // 坐标轴
axisTick: [{ // 坐标轴小标记
show: false
}],
inverse: 'true',
axisLabel: {
textStyle: {
fontSize: '14'
}
}
},
series: {
name: '',
type: 'bar',
barHeight: 20, // 最小柱高
barWidth: 15, // 柱宽度
data: [], // [1, 23489, 29034, 104970, 0, 63030,63230,30230,63030,63230],
itemStyle: {
normal: { // 柱状图颜色
color: '#ff6600',
label: {
show: false, // 显示文本
position: 'inside', // 数据值位置
textStyle: {
color: '#000',
fontSize: '14'
}
}
}
},
label: {
normal: {
show: true,
position: 'right'
}
}
}
}
}
},
watch: {
data () {
this.init()
},
lineOnoff (val) {
if (val) {
let resizeTimer = null
clearTimeout(resizeTimer)
resizeTimer = setTimeout(() => {
this.init()
this.widthChange()
}, 100)
}
},
rendering (val) {
let resizeTimer = null
clearTimeout(resizeTimer)
resizeTimer = setTimeout(() => {
this.init()
this.widthChange()
}, 100)
}
},
mounted () {
this.init()
this.widthChange()
/* window.addEventListener('resize', () => {
this.init()
this.widthChange()
}) */
},
methods: {
widthChange () {
let winWid = window.document.body.clientWidth
// this.ec ? this.ec.setOption(this.options, true) : ''
if (this.ec !== null || this.ec !== undefined) {
// console.log(111)
this.ec.setOption(this.options, true)
}
},
init () {
this.ec = this.ec ? this.ec : echarts.init(document.getElementById(this.domId))
this.options.title.text = this.title || ''
this.options.yAxis.data = this.catalog
if (typeof this.data === 'object') {
this.options.series.name = this.title
this.options.series.data = this.data
} else {
this.options.series.name = this.title
this.options.series.data = this.data
}
this.ec.setOption(this.options, true)
this.ec.resize(() => {
this.ec.setOption(this.options, true)
})
}
}
}
</script>
<template>
<el-breadcrumb class="breadCrumb" separator="/">
<el-breadcrumb-item v-for="item in breadCrumbList" :key="item.id">{{ item.title }}</el-breadcrumb-item>
</el-breadcrumb>
</template>
<script>
export default {
name: 'BreadCrumb',
props: ['breadCrumbList'],
data() {
return {}
}
}
</script>
<style lang="scss" scoped>
.breadCrumb {
height: 40px;
background: #fbfbfb;
padding-left: 10px;
border-bottom: solid 1px #f2f9f9;
.el-breadcrumb__item {
line-height: 40px;
}
}
</style>
<template>
<div class="block">
<span class="demonstration">请选择日期</span>
<el-date-picker
v-model="value"
align="right"
type="daterange"
unlink-panels
value-format="yyyy-MM-dd"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:picker-options="pickerOptions"
:clearable=false
size="small"
@change="dateTimeChange">
</el-date-picker>
</div>
</template>
<script>
import Util from '../utils/util.js'
export default {
data () {
return {
pickerOptions: {
disabledDate (time) {
return time.getTime() > Date.now()
},
shortcuts: [{
text: '最近一周',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
picker.$emit('pick', [start, end])
}
}, {
text: '最近一个月',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
picker.$emit('pick', [start, end])
}
}, {
text: '最近三个月',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
picker.$emit('pick', [start, end])
}
}]
},
value: []
}
},
mounted () {
this.defaultValue()
},
methods: {
defaultValue () {
this.value = []
let sdata = Util.getDay(-7, '-')
let edate = Util.getDay(0, '-')
this.value.push(sdata)
this.value.push(edate)
},
dateTimeChange (value) {
let dateArr = []
for (let i = 0; i < value.length; i++) {
dateArr.push(value[i].replace(/-/g, ''))
}
this.$emit('choose-date', dateArr)
}
}
}
</script>
<template>
<div class="ecLine" :id="domId" :style="{height: height,width: width}" ></div>
</template>
<script>
import echarts from 'echarts'
export default {
props: {
domId: {
type: String,
default: 'ecLine'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
},
title: String,
legend: Array,
catalog: Array,
data1: {
type: Array,
default: () => []
},
data2: {
type: Array,
default: () => []
},
lineOnoff: {
type: Boolean,
default: true
},
yName: {
type: String,
default: '总量'
},
rendering: {
type: Boolean,
default: true
}
},
data () {
return {
ec: null,
options: {
title: {
text: '',
textStyle: {
color: '#333',
fontSize: '16',
fontFamily: '宋体'
}
},
grid: [{
top: '20%',
left: '15%',
right: '5%',
height: '30%'
}, {
top: '58.5%',
left: '15%',
right: '5%',
height: '30%',
bottom: '5%'
}],
tooltip: {
trigger: 'axis',
axisPointer: {
lineStyle: {
color: '#056EA1'
}
},
formatter: function (params) {
if (params instanceof Array) {
var idxMap = [{
text: '服务访问总量',
data: []
}, {
text: '服务平均耗时',
data: []
}]
var time = params[0].axisValue
for (var i = 0; i < params.length; i++) {
var seriesIdx = params[i].seriesId.split(params[i].seriesId[0])
idxMap[seriesIdx[2]].data.push({
marker: params[i].marker,
seriesName: params[i].seriesName,
data: params[i].data
})
}
return '<div>' +
'<time>' + time + '</time>' +
'<br />' +
idxMap.map((item) => {
return item.data.map((iItem) => {
return '<p style="margin: 0;padding: 0;">' + iItem.marker + iItem.seriesName + ': ' + iItem.data + '</p>'
}).join('')
}).join('') +
'</div>'
}
}
},
axisPointer: {
link: {
xAxisIndex: 'all'
}
},
legend: {
data: []
},
xAxis: [{
type: 'category',
gridIndex: 0,
boundaryGap: false,
splitLine: {show: false},
/* axisLabel: {
interval: 0 // 默认展示存放得下一部分数据 ,0 表示全部显示
}, */
data: []
}, {
type: 'category',
gridIndex: 1,
position: 'top',
boundaryGap: false,
splitLine: {show: false},
/* axisLabel: {
show: false,
interval: 0
}, */
data: []
}],
yAxis: [{
name: '访问总量',
type: 'value',
nameTextStyle: {
fontSize: 14
},
gridIndex: 0,
splitLine: {show: false}
}, {
name: '平均耗时',
type: 'value',
nameTextStyle: {
fontSize: 14
},
gridIndex: 1,
inverse: true,
splitLine: {show: false}
}],
series: [{
name: '访问总量',
type: 'line',
smooth: true,
symbol: 'none',
sampling: 'average',
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgb(255, 158, 68)'
}, {
offset: 1,
color: 'rgb(255, 70, 131)'
}])
}
},
data: []
}, {
name: '平均耗时',
type: 'line',
smooth: true,
symbol: 'none',
sampling: 'average',
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgb(255, 158, 68)'
}, {
offset: 1,
color: 'rgb(255, 70, 131)'
}])
}
},
xAxisIndex: 1,
yAxisIndex: 1,
data: []
}]
}
}
},
watch: {
data1 () {
this.init()
},
data2 () {
this.init()
},
lineOnoff (val) {
if (val) {
let resizeTimer = null
clearTimeout(resizeTimer)
resizeTimer = setTimeout(() => {
this.init()
this.widthChange()
}, 100)
}
},
rendering (val) {
let resizeTimer = null
clearTimeout(resizeTimer)
resizeTimer = setTimeout(() => {
this.init()
this.widthChange()
}, 100)
}
},
mounted () {
this.init()
this.widthChange()
/* window.addEventListener('resize', () => {
this.init()
this.widthChange()
}) */
},
methods: {
widthChange () {
let winWid = window.document.body.clientWidth
// this.ec ? this.ec.setOption(this.options, true) : ''
if (this.ec !== null || this.ec !== undefined) {
this.ec.setOption(this.options, true)
}
},
init () {
this.ec = this.ec ? this.ec : echarts.init(document.getElementById(this.domId))
this.options.title.text = this.title || ''
this.options.xAxis[0].data = this.catalog
this.options.xAxis[1].data = this.catalog
this.options.series[0].data = []
this.options.series[1].data = []
if (typeof this.data1[0] === 'object') {
this.data1.map(item => {
this.options.series[0].data.push(item.value)
})
this.data2.map(item => {
this.options.series[1].data.push(item.value)
})
} else {
this.options.series.name = this.title
this.options.series[0].data = this.data1
this.options.series[1].data = this.data2
}
this.ec.setOption(this.options, true)
this.ec.resize(() => {
this.ec.setOption(this.options, true)
})
}
}
}
</script>
<template>
<div class="header">
<div class="title" :class="{'is-collapse': isCollapse}">
<i class="iconfont icon-menu" @click="handleMenu"></i>
<a class="logo"><img :src="logoPath" height="36" alt=""></a>
</div>
<div class="userImformation">
<router-link class="yunweiTitle" to="">运维管理系统</router-link>
<div class="user-info">
<div class="changeTheme">
<el-button type="text" @click="changeThemeHandler">换肤</el-button>
</div>
<div class="message">
<i class="iconfont icon-xiaoxi"></i>
<!-- <span class="dot"></span> -->
</div>
<div class="user-img" @click="handleUsercenter">
<el-tooltip class="item" effect="dark" :content="gisopUserInfo.username" placement="bottom">
<div class="user-imgIn">
<img src="../../static/images/people1.jpg" height="36">
</div>
</el-tooltip>
</div>
<div class="user-more">
<!-- <i class="iconfont icon-gengduoda"></>i
<span class="fl user" @click="handleResetPassword">{{ gisopUserInfo.username }}</span>
<span class="fl exit" @click="handleLoginOut"> [退出] </span> -->
<el-menu
:default-active="activeIndex2"
mode="horizontal"
@select="handleSelect"
background-color="#353d48"
text-color="#fff"
active-text-color="#fff">
<el-submenu index="1">
<template slot="title"><i class="iconfont icon-gengduoda"></i></template>
<el-menu-item index="1-1" @click="handleUsercenter">个人中心</el-menu-item>
<el-menu-item index="1-2" @click="handleLoginOut">退出</el-menu-item>
</el-submenu>
</el-menu>
</div>
</div>
</div>
<el-dialog
class="changeThemDialog"
title="更换皮肤"
:visible.sync="dialogThemeVisible"
width="40%"
@open="handleThemeDialogOpen">
<div class="themeList">
<span>选择皮肤: </span>
<span style="margin-left: 30px;">
<el-radio
v-for="item in themeArr"
:key="item.key"
v-model="radio"
:label="item.key">
<i class="clr" :style="{'background-color': item.color}"></i>{{ item.name }}
</el-radio>
</span>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogThemeVisible = false">取 消</el-button>
<el-button type="primary" @click="handleThemeSave">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { changeTheme } from '@/utils/global.js'
import Api from '@/api/index.js'
export default {
name: 'Header',
data () {
return {
enterOnoff: true,
isCollapse: false,
activeIndex2: '1',
logoPic: {
logo1: require('../../static/images/logo1.png'),
logo: require('../../static/images/logo.png')
},
dialogThemeVisible: false,
radio: 'blue',
redioNormal: 'blue',
themeArr: [{
name: '默认',
color: '#409eff',
key: 'chalk',
assets: 'chalk-index.css'
}, {
name: '红色',
color: '#E02E43',
key: 'red',
assets: 'red-index.css'
}, {
name: '靛蓝',
color: '#3B58E9',
key: 'blue',
assets: 'blue-index.css'
}, {
name: '墨绿色',
color: '#036a67',
key: 'green',
assets: 'green-index.css'
}]
}
},
computed: {
gisopUserInfo() {
return this.$store.state.gisopUserInfo
},
logoPath() {
return this.isCollapse
? this.logoPic.logo1
: this.logoPic.logo
}
},
watch: {
$route(val) {
if (val.query.UserAccount) {
this.init()
}
}
},
mounted() {
this.init()
},
methods: {
/* 更换皮肤 */
changeThemeHandler() {
this.dialogThemeVisible = true
},
handleThemeSave() {
this.dialogThemeVisible = false
const theme = this.themeArr.filter(x => x.key === this.radio)
changeTheme(theme[0].assets)
this.redioNormal = this.radio
},
handleThemeDialogOpen() {
this.radio = this.redioNormal
},
handleSelect(key, keyPath) {
},
isEmptyData (data) { // 判断数据是否为空,一般数据是object/array
if (data instanceof Object) {
var t
for (t in data) {
return false
}
return true
} else if (data instanceof Array) {
if (data.length === 0) return true
return false
}
},
init () {
if (this.isEmptyData(this.gisopUserInfo)) {
const storage = window.localStorage
if (storage.gisopUserInfo) { // 判断本地是否有存储 本地有存储
let gisopUserInfo = {}
gisopUserInfo = JSON.parse(storage.gisopUserInfo)
let time = parseInt(gisopUserInfo.time)
let date = parseInt(gisopUserInfo.date)
if ((time + date) >= Math.round(new Date().getTime() / 1000)) { // 判断是否过期
Api.getLoginIsTimeout(gisopUserInfo.token).then(data => {
if (data.status === 0) {
let user = gisopUserInfo.info
this.$store.dispatch('setGisopUser', user)
} else {
this.$store.dispatch('setGisopUser', {})
storage.removeItem('gisopUserInfo')
this.$message({
type: 'warning',
message: '登录失效了,请重新登录'
})
this.$router.replace('/login')
}
}).catch(res => {
this.$store.dispatch('setGisopUser', {})
storage.removeItem('gisopUserInfo')
this.$message({
type: 'error',
message: '登录失败,请重新登录'
})
this.$router.replace('/login')
})
} else {
this.$router.replace('/login')
}
} else { // 本地没有存储
this.$router.replace('/login')
}
}
},
// 个人中心操作
/* handleUserInfo () {
this.$router.push({name: 'ModifyPass'})
}, */
// 菜单操作
handleMenu () {
this.isCollapse = !this.isCollapse
this.$root.eventHub.$emit('handleMenu', this.isCollapse) // Hub触发事件,通过this.root.eventHub获取此对象//调用emit 方法
},
// 重置密码
handleUsercenter () {
this.$emit('user-center', true)
},
handleLoginOut () { // 退出用户登录
window.localStorage.removeItem('gisopUserInfo')
window.sessionStorage.setItem('redirect', this.$route.fullPath)
this.$message({
type: 'success',
message: '用户成功退出!'
})
this.$router.replace('/login')
this.$store.dispatch('setGisopUser', {})
this.enterOnoff = false
},
checkBusinessInfo () {
this.$refs.infoDialog.showInfo()
}
}
}
</script>
<style lang="scss">
</style>
<template>
<div class="ecLine" :id="domId" :style="{height: height,width: width}" ></div>
</template>
<script>
import echarts from 'echarts'
export default {
props: {
domId: {
type: String,
default: 'ecLine'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
},
title: String,
legend: Array,
catalog: Array,
data: {
type: Array,
default: () => []
},
lineOnoff: {
type: Boolean,
default: true
},
yName: {
type: String,
default: '总量'
},
iColor: {
type: String,
default: 'rgb(255, 70, 131)'
},
aColori: {
type: String,
default: 'rgb(255, 158, 68)'
},
aColorii: {
type: String,
default: 'rgb(255, 70, 131)'
},
rendering: {
type: Boolean,
default: true
}
},
data() {
return {
resizeTimer: null,
ec: null,
options: {
title: {
text: '',
textStyle: {
color: '#333',
fontSize: '16',
fontFamily: '宋体'
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
lineStyle: {
color: '#056EA1'
}
}
},
legend: {
left: 'right',
data: [],
padding: [0, 5, 5, 90]
},
xAxis: {
type: 'category',
name: '时间',
splitLine: {show: false},
data: [],
boundaryGap: false
},
grid: { // 调整上下左右的显示范围
left: '20',
right: '50',
top: '60',
bottom: '30',
containLabel: true
},
yAxis: {
type: 'value',
name: this.yName,
min: 0,
splitNumber: 4,
splitLine: {show: false}
},
series: {
name: '',
type: 'line',
smooth: true,
symbol: 'none',
sampling: 'average',
itemStyle: {
normal: {
color: this.iColor
}
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: this.aColori // '#ffd897'
}, {
offset: 1,
color: this.aColorii // '#fff'
}])
}
},
data: []
}
},
colorArr: [{
color1: '#ffd897',
color2: '#fdfdfd'
}, {
color1: '#abc3ff',
color2: '#fdfdfd'
}, {
color1: '#ffabd8',
color2: '#fdfdfd'
}, {
color1: '#cefac9',
color2: '#fdfdfd'
}, {
color1: '#fac9f0',
color2: '#fdfdfd'
}]
}
},
watch: {
data () {
this.init()
},
lineOnoff (val) {
if (val) {
let resizeTimer = null
clearTimeout(resizeTimer)
resizeTimer = setTimeout(() => {
this.init()
this.widthChange()
}, 100)
}
},
rendering (val) {
let resizeTimer = null
clearTimeout(resizeTimer)
resizeTimer = setTimeout(() => {
this.init()
this.widthChange()
}, 100)
/* window.addEventListener('resize', () => {
if (resizeTimer) clearTimeout(resizeTimer)
resizeTimer = setTimeout(() => {
console.log(666)
this.init()
this.widthChange()
}, 1000)
}) */
}
},
mounted () {
this.init()
// this.widthChange()
},
methods: {
widthChange () {
let winWid = window.document.body.clientWidth
if (this.ec !== null || this.ec !== undefined) {
this.ec.setOption(this.options, true)
}
// this.ec ? this.ec.setOption(this.options, true) : ''
},
init () {
this.ec = this.ec ? this.ec : echarts.init(document.getElementById(this.domId))
this.options.title.text = this.title || ''
this.options.xAxis.data = this.catalog
if (typeof this.data[0] === 'object') {
if (this.data[0]['data'] !== undefined) { // 多条折线
let arr = [], legend = []
this.data.map((item, index) => {
let series = {
name: item.name,
type: 'line',
smooth: true,
symbol: 'none',
sampling: 'average',
areaStyle: { normal: {} },
/* areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: this.colorArr[index].color1 // '#ffd897'
}, {
offset: 1,
color: this.colorArr[index].color2 // '#fff'
}])
}
}, */
data: item.data
}
legend.push(item.name)
arr.push(series)
})
this.options.legend.data = legend
this.options.series = arr
} else {
this.options.series.data = this.data
}
} else {
this.options.series.name = this.title
this.options.series.data = this.data
}
this.ec.setOption(this.options, true)
this.ec.resize(() => {
this.ec.setOption(this.options, true)
})
}
}
}
</script>
<template>
<el-tree
class="multiselectTree"
ref="treeNode"
:data="treeData"
:load="loadNode"
lazy
:props="defaultProps"
:node-key="nodeKey"
:default-expanded-keys="defaultExpandedKeys"
:current-node-key="currentNodeKey"
:default-expand-all="defaultExpandAll"
:highlight-current="highlightCurrent"
@node-click="handleNodeClick"
:render-content="renderContent"
>
</el-tree>
</template>
<script>
import Api from '@/api/index.js'
export default{
props: {
treeData: {
type: Array,
default: () => []
},
nodeKey: {
type: String,
default: 'id'
},
tab2Onoff: {
type: Boolean,
default: false
},
defaultProps: {
type: Object,
default: () => ({
children: 'childrens',
label: 'text',
isLeaf: function (data, node) {
// console.log(data)
}
})
},
editOnoff: {
type: Boolean,
default: false
},
defaultExpandedKeys: {
type: Array,
default: () => []
},
defaultCheckedKeys: {
type: Array,
default: () => []
},
defaultExpandAll: {
type: Boolean,
default: false
},
highlightCurrent: {
type: Boolean,
default: true
}
},
data () {
return {
currentNodeKey: '', // 当前选中节点的 key -> string, number
getCheckedKeys: [],
id: ''
}
},
watch: {
tab2Onoff (val) {
if (val) {
this.$refs['treeNode'].setCheckedKeys(this.getCheckedKeys)
}
},
editOnoff (val) {
this.$refs['treeNode'].setCheckedKeys(this.defaultCheckedKeys)
}
},
methods: {
renderContent (createElement, {node, data, store}) {
var self = this
return createElement('span', [
createElement('span', {attrs: {
style: 'width: 22px;height: 36px;float: left; margin: 0 4px 0 6px;font-size: 18px;'
}}, [createElement('svg', {class: 'icon', attrs: {'aria-hidden': true, style: 'width: 22px;height: 36px;'}}, data.type === 'S' ? [createElement('use', {attrs: {'xlink:href': '#icon-fuwurizhi'}})] : [createElement('use', {attrs: {'xlink:href': '#icon-folderpaper'}})])]),
createElement('span', {attrs: {
style: 'float: left;font-size: 14px;'
}}, node.label)
])
},
// 目录树
getCatalogServiceTree (serviceId) {
this.isLoadingTree = true
Api.getdirectoryAndServicesTree(serviceId).then(data => {
this.isLoadingTree = false
if (data.status === 0) {
this.treeData = data.data
} else {
this.$message({
type: 'error',
message: '获取数据失败!'
})
}
}).catch(res => {
this.isLoadingTree = false
this.$message({
type: 'error',
message: '请求数据失败'
})
})
},
// 异步加载树
loadNode (node, resolve) { // 加载节点
let vm = this
if (node.level === 0) { // 直接显示第一级菜单
return false
}
let arr = []
Api.getdirectoryAndServicesTree(node.data.id).then(data => {
if (data.status === 0) {
let body = data.data
if (body instanceof Array) {
if (body.length !== 0) {
// console.log(body)
body.forEach((item) => {
let leaf = true
if (item.isLeaf === false) {
leaf = false
}
arr.push({
id: item.id,
nameCn: item.nameCn,
nameEn: item.nameEn,
type: item.type,
isLeaf: leaf
})
})
} else {
arr = []
resolve([])
return
}
} else {
arr = []
}
// 加载下级
let childData = (node.data.type === 'D') ? arr : []
setTimeout(() => {
resolve(childData)
}, 300)
} else {
this.$message({
type: 'error',
message: '获取数据失败!'
})
}
}).catch(res => {
this.$message({
type: 'error',
message: '请求数据失败'
})
})
},
handleNodeClick (data) {
this.$emit('node-click', data)
}
}
}
</script>
<style lang="scss">
.multiselectTree {
width: 360px;
max-height: 360px;
overflow-y: auto;
float: left;
margin-top: 10px;
}
</style>
<template>
<el-row class="login content">
<div class="logo">
<img src="../../static/images/logo1.png" height="46" alt="">
<h1>运维管理系统</h1>
</div>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span style="line-height: 36px;font-size:20px;">登录</span>
<!-- <el-button style="float: right;" type="text">注册</el-button> -->
</div>
<el-form
ref="loginForm"
:model="loginForm"
:rules="rules"
label-width="120px">
<el-form-item label="账户:" prop="name">
<el-input v-model="loginForm.name" placeholder="输入登录用户名" autofocus @change="handleInputChange"></el-input>
</el-form-item>
<el-form-item label="密码:" prop="password">
<el-input type="password"
v-model="loginForm.password"
placeholder="请输入密码"
@keyup.native.enter="onSubmit('loginForm')"
@change="handleInputChange"></el-input>
</el-form-item>
<el-form-item>
<el-checkbox label="记住账户" v-model="loginForm.remember"></el-checkbox>
</el-form-item>
<el-form-item class="buttons">
<el-button
type="primary"
size="large"
class="submitBtn"
:loading="loginForm.loading"
@click="onSubmit('loginForm')" >
{{ loginForm.submitText }}
</el-button>
<el-button type="text" @click="resetFields('loginForm')">重置</el-button>
</el-form-item>
<el-form-item v-if="loginForm.isSubmit" style="margin-bottom: 0;">
<el-alert type="error" :title="loginForm.errorText" :closable="true" style="line-height: 1.2;" @close="loginForm.isSubmit = false"></el-alert>
</el-form-item>
</el-form>
</el-card>
</el-row>
</template>
<script>
import Api from '../api/index.js'
import base64 from 'base-64'
export default {
data() {
return {
loginForm: {
name: '',
password: '',
remember: false,
loading: false,
isSubmit: false,
errorText: '用户名或密码错误',
submitText: '登录'
},
rules: {
name: [
{required: true, message: '请输入账户名称', trigger: 'change'}/* ,
{ min: 3, max: 12, message: '长度在 3 到 12 个字符', trigger: 'blur' } */
],
password: [
{required: true, message: '请输入密码', trigger: 'change'}/* ,
{ min: 3, max: 18, message: '长度在 3 到 18 个字符', trigger: 'blur' } */
]
}
}
},
mounted() {
// this.$Progress.finish()
const storage = window.localStorage
if (storage.rememberNameOp) { // 本地存储登录用户名
this.loginForm.remember = true
this.loginForm.name = storage.rememberNameOp
}
if (storage.gisopUserInfo) { // 本地用户信息有存储信息
let gisopUserInfo = JSON.parse(storage.gisopUserInfo),
time = parseInt(gisopUserInfo.time),
date = parseInt(gisopUserInfo.date)
// console.log(time + date, Math.round(new Date().getTime()/1000))
if ((time + date) >= Math.round(new Date().getTime() / 1000)) { // 判断是否过期
this.$router.replace('/')
}
}
},
methods: {
handleInputChange () {
this.loginForm.isSubmit = false
},
onSubmit (formName) {
// console.log(formName)
this.$refs[formName].validate((valid) => {
this.loginForm.isSubmit = false
if (valid) {
this.loginForm.loading = true
let psw = base64.encode(this.loginForm.password),
uName = this.loginForm.name.replace(/\s/g, '')
// console.log('base64 Password: ', pws)
Api.getLoginApi(uName, psw).then(data => {
this.loginForm.loading = false
let datas = data.data
if (data.status === 0) {
let userLocal = {
name: uName,
token: datas.result.token,
info: datas.result.userInfo,
date: Math.round(new Date().getTime() / 1000),
time: 3600 * 24 * 1 // 存储时间秒*时*天
}
// 本地存储
localStorage.setItem('gisopUserInfo', JSON.stringify(userLocal))
localStorage.removeItem('rememberNameOp')
if (this.loginForm.remember) {
localStorage.setItem('rememberNameOp', uName)
}
// vuex store
let userState = datas.result.userInfo
this.$store.dispatch('setGisopUser', userState)
// notify
let message = '欢迎您,' + userState.username
this.$notify({
title: '登录成功',
message: message,
type: 'success'
})
this.$router.replace('/')
} else {
console.error(data)
this.loginForm.errorText = '用户名或密码错误'
this.loginForm.isSubmit = true
}
}).catch(res => {
this.loginForm.loading = false
this.loginForm.isSubmit = true
this.loginForm.errorText = '提交失败,服务有误'
console.error(res)
})
} else {
console.log('error submit!!')
return false
}
})
},
resetFields(formName) {
this.$refs[formName].resetFields()
}
}
}
</script>
<style lang="scss">
.login {
width: 100%;
height: 100%;
background-image: linear-gradient(180deg, rgba(255, 255, 255, 0) 60%, #f9f9f9), linear-gradient(70deg, #f6f9ed 32%, #e4f7f6);
background-color: #e4f7f6;
.logo {
margin-top: 100px;
text-align: center;
img {
vertical-align: middle;
}
h1 {
display: inline-block;
margin-left: 20px;
font-size: 30px;
color: #424857;
font-weight: 400;
vertical-align: middle;
line-height: 46px;
}
}
.box-card {
width: 520px;
/* height: 360px; */
margin: 40px auto;
.el-form {
margin: 25px 25px 10px 0;
.buttons {
margin-top: 10px;
}
.submitBtn {
width: 180px;
margin-right: 15px;
}
}
}
}
</style>
<template>
<section class="modifyPass form-content">
<el-form ref="form" :model="formData" :rules="rules" label-width="120px">
<el-form-item label="旧密码:" prop="oldPass">
<el-input type="password" v-model="formData.oldPass" @change="handleInputChange"></el-input>
<span></span>
</el-form-item>
<el-form-item label="新密码:" prop="newPass">
<el-input type="password" v-model="formData.newPass" @change="handleInputChange"></el-input>
<span class="tips">1. 至少含8个字符; <br> 2. 至少大写、小写英文字母、数字、特殊符号中的三种</span>
</el-form-item>
<el-form-item label="确认新密码:" prop="checkPass">
<el-input type="password" v-model="formData.checkPass" @change="handleInputChange"></el-input>
<span></span>
</el-form-item>
<el-form-item style="padding-top: 14px;">
<el-button @click="resetForm('form')">重置</el-button>
<el-button type="primary" :loading="formData.submiting" @click="onSubmit('form')">提交</el-button>
</el-form-item>
<el-form-item v-if="formData.error">
<el-alert
type="error"
:title="formData.errorText"
:closable="true"
style="line-height: 1.2; width: 280px;"
@close="formData.error = false"></el-alert>
</el-form-item>
</el-form>
</section>
</template>
<script>
import base64 from 'base-64'
import Api from '../api/index.js'
export default {
data () {
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入旧密码'))
} else {
callback()
}
}
var validatePass1 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入新密码'))
} else {
if (this.formData.newPass !== '') {
if (this.formData.newPass.length < 8) {
callback(new Error('密码最小长度为8个字符'))
} else {
var reg = /(((?=.*[a-z])+(?=.*[A-Z])+(?=.*\d)+)|((?=.*[A-Z])+(?=.*[a-z])+(?=.*[~!@#$%^&*()<>?_+{}|])+)|((?=.*\d)+(?=.*[A-Z])+(?=.*[~!@#$%^&*()<>?_+{}|])+)|((?=.*\d)+(?=.*[a-z])+(?=.*[~!@#$%^&*()<>?_+{}|])+))[A-Za-z\d~!@#$%^&*()<>?_+{}|]/
// console.log(reg.test(this.formData.newPass))
if (!reg.test(this.formData.newPass)) {
callback(new Error('密码输入规则有误,请阅读下边规则'))
} else {
this.$refs.form.validateField('checkPass')
}
}
}
callback()
}
}
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入新密码'))
} else if (value !== this.formData.newPass) {
callback(new Error('两次输入密码不一致!'))
} else {
callback()
}
}
return {
formData: {
oldPass: '',
newPass: '',
checkPass: '',
submiting: false,
error: false,
errorText: ''
},
rules: {
oldPass: [
{validator: validatePass, trigger: 'blur'}
],
newPass: [
{validator: validatePass1, trigger: 'blur'},
{validator: validatePass1, trigger: 'change'}
],
checkPass: [
{validator: validatePass2, trigger: 'blur'}
]
}
}
},
computed: {
gisopUserInfo() {
return this.$store.state.gisopUserInfo
}
},
mounted () {
this.userguid = this.gisopUserInfo.userguid
if (this.userguid === undefined) {
return false
} else {
this.userguid = this.userguid.trim()
}
},
methods: {
handleInputChange() {
this.formData.error = false
},
onSubmit (formName) {
this.formData.error = false
this.formData.submiting = true
this.$refs[formName].validate((valid) => {
if (valid) {
Api.modifyUserPassword(this.userguid, base64.encode(this.formData.oldPass), base64.encode(this.formData.newPass)).then(data => {
this.formData.submiting = false
this.$router.go(-1)
if (data.status === 0) {
this.$message({
type: 'success',
message: '修改密码成功,请重新登录'
})
window.localStorage.removeItem('gisopUserInfo')
window.sessionStorage.setItem('redirect', this.$route.fullPath)
this.$router.replace('/login')
this.$store.dispatch('setGisopUser', {})
} else {
this.$message({
type: 'warning',
message: data.message
})
}
})
.catch(res => {
this.$message({
type: 'error',
message: '请求数据失败'
})
})
} else {
this.formData.submiting = false
// console.log('error submit!!')
return false
}
})
},
resetForm(formName) {
this.$refs[formName].resetFields()
}
}
}
</script>
<style lang="scss">
.modifyPass {
padding: 0 12px;
.el-input {
display: inline-block;
width: 280px;
}
span.tips {
margin-left: 10px;
margin-top: 10px;
display: inline-block;
width: 300px;
vertical-align: top;
font-size: 12px;
color: #768394;
line-height: 14px;
}
}
</style>
<template>
<el-tree
class="multiselectTree"
ref="treeNode"
:data="treeData"
show-checkbox
:props="defaultProps"
:node-key="nodeKey"
:default-expanded-keys="defaultExpandedKeys"
:current-node-key="currentNodeKey"
:default-expand-all='defaultExpandAll'
@check-change="handleCheckChange"
@node-click="handleNodeClick"
>
</el-tree>
</template>
<script>
import Api from '../api/index.js'
export default {
props: {
treeData: {
type: Array,
default: () => []
},
nodeKey: {
type: String,
default: 'id'
},
tab2Onoff: {
type: Boolean,
default: false
},
defaultProps: {
type: Object,
default: () => ({
children: 'childrens',
label: 'text',
isLeaf: 'leaf'
})
/* function () {
return {
children: 'childrens',
label: 'text',
isLeaf: 'leaf'
}
} */
},
editOnoff: {
type: Boolean,
default: false
},
defaultExpandedKeys: {
type: Array,
default: () => []
},
defaultCheckedKeys: {
type: Array,
default: () => []
},
defaultExpandAll: {
type: Boolean,
default: false
}
},
data () {
return {
currentNodeKey: '', // 当前选中节点的 key -> string, number
getCheckedKeys: []
}
},
watch: {
tab2Onoff (val) {
if (val) {
this.$refs['treeNode'].setCheckedKeys(this.getCheckedKeys)
}
},
editOnoff (val) {
this.$refs['treeNode'].setCheckedKeys(this.defaultCheckedKeys)
}
},
methods: {
// 异步加载树
/* loadNode(node, resolve) { // 加载节点
let vm = this
if (node.level === 0) { //直接显示第一级菜单
return resolve(this.treeData);
}
let arr = []
console.log(node)
this.$http.get(Api.monitorServiceApi+'/getCatalogServiceTree')
.then(function(response) {
// success callback
console.log(response.body.results)
let body = response.body.results
if (body instanceof Array) {
body.forEach(function(item) {
if(node.data.text === item.text){
body = item.childrens
body.forEach(function(item) { //将所点击的子级传给arr
arr.push({
id: item.id,
text: item.text,
parentId: item.parentId,
sort: item.sort,
leaf: item.leaf
})
})
return
}
})
}else {
arr = []
}
// 加载下级
let data = (node.data.leaf === false) ? data = arr : []
setTimeout(() => {
resolve(data);
}, 300);
}, function(response) {
// error callback
console.log('error:',response)
})
}, */
// 选择树节点
handleCheckChange () {
this.getCheckedKeys = this.$refs['treeNode'].getCheckedKeys()
this.$emit('select-node', this.$refs['treeNode'].getCheckedKeys())
},
handleNodeClick () {
// console.log(this.$refs['treeNode'].getCheckedKeys())
}
}
}
</script>
<style lang="scss">
.multiselectTree {
width: 360px;
max-height: 360px;
overflow-y: auto;
float: left;
margin-top: 10px;
/*
.el-tree-node__content {
overflow: hidden;
}
.el-tree-node__expand-icon {
float: right;
background: url('../../static/images/right.png') no-repeat center center;
background-size: 70% auto;
width: 36px;
height: 36px;
padding: 0;
margin: 0;
border: none;
}
.el-tree-node__expand-icon.is-leaf {
border: none;background: none;
}
.el-checkbox {
margin-left: 10px;
}
.el-checkbox,.el-tree-node__label {
float: left;
} */
}
</style>
<template>
<div class="ecLine" :id="domId" :style="{height: height,width: width}" ></div>
</template>
<script>
import echarts from 'echarts'
export default {
props: {
domId: {
type: String,
default: 'ecLine'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
},
title: String,
legend: Array,
catalog: Array,
data: {
type: Array,
default: () => []
},
lineOnoff: {
type: Boolean,
default: true
},
yName: {
type: String,
default: ''
},
iColor: {
type: String,
default: '#green'
},
aColori: {
type: String,
default: 'rgb(255, 255, 255)'
},
aColorii: {
type: String,
default: 'rgb(255, 255, 255)'
},
rendering: {
type: Boolean,
default: true
}
},
data() {
return {
resizeTimer: null,
ec: null,
options: {
title: {
text: '',
textStyle: {
color: '#333',
fontSize: '16',
fontWeight: 'normal',
fontFamily: 'Microsoft YaHei ' // 微软雅黑
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
lineStyle: {
color: 'rgb(147, 112, 219)'
}
}
},
legend: {
left: 'right',
data: [],
padding: [0, 5, 5, 90]
},
xAxis: {
type: 'category',
name: '时间',
splitLine: {show: true},
data: [],
boundaryGap: false,
splitArea: {show: false} // 保留网格区域背景颜色
},
grid: { // 调整上下左右的显示范围
left: '20',
right: '40',
top: '80',
bottom: '10',
containLabel: true
},
yAxis: {
type: 'value',
name: this.yName,
min: 0,
splitNumber: 5,
splitLine: {show: true}, // 网格
splitArea: {show: false}, // 保留网格区域背景颜色
boundaryGap: [0.2, 0.2]
},
series: {
name: '',
type: 'line',
smooth: true,
symbol: 'none',
sampling: 'average',
itemStyle: {
normal: {
color: this.iColor
}
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: this.aColori // '#ffd897'
}, {
offset: 1,
color: this.aColorii // '#fff'
}])
}
},
data: []
}
},
colorArr: [{
color1: '#00EE00',
color2: '#fdfdfd'
}, {
color1: '#ffd897',
color2: '#fdfdfd'
}, {
color1: '#ffabd8',
color2: '#fdfdfd'
}, {
color1: '#cefac9',
color2: '#fdfdfd'
}, {
color1: '#fac9f0',
color2: '#fdfdfd'
}]
}
},
watch: {
data () {
this.init()
},
lineOnoff (val) {
if (val) {
let resizeTimer = null
clearTimeout(resizeTimer)
resizeTimer = setTimeout(() => {
this.init()
this.widthChange()
}, 100)
}
},
rendering (val) {
let resizeTimer = null
clearTimeout(resizeTimer)
resizeTimer = setTimeout(() => {
this.init()
this.widthChange()
}, 100)
/* window.addEventListener('resize', () => {
if (resizeTimer) clearTimeout(resizeTimer)
resizeTimer = setTimeout(() => {
console.log(666)
this.init()
this.widthChange()
}, 1000)
}) */
}
},
mounted () {
this.init()
// this.widthChange()
},
methods: {
widthChange () {
let winWid = window.document.body.clientWidth
if (this.ec !== null || this.ec !== undefined) {
this.ec.setOption(this.options, true)
}
// this.ec ? this.ec.setOption(this.options, true) : ''
},
init () {
this.ec = this.ec ? this.ec : echarts.init(document.getElementById(this.domId))
this.options.title.text = this.title || ''
this.options.xAxis.data = this.catalog
if (typeof this.data[0] === 'object') {
if (this.data[0]['data'] !== undefined) { // 多条折线
let arr = [], legend = []
this.data.map((item, index) => {
let series = {
name: item.name,
type: 'line',
smooth: true,
symbol: 'none',
sampling: 'average',
areaStyle: { normal: {} },
/* areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: this.colorArr[index].color1 // '#ffd897'
}, {
offset: 1,
color: this.colorArr[index].color2 // '#fff'
}])
}
}, */
data: item.data
}
legend.push(item.name)
arr.push(series)
})
this.options.legend.data = legend
this.options.series = arr
} else {
this.options.series.data = this.data
}
} else {
this.options.series.name = this.title
this.options.series.data = this.data
}
this.ec.setOption(this.options, true)
this.ec.resize(() => {
this.ec.setOption(this.options, true)
})
}
}
}
</script>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
import SystemMonitorindex from '@/views/SystemMonitor/Index.vue'
const route = {
path: '/systemMonitor',
name: 'SystemMonitor',
component: SystemMonitorindex,
redirect: '/systemMonitor/systemLog',
children: [{
path: 'clickCount',
name: 'ClickCount',
component: resolve => require(['@/views/SystemMonitor/ClickCount.vue'], resolve)
}, {
path: 'systemLog',
name: 'SystemLog',
component: resolve => require(['@/views/SystemMonitor/SystemLog.vue'], resolve)
}]
}
export default route
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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