luyanan 6 years ago
commit
4e9af27985
108 changed files with 5725 additions and 0 deletions
  1. 12 0
      .babelrc
  2. 14 0
      .editorconfig
  3. 3 0
      .eslintignore
  4. 198 0
      .eslintrc.js
  5. 15 0
      .gitignore
  6. 10 0
      .postcssrc.js
  7. 28 0
      .project
  8. 5 0
      .travis.yml
  9. 0 0
      README.md
  10. 41 0
      build/build.js
  11. 54 0
      build/check-versions.js
  12. BIN
      build/logo.png
  13. 101 0
      build/utils.js
  14. 22 0
      build/vue-loader.conf.js
  15. 100 0
      build/webpack.base.conf.js
  16. 86 0
      build/webpack.dev.conf.js
  17. 156 0
      build/webpack.prod.conf.js
  18. 8 0
      config/dev.env.js
  19. 87 0
      config/index.js
  20. 5 0
      config/prod.env.js
  21. BIN
      favicon.ico
  22. 13 0
      index.html
  23. 82 0
      package.json
  24. 11 0
      src/App.vue
  25. 81 0
      src/api/bridge.js
  26. 90 0
      src/api/bridgeInfo.js
  27. 73 0
      src/api/collectionbox.js
  28. 97 0
      src/api/login.js
  29. 5 0
      src/api/pictureVc.js
  30. 73 0
      src/api/sensor.js
  31. 73 0
      src/api/server.js
  32. 82 0
      src/api/userManagemen.js
  33. BIN
      src/assets/404_images/404.png
  34. BIN
      src/assets/404_images/404_cloud.png
  35. 58 0
      src/components/Breadcrumb/index.vue
  36. 142 0
      src/components/CityPicker/index.vue
  37. 57 0
      src/components/DefaultPage/index.vue
  38. 44 0
      src/components/Hamburger/index.vue
  39. 146 0
      src/components/Marqueebox/index.vue
  40. 42 0
      src/components/SvgIcon/index.vue
  41. 36 0
      src/components/TreeMenu/index.vue
  42. 82 0
      src/components/complexTable/index.vue
  43. 9 0
      src/icons/index.js
  44. 1 0
      src/icons/svg/Department.svg
  45. 1 0
      src/icons/svg/doctor.svg
  46. 1 0
      src/icons/svg/example.svg
  47. 1 0
      src/icons/svg/eye.svg
  48. 1 0
      src/icons/svg/form.svg
  49. 1 0
      src/icons/svg/hospital.svg
  50. 1 0
      src/icons/svg/instrument.svg
  51. 1 0
      src/icons/svg/list.svg
  52. 1 0
      src/icons/svg/msgvc.svg
  53. 1 0
      src/icons/svg/nested.svg
  54. 1 0
      src/icons/svg/password-view.svg
  55. 1 0
      src/icons/svg/password.svg
  56. 1 0
      src/icons/svg/peoples.svg
  57. 1 0
      src/icons/svg/table.svg
  58. 1 0
      src/icons/svg/tree.svg
  59. 1 0
      src/icons/svg/unread.svg
  60. 1 0
      src/icons/svg/user.svg
  61. 28 0
      src/main.js
  62. 58 0
      src/permission.js
  63. 119 0
      src/router/index.js
  64. 13 0
      src/store/getters.js
  65. 19 0
      src/store/index.js
  66. 43 0
      src/store/modules/app.js
  67. 58 0
      src/store/modules/permission.js
  68. 111 0
      src/store/modules/user.js
  69. 53 0
      src/styles/element-ui.scss
  70. 128 0
      src/styles/index.scss
  71. 144 0
      src/styles/loginform.scss
  72. 29 0
      src/styles/mixin.scss
  73. 106 0
      src/styles/roleuser.scss
  74. 58 0
      src/styles/sidebar.scss
  75. 32 0
      src/styles/transition.scss
  76. 4 0
      src/styles/variables.scss
  77. 13 0
      src/utils/auth.js
  78. 87 0
      src/utils/index.js
  79. 138 0
      src/utils/queryBase.js
  80. 54 0
      src/utils/queryDict.js
  81. 81 0
      src/utils/queryInfo.js
  82. 78 0
      src/utils/request.js
  83. 78 0
      src/utils/timingConstruct.js
  84. 236 0
      src/views/404.vue
  85. 3 0
      src/views/contentPub/draftList.vue
  86. 100 0
      src/views/contentPub/pubList.vue
  87. 3 0
      src/views/contentPub/recycleBin.vue
  88. 45 0
      src/views/dashboard/admin/index.vue
  89. 26 0
      src/views/dashboard/index.vue
  90. 100 0
      src/views/demandCen/closedList.vue
  91. 100 0
      src/views/demandCen/completedList.vue
  92. 100 0
      src/views/demandCen/expiredList.vue
  93. 100 0
      src/views/demandCen/publishedList.vue
  94. 246 0
      src/views/findPwd/index.vue
  95. 86 0
      src/views/layout/Layout.vue
  96. 28 0
      src/views/layout/components/AppMain.vue
  97. 67 0
      src/views/layout/components/Navbar.vue
  98. 78 0
      src/views/layout/components/Sidebar/SidebarItem.vue
  99. 28 0
      src/views/layout/components/Sidebar/index.vue
  100. 43 0
      src/views/layout/components/Sidebar2.vue
  101. 132 0
      src/views/layout/components/TopNavbar.vue
  102. 4 0
      src/views/layout/components/index.js
  103. 41 0
      src/views/layout/mixin/ResizeHandler.js
  104. 145 0
      src/views/login/index.vue
  105. 0 0
      static/.gitkeep
  106. BIN
      static/login_bg.jpg
  107. 224 0
      static/menu.json
  108. BIN
      static/touchwave.png

+ 12 - 0
.babelrc

@ -0,0 +1,12 @@
1
{
2
  "presets": [
3
    ["env", {
4
      "modules": false,
5
      "targets": {
6
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7
      }
8
    }],
9
    "stage-2"
10
  ],
11
  "plugins":["transform-vue-jsx", "transform-runtime"]
12
}

+ 14 - 0
.editorconfig

@ -0,0 +1,14 @@
1
# http://editorconfig.org
2
root = true
3
4
[*]
5
charset = utf-8
6
indent_style = space
7
indent_size = 2
8
end_of_line = lf
9
insert_final_newline = true
10
trim_trailing_whitespace = true
11
12
[*.md]
13
insert_final_newline = false
14
trim_trailing_whitespace = false

+ 3 - 0
.eslintignore

@ -0,0 +1,3 @@
1
build/*.js
2
config/*.js
3
src/assets

+ 198 - 0
.eslintrc.js

@ -0,0 +1,198 @@
1
module.exports = {
2
  root: true,
3
  parser: 'babel-eslint',
4
  parserOptions: {
5
    sourceType: 'module'
6
  },
7
  env: {
8
    browser: true,
9
    node: true,
10
    es6: true,
11
  },
12
  extends: 'eslint:recommended',
13
  // required to lint *.vue files
14
  plugins: [
15
    'html'
16
  ],
17
  // check if imports actually resolve
18
  'settings': {
19
    'import/resolver': {
20
      'webpack': {
21
        'config': 'build/webpack.base.conf.js'
22
      }
23
    }
24
  },
25
  // add your custom rules here
26
  //it is base on https://github.com/vuejs/eslint-config-vue
27
  rules: {
28
    'accessor-pairs': 2,
29
    'arrow-spacing': [2, {
30
      'before': true,
31
      'after': true
32
    }],
33
    'block-spacing': [2, 'always'],
34
    'brace-style': [2, '1tbs', {
35
      'allowSingleLine': true
36
    }],
37
    'camelcase': [0, {
38
      'properties': 'always'
39
    }],
40
    'comma-dangle': [2, 'never'],
41
    'comma-spacing': [2, {
42
      'before': false,
43
      'after': true
44
    }],
45
    'comma-style': [2, 'last'],
46
    'constructor-super': 2,
47
    'curly': [2, 'multi-line'],
48
    'dot-location': [2, 'property'],
49
    'eol-last': 2,
50
    'eqeqeq': [2, 'allow-null'],
51
    'generator-star-spacing': [2, {
52
      'before': true,
53
      'after': true
54
    }],
55
    'handle-callback-err': [2, '^(err|error)$'],
56
    'indent': [2, 2, {
57
      'SwitchCase': 1
58
    }],
59
    'jsx-quotes': [2, 'prefer-single'],
60
    'key-spacing': [2, {
61
      'beforeColon': false,
62
      'afterColon': true
63
    }],
64
    'keyword-spacing': [2, {
65
      'before': true,
66
      'after': true
67
    }],
68
    'new-cap': [2, {
69
      'newIsCap': true,
70
      'capIsNew': false
71
    }],
72
    'new-parens': 2,
73
    'no-array-constructor': 2,
74
    'no-caller': 2,
75
    'no-console': 'off',
76
    'no-class-assign': 2,
77
    'no-cond-assign': 2,
78
    'no-const-assign': 2,
79
    'no-control-regex': 2,
80
    'no-delete-var': 2,
81
    'no-dupe-args': 2,
82
    'no-dupe-class-members': 2,
83
    'no-dupe-keys': 2,
84
    'no-duplicate-case': 2,
85
    'no-empty-character-class': 2,
86
    'no-empty-pattern': 2,
87
    'no-eval': 2,
88
    'no-ex-assign': 2,
89
    'no-extend-native': 2,
90
    'no-extra-bind': 2,
91
    'no-extra-boolean-cast': 2,
92
    'no-extra-parens': [2, 'functions'],
93
    'no-fallthrough': 2,
94
    'no-floating-decimal': 2,
95
    'no-func-assign': 2,
96
    'no-implied-eval': 2,
97
    'no-inner-declarations': [2, 'functions'],
98
    'no-invalid-regexp': 2,
99
    'no-irregular-whitespace': 2,
100
    'no-iterator': 2,
101
    'no-label-var': 2,
102
    'no-labels': [2, {
103
      'allowLoop': false,
104
      'allowSwitch': false
105
    }],
106
    'no-lone-blocks': 2,
107
    'no-mixed-spaces-and-tabs': 2,
108
    'no-multi-spaces': 2,
109
    'no-multi-str': 2,
110
    'no-multiple-empty-lines': [2, {
111
      'max': 1
112
    }],
113
    'no-native-reassign': 2,
114
    'no-negated-in-lhs': 2,
115
    'no-new-object': 2,
116
    'no-new-require': 2,
117
    'no-new-symbol': 2,
118
    'no-new-wrappers': 2,
119
    'no-obj-calls': 2,
120
    'no-octal': 2,
121
    'no-octal-escape': 2,
122
    'no-path-concat': 2,
123
    'no-proto': 2,
124
    'no-redeclare': 2,
125
    'no-regex-spaces': 2,
126
    'no-return-assign': [2, 'except-parens'],
127
    'no-self-assign': 2,
128
    'no-self-compare': 2,
129
    'no-sequences': 2,
130
    'no-shadow-restricted-names': 2,
131
    'no-spaced-func': 2,
132
    'no-sparse-arrays': 2,
133
    'no-this-before-super': 2,
134
    'no-throw-literal': 2,
135
    'no-trailing-spaces': 2,
136
    'no-undef': 2,
137
    'no-undef-init': 2,
138
    'no-unexpected-multiline': 2,
139
    'no-unmodified-loop-condition': 2,
140
    'no-unneeded-ternary': [2, {
141
      'defaultAssignment': false
142
    }],
143
    'no-unreachable': 2,
144
    'no-unsafe-finally': 2,
145
    'no-unused-vars': [2, {
146
      'vars': 'all',
147
      'args': 'none'
148
    }],
149
    'no-useless-call': 2,
150
    'no-useless-computed-key': 2,
151
    'no-useless-constructor': 2,
152
    'no-useless-escape': 0,
153
    'no-whitespace-before-property': 2,
154
    'no-with': 2,
155
    'one-var': [2, {
156
      'initialized': 'never'
157
    }],
158
    'operator-linebreak': [2, 'after', {
159
      'overrides': {
160
        '?': 'before',
161
        ':': 'before'
162
      }
163
    }],
164
    'padded-blocks': [2, 'never'],
165
    'quotes': [2, 'single', {
166
      'avoidEscape': true,
167
      'allowTemplateLiterals': true
168
    }],
169
    'semi': [2, 'never'],
170
    'semi-spacing': [2, {
171
      'before': false,
172
      'after': true
173
    }],
174
    'space-before-blocks': [2, 'always'],
175
    'space-before-function-paren': [2, 'never'],
176
    'space-in-parens': [2, 'never'],
177
    'space-infix-ops': 2,
178
    'space-unary-ops': [2, {
179
      'words': true,
180
      'nonwords': false
181
    }],
182
    'spaced-comment': [2, 'always', {
183
      'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
184
    }],
185
    'template-curly-spacing': [2, 'never'],
186
    'use-isnan': 2,
187
    'valid-typeof': 2,
188
    'wrap-iife': [2, 'any'],
189
    'yield-star-spacing': [2, 'both'],
190
    'yoda': [2, 'never'],
191
    'prefer-const': 2,
192
    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
193
    'object-curly-spacing': [2, 'always', {
194
      objectsInObjects: false
195
    }],
196
    'array-bracket-spacing': [2, 'never']
197
  }
198
}

+ 15 - 0
.gitignore

@ -0,0 +1,15 @@
1
.DS_Store
2
node_modules/
3
dist/
4
npm-debug.log*
5
yarn-debug.log*
6
yarn-error.log*
7
package-lock.json
8
9
# Editor directories and files
10
.idea
11
.vscode
12
*.suo
13
*.ntvs*
14
*.njsproj
15
*.sln

+ 10 - 0
.postcssrc.js

@ -0,0 +1,10 @@
1
// https://github.com/michael-ciniawsky/postcss-load-config
2
3
module.exports = {
4
  "plugins": {
5
    "postcss-import": {},
6
    "postcss-url": {},
7
    // to edit target browsers: use "browserslist" field in package.json
8
    "autoprefixer": {}
9
  }
10
}

+ 28 - 0
.project

@ -0,0 +1,28 @@
1
<?xml version="1.0" encoding="UTF-8"?>
2
<projectDescription>
3
	<name>touchwave</name>
4
	<comment></comment>
5
	<projects>
6
	</projects>
7
	<buildSpec>
8
		<buildCommand>
9
			<name>com.aptana.ide.core.unifiedBuilder</name>
10
			<arguments>
11
			</arguments>
12
		</buildCommand>
13
	</buildSpec>
14
	<natures>
15
		<nature>com.aptana.projects.webnature</nature>
16
	</natures>
17
	<filteredResources>
18
		<filter>
19
			<id>1536728706163</id>
20
			<name></name>
21
			<type>26</type>
22
			<matcher>
23
				<id>org.eclipse.ui.ide.multiFilter</id>
24
				<arguments>1.0-name-matches-false-false-node_modules</arguments>
25
			</matcher>
26
		</filter>
27
	</filteredResources>
28
</projectDescription>

+ 5 - 0
.travis.yml

@ -0,0 +1,5 @@
1
language: node_js
2
node_js: stable
3
script: npm run test
4
notifications:
5
  email: false

+ 0 - 0
README.md


+ 41 - 0
build/build.js

@ -0,0 +1,41 @@
1
'use strict'
2
require('./check-versions')()
3
4
process.env.NODE_ENV = 'production'
5
6
const ora = require('ora')
7
const rm = require('rimraf')
8
const path = require('path')
9
const chalk = require('chalk')
10
const webpack = require('webpack')
11
const config = require('../config')
12
const webpackConfig = require('./webpack.prod.conf')
13
14
const spinner = ora('building for production...')
15
spinner.start()
16
17
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18
  if (err) throw err
19
  webpack(webpackConfig, (err, stats) => {
20
    spinner.stop()
21
    if (err) throw err
22
    process.stdout.write(stats.toString({
23
      colors: true,
24
      modules: false,
25
      children: false,
26
      chunks: false,
27
      chunkModules: false
28
    }) + '\n\n')
29
30
    if (stats.hasErrors()) {
31
      console.log(chalk.red('  Build failed with errors.\n'))
32
      process.exit(1)
33
    }
34
35
    console.log(chalk.cyan('  Build complete.\n'))
36
    console.log(chalk.yellow(
37
      '  Tip: built files are meant to be served over an HTTP server.\n' +
38
      '  Opening index.html over file:// won\'t work.\n'
39
    ))
40
  })
41
})

+ 54 - 0
build/check-versions.js

@ -0,0 +1,54 @@
1
'use strict'
2
const chalk = require('chalk')
3
const semver = require('semver')
4
const packageConfig = require('../package.json')
5
const shell = require('shelljs')
6
7
function exec (cmd) {
8
  return require('child_process').execSync(cmd).toString().trim()
9
}
10
11
const versionRequirements = [
12
  {
13
    name: 'node',
14
    currentVersion: semver.clean(process.version),
15
    versionRequirement: packageConfig.engines.node
16
  }
17
]
18
19
if (shell.which('npm')) {
20
  versionRequirements.push({
21
    name: 'npm',
22
    currentVersion: exec('npm --version'),
23
    versionRequirement: packageConfig.engines.npm
24
  })
25
}
26
27
module.exports = function () {
28
  const warnings = []
29
30
  for (let i = 0; i < versionRequirements.length; i++) {
31
    const mod = versionRequirements[i]
32
33
    if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34
      warnings.push(mod.name + ': ' +
35
        chalk.red(mod.currentVersion) + ' should be ' +
36
        chalk.green(mod.versionRequirement)
37
      )
38
    }
39
  }
40
41
  if (warnings.length) {
42
    console.log('')
43
    console.log(chalk.yellow('To use this template, you must update following to modules:'))
44
    console.log()
45
46
    for (let i = 0; i < warnings.length; i++) {
47
      const warning = warnings[i]
48
      console.log('  ' + warning)
49
    }
50
51
    console.log()
52
    process.exit(1)
53
  }
54
}

BIN
build/logo.png


+ 101 - 0
build/utils.js

@ -0,0 +1,101 @@
1
'use strict'
2
const path = require('path')
3
const config = require('../config')
4
const ExtractTextPlugin = require('extract-text-webpack-plugin')
5
const packageConfig = require('../package.json')
6
7
exports.assetsPath = function (_path) {
8
  const assetsSubDirectory = process.env.NODE_ENV === 'production'
9
    ? config.build.assetsSubDirectory
10
    : config.dev.assetsSubDirectory
11
12
  return path.posix.join(assetsSubDirectory, _path)
13
}
14
15
exports.cssLoaders = function (options) {
16
  options = options || {}
17
18
  const cssLoader = {
19
    loader: 'css-loader',
20
    options: {
21
      sourceMap: options.sourceMap
22
    }
23
  }
24
25
  const postcssLoader = {
26
    loader: 'postcss-loader',
27
    options: {
28
      sourceMap: options.sourceMap
29
    }
30
  }
31
32
  // generate loader string to be used with extract text plugin
33
  function generateLoaders (loader, loaderOptions) {
34
    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
35
36
    if (loader) {
37
      loaders.push({
38
        loader: loader + '-loader',
39
        options: Object.assign({}, loaderOptions, {
40
          sourceMap: options.sourceMap
41
        })
42
      })
43
    }
44
45
    // Extract CSS when that option is specified
46
    // (which is the case during production build)
47
    if (options.extract) {
48
      return ExtractTextPlugin.extract({
49
        use: loaders,
50
        fallback: 'vue-style-loader'
51
      })
52
    } else {
53
      return ['vue-style-loader'].concat(loaders)
54
    }
55
  }
56
57
  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
58
  return {
59
    css: generateLoaders(),
60
    postcss: generateLoaders(),
61
    less: generateLoaders('less'),
62
    sass: generateLoaders('sass', { indentedSyntax: true }),
63
    scss: generateLoaders('sass'),
64
    stylus: generateLoaders('stylus'),
65
    styl: generateLoaders('stylus')
66
  }
67
}
68
69
// Generate loaders for standalone style files (outside of .vue)
70
exports.styleLoaders = function (options) {
71
  const output = []
72
  const loaders = exports.cssLoaders(options)
73
74
  for (const extension in loaders) {
75
    const loader = loaders[extension]
76
    output.push({
77
      test: new RegExp('\\.' + extension + '$'),
78
      use: loader
79
    })
80
  }
81
82
  return output
83
}
84
85
exports.createNotifierCallback = () => {
86
  const notifier = require('node-notifier')
87
88
  return (severity, errors) => {
89
    if (severity !== 'error') return
90
91
    const error = errors[0]
92
    const filename = error.file && error.file.split('!').pop()
93
94
    notifier.notify({
95
      title: packageConfig.name,
96
      message: severity + ': ' + error.name,
97
      subtitle: filename || '',
98
      icon: path.join(__dirname, 'logo.png')
99
    })
100
  }
101
}

+ 22 - 0
build/vue-loader.conf.js

@ -0,0 +1,22 @@
1
'use strict'
2
const utils = require('./utils')
3
const config = require('../config')
4
const isProduction = process.env.NODE_ENV === 'production'
5
const sourceMapEnabled = isProduction
6
  ? config.build.productionSourceMap
7
  : config.dev.cssSourceMap
8
9
module.exports = {
10
  loaders: utils.cssLoaders({
11
    sourceMap: sourceMapEnabled,
12
    extract: isProduction
13
  }),
14
  cssSourceMap: sourceMapEnabled,
15
  cacheBusting: config.dev.cacheBusting,
16
  transformToRequire: {
17
    video: ['src', 'poster'],
18
    source: 'src',
19
    img: 'src',
20
    image: 'xlink:href'
21
  }
22
}

+ 100 - 0
build/webpack.base.conf.js

@ -0,0 +1,100 @@
1
'use strict'
2
const path = require('path')
3
const utils = require('./utils')
4
const config = require('../config')
5
const vueLoaderConfig = require('./vue-loader.conf')
6
7
function resolve (dir) {
8
  return path.join(__dirname, '..', dir)
9
}
10
11
const createLintingRule = () => ({
12
  test: /\.(js|vue)$/,
13
  loader: 'eslint-loader',
14
  enforce: 'pre',
15
  include: [resolve('src'), resolve('test')],
16
  options: {
17
    formatter: require('eslint-friendly-formatter'),
18
    emitWarning: !config.dev.showEslintErrorsInOverlay
19
  }
20
})
21
22
module.exports = {
23
  context: path.resolve(__dirname, '../'),
24
  entry: {
25
    app: ['babel-polyfill', './src/main.js']
26
  },
27
  output: {
28
    path: config.build.assetsRoot,
29
    filename: '[name].js',
30
    publicPath: process.env.NODE_ENV === 'production'
31
      ? config.build.assetsPublicPath
32
      : config.dev.assetsPublicPath
33
  },
34
  resolve: {
35
    extensions: ['.js', '.vue', '.json'],
36
    alias: {
37
      '@': resolve('src')
38
    }
39
  },
40
  module: {
41
    rules: [
42
      ...(config.dev.useEslint ? [createLintingRule()] : []),
43
      {
44
        test: /\.vue$/,
45
        loader: 'vue-loader',
46
        options: vueLoaderConfig
47
      },
48
      {
49
        test: /\.js$/,
50
        loader: 'babel-loader',
51
        include: [resolve('src'), resolve('test') ,resolve('node_modules/webpack-dev-server/client')]
52
      },
53
      {
54
        test: /\.svg$/,
55
        loader: 'svg-sprite-loader',
56
        include: [resolve('src/icons')],
57
        options: {
58
          symbolId: 'icon-[name]'
59
        }
60
      },
61
      {
62
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
63
        loader: 'url-loader',
64
        exclude: [resolve('src/icons')],
65
        options: {
66
          limit: 10000,
67
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
68
        }
69
      },
70
      {
71
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
72
        loader: 'url-loader',
73
        options: {
74
          limit: 10000,
75
          name: utils.assetsPath('media/[name].[hash:7].[ext]')
76
        }
77
      },
78
      {
79
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
80
        loader: 'url-loader',
81
        options: {
82
          limit: 10000,
83
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
84
        }
85
      }
86
    ]
87
  },
88
  node: {
89
    // prevent webpack from injecting useless setImmediate polyfill because Vue
90
    // source contains it (although only uses it if it's native).
91
    setImmediate: false,
92
    // prevent webpack from injecting mocks to Node native modules
93
    // that does not make sense for the client
94
    dgram: 'empty',
95
    fs: 'empty',
96
    net: 'empty',
97
    tls: 'empty',
98
    child_process: 'empty'
99
  }
100
}

+ 86 - 0
build/webpack.dev.conf.js

@ -0,0 +1,86 @@
1
'use strict'
2
const path = require('path')
3
const utils = require('./utils')
4
const webpack = require('webpack')
5
const config = require('../config')
6
const merge = require('webpack-merge')
7
const baseWebpackConfig = require('./webpack.base.conf')
8
const HtmlWebpackPlugin = require('html-webpack-plugin')
9
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
10
const portfinder = require('portfinder')
11
12
function resolve (dir) {
13
  return path.join(__dirname, '..', dir)
14
}
15
16
const HOST = process.env.HOST
17
const PORT = process.env.PORT && Number(process.env.PORT)
18
19
const devWebpackConfig = merge(baseWebpackConfig, {
20
  module: {
21
    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
22
  },
23
  // cheap-module-eval-source-map is faster for development
24
  devtool: config.dev.devtool,
25
26
  // these devServer options should be customized in /config/index.js
27
  devServer: {
28
    clientLogLevel: 'warning',
29
    historyApiFallback: true,
30
    hot: true,
31
    compress: true,
32
    host: HOST || config.dev.host,
33
    port: PORT || config.dev.port,
34
    open: config.dev.autoOpenBrowser,
35
    overlay: config.dev.errorOverlay
36
      ? { warnings: false, errors: true }
37
      : false,
38
    publicPath: config.dev.assetsPublicPath,
39
    proxy: config.dev.proxyTable,
40
    quiet: true, // necessary for FriendlyErrorsPlugin
41
    watchOptions: {
42
      poll: config.dev.poll,
43
    }
44
  },
45
  plugins: [
46
    new webpack.DefinePlugin({
47
      'process.env': require('../config/dev.env')
48
    }),
49
    new webpack.HotModuleReplacementPlugin(),
50
    new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
51
    new webpack.NoEmitOnErrorsPlugin(),
52
    // https://github.com/ampedandwired/html-webpack-plugin
53
    new HtmlWebpackPlugin({
54
      filename: 'index.html',
55
      template: 'index.html',
56
      inject: true,
57
      favicon: resolve('favicon.ico')
58
    })
59
  ]
60
})
61
62
module.exports = new Promise((resolve, reject) => {
63
  portfinder.basePort = process.env.PORT || config.dev.port
64
  portfinder.getPort((err, port) => {
65
    if (err) {
66
      reject(err)
67
    } else {
68
      // publish the new Port, necessary for e2e tests
69
      process.env.PORT = port
70
      // add port to devServer config
71
      devWebpackConfig.devServer.port = port
72
73
      // Add FriendlyErrorsPlugin
74
      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
75
        compilationSuccessInfo: {
76
          messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
77
        },
78
        onErrors: config.dev.notifyOnErrors
79
        ? utils.createNotifierCallback()
80
        : undefined
81
      }))
82
83
      resolve(devWebpackConfig)
84
    }
85
  })
86
})

+ 156 - 0
build/webpack.prod.conf.js

@ -0,0 +1,156 @@
1
'use strict'
2
const path = require('path')
3
const utils = require('./utils')
4
const webpack = require('webpack')
5
const config = require('../config')
6
const merge = require('webpack-merge')
7
const baseWebpackConfig = require('./webpack.base.conf')
8
const CopyWebpackPlugin = require('copy-webpack-plugin')
9
const HtmlWebpackPlugin = require('html-webpack-plugin')
10
const ExtractTextPlugin = require('extract-text-webpack-plugin')
11
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
12
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
13
14
function resolve (dir) {
15
  return path.join(__dirname, '..', dir)
16
}
17
18
const env = require('../config/prod.env')
19
20
const webpackConfig = merge(baseWebpackConfig, {
21
  module: {
22
    rules: utils.styleLoaders({
23
      sourceMap: config.build.productionSourceMap,
24
      extract: true,
25
      usePostCSS: true
26
    })
27
  },
28
  devtool: config.build.productionSourceMap ? config.build.devtool : false,
29
  output: {
30
    path: config.build.assetsRoot,
31
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
32
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
33
  },
34
  plugins: [
35
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
36
    new webpack.DefinePlugin({
37
      'process.env': env
38
    }),
39
    new UglifyJsPlugin({
40
      uglifyOptions: {
41
        compress: {
42
          warnings: false
43
        }
44
      },
45
      sourceMap: config.build.productionSourceMap,
46
      parallel: true
47
    }),
48
    // extract css into its own file
49
    new ExtractTextPlugin({
50
      filename: utils.assetsPath('css/[name].[contenthash].css'),
51
      // Setting the following option to `false` will not extract CSS from codesplit chunks.
52
      // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
53
      // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
54
      allChunks: false,
55
    }),
56
    // Compress extracted CSS. We are using this plugin so that possible
57
    // duplicated CSS from different components can be deduped.
58
    new OptimizeCSSPlugin({
59
      cssProcessorOptions: config.build.productionSourceMap
60
        ? { safe: true, map: { inline: false } }
61
        : { safe: true }
62
    }),
63
    // generate dist index.html with correct asset hash for caching.
64
    // you can customize output by editing /index.html
65
    // see https://github.com/ampedandwired/html-webpack-plugin
66
    new HtmlWebpackPlugin({
67
      filename: config.build.index,
68
      template: 'index.html',
69
      inject: true,
70
      favicon: resolve('favicon.ico'),
71
      minify: {
72
        removeComments: true,
73
        collapseWhitespace: true,
74
        removeAttributeQuotes: true
75
        // more options:
76
        // https://github.com/kangax/html-minifier#options-quick-reference
77
      },
78
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
79
      chunksSortMode: 'dependency'
80
    }),
81
    // keep module.id stable when vender modules does not change
82
    new webpack.HashedModuleIdsPlugin(),
83
    // enable scope hoisting
84
    new webpack.optimize.ModuleConcatenationPlugin(),
85
    // split vendor js into its own file
86
    new webpack.optimize.CommonsChunkPlugin({
87
      name: 'vendor',
88
      minChunks (module) {
89
        // any required modules inside node_modules are extracted to vendor
90
        return (
91
          module.resource &&
92
          /\.js$/.test(module.resource) &&
93
          module.resource.indexOf(
94
            path.join(__dirname, '../node_modules')
95
          ) === 0
96
        )
97
      }
98
    }),
99
    // extract webpack runtime and module manifest to its own file in order to
100
    // prevent vendor hash from being updated whenever app bundle is updated
101
    new webpack.optimize.CommonsChunkPlugin({
102
      name: 'manifest',
103
      minChunks: Infinity
104
    }),
105
    // This instance extracts shared chunks from code splitted chunks and bundles them
106
    // in a separate chunk, similar to the vendor chunk
107
    // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
108
    new webpack.optimize.CommonsChunkPlugin({
109
      name: 'app',
110
      async: 'vendor-async',
111
      children: true,
112
      minChunks: 3
113
    }),
114
    // split echarts into its own file
115
    new webpack.optimize.CommonsChunkPlugin({
116
      async: 'echarts',
117
      minChunks(module) {
118
        var context = module.context;
119
        return context && (context.indexOf('echarts') >= 0 || context.indexOf('zrender') >= 0);
120
      }
121
    }),
122
    // copy custom static assets
123
    new CopyWebpackPlugin([
124
      {
125
        from: path.resolve(__dirname, '../static'),
126
        to: config.build.assetsSubDirectory,
127
        ignore: ['.*']
128
      }
129
    ])
130
  ]
131
})
132
133
if (config.build.productionGzip) {
134
  const CompressionWebpackPlugin = require('compression-webpack-plugin')
135
136
  webpackConfig.plugins.push(
137
    new CompressionWebpackPlugin({
138
      asset: '[path].gz[query]',
139
      algorithm: 'gzip',
140
      test: new RegExp(
141
        '\\.(' +
142
        config.build.productionGzipExtensions.join('|') +
143
        ')$'
144
      ),
145
      threshold: 10240,
146
      minRatio: 0.8
147
    })
148
  )
149
}
150
151
if (config.build.bundleAnalyzerReport) {
152
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
153
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
154
}
155
156
module.exports = webpackConfig

+ 8 - 0
config/dev.env.js

@ -0,0 +1,8 @@
1
'use strict'
2
const merge = require('webpack-merge')
3
const prodEnv = require('./prod.env')
4
5
module.exports = merge(prodEnv, {
6
  NODE_ENV: '"development"',
7
  BASE_API: '""'
8
})

+ 87 - 0
config/index.js

@ -0,0 +1,87 @@
1
'use strict'
2
3
const path = require('path')
4
5
module.exports = {
6
  dev: {
7
8
    // Paths
9
    assetsSubDirectory: 'static',
10
    assetsPublicPath: '/',
11
    proxyTable: {},
12
13
    // Various Dev Server settings
14
    host: 'localhost', // can be overwritten by process.env.HOST
15
    port: 8055, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
16
    autoOpenBrowser: false,
17
    errorOverlay: true,
18
    notifyOnErrors: false,
19
    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
20
21
    // Use Eslint Loader?
22
    // If true, your code will be linted during bundling and
23
    // linting errors and warnings will be shown in the console.
24
    useEslint: true,
25
    // If true, eslint errors and warnings will also be shown in the error overlay
26
    // in the browser.
27
    showEslintErrorsInOverlay: false,
28
29
    /**
30
     * Source Maps
31
     */
32
33
    // https://webpack.js.org/configuration/devtool/#development
34
    devtool: 'cheap-module-eval-source-map',
35
36
    // If you have problems debugging vue-files in devtools,
37
    // set this to false - it *may* help
38
    // https://vue-loader.vuejs.org/en/options.html#cachebusting
39
    cacheBusting: true,
40
41
    // CSS Sourcemaps off by default because relative paths are "buggy"
42
    // with this option, according to the CSS-Loader README
43
    // (https://github.com/webpack/css-loader#sourcemaps)
44
    // In our experience, they generally work as expected,
45
    // just be aware of this issue when enabling this option.
46
    cssSourceMap: false,
47
  },
48
49
  build: {
50
    // Template for index.html
51
    index: path.resolve(__dirname, '../dist/index.html'),
52
53
    // Paths
54
    assetsRoot: path.resolve(__dirname, '../dist'),
55
    assetsSubDirectory: 'static',
56
57
    /**
58
     * You can set by youself according to actual condition
59
     * You will need to set this if you plan to deploy your site under a sub path,
60
     * for example GitHub pages. If you plan to deploy your site to https://foo.github.io/bar/,
61
     * then assetsPublicPath should be set to "/bar/".
62
     * In most cases please use '/' !!!
63
     */
64
    assetsPublicPath: '/', // If you are deployed on the root path, please use '/'
65
66
    /**
67
     * Source Maps
68
     */
69
70
    productionSourceMap: true,
71
    // https://webpack.js.org/configuration/devtool/#production
72
    devtool: '#source-map',
73
74
    // Gzip off by default as many popular static hosts such as
75
    // Surge or Netlify already gzip all static assets for you.
76
    // Before setting to `true`, make sure to:
77
    // npm install --save-dev compression-webpack-plugin
78
    productionGzip: false,
79
    productionGzipExtensions: ['js', 'css'],
80
81
    // Run the build command with an extra argument to
82
    // View the bundle analyzer report after build finishes:
83
    // `npm run build --report`
84
    // Set to `true` or `false` to always turn it on or off
85
    bundleAnalyzerReport: process.env.npm_config_report
86
  }
87
}

+ 5 - 0
config/prod.env.js

@ -0,0 +1,5 @@
1
'use strict'
2
module.exports = {
3
  NODE_ENV: '"production"',
4
  BASE_API: '""'
5
}

BIN
favicon.ico


+ 13 - 0
index.html

@ -0,0 +1,13 @@
1
<!DOCTYPE html>
2
<html>
3
  <head>
4
    <meta charset="utf-8">
5
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
6
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
7
    <title>科袖科技条件平台_后台管理系统</title>
8
  </head>
9
  <body>
10
    <div id="app"></div>
11
    <!-- built files will be auto injected -->
12
  </body>
13
</html>

+ 82 - 0
package.json

@ -0,0 +1,82 @@
1
{
2
  "name": "plat-admin",
3
  "version": "1.0.0",
4
  "description": "A vue admin template with Element UI & axios & iconfont & permission control & lint",
5
  "author": "luyanan <1271778060@qq.com>",
6
  "private": true,
7
  "scripts": {
8
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
9
    "start": "npm run dev",
10
    "build": "node build/build.js",
11
    "build:report": "npm_config_report=true node build/build.js",
12
    "lint": "eslint --ext .js,.vue src",
13
    "test": "npm run lint"
14
  },
15
  "dependencies": {
16
    "axios": "0.17.1",
17
    "babel-polyfill": "^6.26.0",
18
    "echarts": "3.8.5",
19
    "element-ui": "2.3.4",
20
    "js-cookie": "2.2.0",
21
    "normalize.css": "7.0.0",
22
    "nprogress": "0.2.0",
23
    "vue": "2.5.10",
24
    "vue-router": "3.0.1",
25
    "vuex": "3.0.1"
26
  },
27
  "devDependencies": {
28
    "autoprefixer": "7.2.3",
29
    "babel-core": "6.26.0",
30
    "babel-eslint": "8.0.3",
31
    "babel-helper-vue-jsx-merge-props": "2.0.3",
32
    "babel-loader": "7.1.2",
33
    "babel-plugin-syntax-jsx": "6.18.0",
34
    "babel-plugin-transform-runtime": "6.23.0",
35
    "babel-plugin-transform-vue-jsx": "3.5.0",
36
    "babel-preset-env": "1.6.1",
37
    "babel-preset-stage-2": "6.24.1",
38
    "chalk": "2.3.0",
39
    "copy-webpack-plugin": "4.2.3",
40
    "css-loader": "0.28.7",
41
    "eslint": "4.13.1",
42
    "eslint-friendly-formatter": "3.0.0",
43
    "eslint-loader": "1.9.0",
44
    "eslint-plugin-html": "4.0.1",
45
    "eventsource-polyfill": "0.9.6",
46
    "extract-text-webpack-plugin": "3.0.2",
47
    "file-loader": "1.1.5",
48
    "friendly-errors-webpack-plugin": "1.6.1",
49
    "html-webpack-plugin": "2.30.1",
50
    "node-notifier": "5.1.2",
51
    "node-sass": "^4.7.2",
52
    "optimize-css-assets-webpack-plugin": "3.2.0",
53
    "ora": "1.3.0",
54
    "portfinder": "1.0.13",
55
    "postcss-import": "11.0.0",
56
    "postcss-loader": "2.0.9",
57
    "postcss-url": "7.3.0",
58
    "rimraf": "2.6.2",
59
    "sass-loader": "6.0.6",
60
    "semver": "5.4.1",
61
    "shelljs": "0.7.8",
62
    "svg-sprite-loader": "3.5.2",
63
    "uglifyjs-webpack-plugin": "1.1.3",
64
    "url-loader": "0.6.2",
65
    "vue-loader": "13.7.2",
66
    "vue-style-loader": "3.0.3",
67
    "vue-template-compiler": "2.5.10",
68
    "webpack": "3.10.0",
69
    "webpack-bundle-analyzer": "2.9.1",
70
    "webpack-dev-server": "2.9.7",
71
    "webpack-merge": "4.1.1"
72
  },
73
  "engines": {
74
    "node": ">= 4.0.0",
75
    "npm": ">= 3.0.0"
76
  },
77
  "browserslist": [
78
    "> 1%",
79
    "last 2 versions",
80
    "not ie <= 8"
81
  ]
82
}

+ 11 - 0
src/App.vue

@ -0,0 +1,11 @@
1
<template>
2
  <div id="app">
3
    <router-view></router-view>
4
  </div>
5
</template>
6
7
<script>
8
export default {
9
  name: 'App'
10
}
11
</script>

+ 81 - 0
src/api/bridge.js

@ -0,0 +1,81 @@
1
import request from '@/utils/request'
2
3
/*  添加桥梁 */
4
export function addDevice(params) {
5
  return request({
6
    url: '/ajax/bridge',
7
    method: 'post',
8
    data: params
9
  })
10
}
11
12
/*  更新桥梁信息 */
13
export function updateDevice(params) {
14
  return request({
15
    url: '/ajax/bridge/update',
16
    method: 'post',
17
    data: params
18
  })
19
}
20
21
/*  删除桥梁信息 */
22
export function deleteDevice(params) {
23
  return request({
24
    url: '/ajax/bridge/delete',
25
    method: 'get',
26
    params
27
  })
28
}
29
30
/*  查询单个桥梁 */
31
export function queryDevice(params) {
32
  return request({
33
    url: '/ajax/bridge/qo',
34
    method: 'get',
35
    params
36
  })
37
}
38
39
/*  分页查询桥梁 */
40
export function pageQueryDevice(params) {
41
  return request({
42
    url: '/ajax/bridge/pq',
43
    method: 'get',
44
    params
45
  })
46
}
47
48
/*  校验桥梁编号 */
49
export function checkDeviceCode(params) {
50
  return request({
51
    url: '/ajax/bridge/checkCode',
52
    method: 'get',
53
    params
54
  })
55
}
56
57
/*  校验桥梁简称 */
58
export function checkBridgeShortName(params) {
59
  return request({
60
    url: '/ajax/bridge/checkShortName',
61
    method: 'get',
62
    params
63
  })
64
}
65
66
/*  校验桥梁全称 */
67
export function checkBridgeName(params) {
68
  return request({
69
    url: '/ajax/bridge/checkName',
70
    method: 'get',
71
    params
72
  })
73
}
74
75
/*  上传图片 */
76
export function uploadBridgeImg() {
77
  return request({
78
    url: '/ajax/bridge/upload',
79
    method: 'post'
80
  })
81
}

+ 90 - 0
src/api/bridgeInfo.js

@ -0,0 +1,90 @@
1
import request from '@/utils/request'
2
3
export function getBridgeList(params) { // 用户所有桥梁
4
  return request({
5
    url: '/ajax/bridge/byUser',
6
    method: 'get',
7
    params
8
  })
9
}
10
11
export function getBridgeInfo(params) { // 桥梁信息
12
  return request({
13
    url: '/ajax/bridge/qo',
14
    method: 'get',
15
    params
16
  })
17
}
18
19
export function getBridgeServers(params) { // 桥梁服务器
20
  return request({
21
    url: '/ajax/server/byBridge',
22
    method: 'get',
23
    params
24
  })
25
}
26
27
// 报警信息
28
export function getDangerList(params) {
29
  return request({
30
    url: '/ajax/alarm/msg',
31
    method: 'get',
32
    params
33
  })
34
}
35
export function getDangerDetail(params) {
36
  return request({
37
    url: '/ajax/alarm/detail',
38
    method: 'get',
39
    params
40
  })
41
}
42
// 报警信息
43
44
// 未读报警
45
export function getBridgeUnread(params) {
46
  return request({
47
    url: '/ajax/alarm/msg/unread',
48
    method: 'get',
49
    params
50
  })
51
}
52
export function setUnreadToRead(params) {
53
  return request({
54
    url: '/ajax/alarm/msg/read',
55
    method: 'post',
56
    data: params
57
  })
58
}
59
// 未读报警
60
61
// 监测信息
62
export function getMonitorByDay(params) {
63
  return request({
64
    url: '/ajax/collect/wave/server/day',
65
    method: 'get',
66
    params
67
  })
68
}
69
export function getSysTime(params) {
70
  return request({
71
    url: '/ajax/sys/serviceTime',
72
    method: 'get',
73
    params
74
  })
75
}
76
export function getMonitorByTime(params) {
77
  return request({
78
    url: '/ajax/collect/wave/server/time',
79
    method: 'get',
80
    params
81
  })
82
}
83
export function getTimingMonitor(params) {
84
  return request({
85
    url: '/ajax/collect/wave/curr',
86
    method: 'get',
87
    params
88
  })
89
}
90
// 监测信息

+ 73 - 0
src/api/collectionbox.js

@ -0,0 +1,73 @@
1
import request from '@/utils/request'
2
3
/*  添加采集盒 */
4
export function addDevice(params) {
5
  return request({
6
    url: '/ajax/device',
7
    method: 'post',
8
    data: params
9
  })
10
}
11
12
/*  更新采集盒信息 */
13
export function updateDevice(params) {
14
  return request({
15
    url: '/ajax/device/update',
16
    method: 'post',
17
    data: params
18
  })
19
}
20
21
/*  删除采集盒信息 */
22
export function deleteDevice(params) {
23
  return request({
24
    url: '/ajax/device/delete',
25
    method: 'get',
26
    params
27
  })
28
}
29
30
/*  查询单个采集盒 */
31
export function queryDevice(params) {
32
  return request({
33
    url: '/ajax/device/qo',
34
    method: 'get',
35
    params
36
  })
37
}
38
39
/*  分页查询采集盒 */
40
export function pageQueryDevice(params) {
41
  return request({
42
    url: '/ajax/device/pq',
43
    method: 'get',
44
    params
45
  })
46
}
47
48
/*  采集盒所属服务器编号列表 */
49
export function DeviceOfservice(params) {
50
  return request({
51
    url: '/ajax/server/listByCode',
52
    method: 'get',
53
    params
54
  })
55
}
56
57
/*  校验采集盒编号 */
58
export function checkDeviceCode(params) {
59
  return request({
60
    url: '/ajax/device/checkCode',
61
    method: 'get',
62
    params
63
  })
64
}
65
66
/*  校验采集盒内部编号 */
67
export function checkDeviceInternalCode(params) {
68
  return request({
69
    url: '/ajax/device/checkSeq',
70
    method: 'get',
71
    params
72
  })
73
}

+ 97 - 0
src/api/login.js

@ -0,0 +1,97 @@
1
import request from '@/utils/request'
2
3
export function login(account, pw, vc) {
4
  return request({
5
    url: '/ajax/sys/login',
6
    method: 'post',
7
    data: {
8
      account,
9
      pw,
10
      vc
11
    }
12
  })
13
}
14
15
export function getInfo() {
16
  return request({
17
    url: '/ajax/sys/user',
18
    method: 'get'
19
  })
20
}
21
22
export function logout() {
23
  return request({
24
    url: '/ajax/sys/logout',
25
    method: 'get'
26
  })
27
}
28
29
export function isReg(params) {
30
  return request({
31
    url: '/ajax/sys/check',
32
    method: 'get',
33
    params
34
  })
35
}
36
37
// 找回密码
38
export function getResetMsgPhone(params) {
39
  return request({
40
    url: '/ajax/sys/resetPwMobile',
41
    method: 'get',
42
    params
43
  })
44
}
45
46
export function resetPwdByTel(pw, vc) {
47
  return request({
48
    url: '/ajax/sys/resetPasswordWithMobilePhone',
49
    method: 'post',
50
    data: {
51
      pw,
52
      vc
53
    }
54
  })
55
}
56
57
// 修改密码
58
export function changePw(params) {
59
  return request({
60
    url: '/ajax/sys/changePw',
61
    method: 'post',
62
    data: params
63
  })
64
}
65
66
// 获取修改个人信息
67
export function getMyself(params) {
68
  return request({
69
    url: '/ajax/sys/qo',
70
    method: 'get',
71
    params
72
  })
73
}
74
75
export function updateMyself(params) {
76
  return request({
77
    url: '/ajax/sys/update',
78
    method: 'post',
79
    data: params
80
  })
81
}
82
83
// 获取公告信息
84
export function getNotice() {
85
  return request({
86
    url: '/ajax/sys/notice',
87
    method: 'get'
88
  })
89
}
90
91
export function updateNotice(params) {
92
  return request({
93
    url: '/ajax/sys/notice',
94
    method: 'post',
95
    data: params
96
  })
97
}

+ 5 - 0
src/api/pictureVc.js

@ -0,0 +1,5 @@
1
import { comUrl } from '@/utils/index'
2
3
export function getPictureVC(flag) {
4
  return comUrl + '/ajax/PictureVC?t=' + new Date().getTime() + '&flag=' + flag + '&__timeout=' + 3 * 1000 * 60
5
}

+ 73 - 0
src/api/sensor.js

@ -0,0 +1,73 @@
1
import request from '@/utils/request'
2
3
/*  添加传感器 */
4
export function addDevice(params) {
5
  return request({
6
    url: '/ajax/transducer',
7
    method: 'post',
8
    data: params
9
  })
10
}
11
12
/*  更新传感器信息 */
13
export function updateDevice(params) {
14
  return request({
15
    url: '/ajax/transducer/update',
16
    method: 'post',
17
    data: params
18
  })
19
}
20
21
/*  删除传感器信息 */
22
export function deleteDevice(params) {
23
  return request({
24
    url: '/ajax/transducer/delete',
25
    method: 'get',
26
    params
27
  })
28
}
29
30
/*  查询单个传感器 */
31
export function queryDevice(params) {
32
  return request({
33
    url: '/ajax/transducer/qo',
34
    method: 'get',
35
    params
36
  })
37
}
38
39
/*  分页查询传感器 */
40
export function pageQueryDevice(params) {
41
  return request({
42
    url: '/ajax/transducer/pq',
43
    method: 'get',
44
    params
45
  })
46
}
47
48
/*  传感器所属采集盒编号列表 */
49
export function DeviceOfservice(params) {
50
  return request({
51
    url: '/ajax/device/listByCode',
52
    method: 'get',
53
    params
54
  })
55
}
56
57
/*  校验传感器编号 */
58
export function checkDeviceCode(params) {
59
  return request({
60
    url: '/ajax/transducer/checkCode',
61
    method: 'get',
62
    params
63
  })
64
}
65
66
/*  校验传感器内部编号 */
67
export function checkDeviceInternalCode(params) {
68
  return request({
69
    url: '/ajax/transducer/checkSeq',
70
    method: 'get',
71
    params
72
  })
73
}

+ 73 - 0
src/api/server.js

@ -0,0 +1,73 @@
1
import request from '@/utils/request'
2
3
/*  添加服务器 */
4
export function addDevice(params) {
5
  return request({
6
    url: '/ajax/server',
7
    method: 'post',
8
    data: params
9
  })
10
}
11
12
/*  更新服务器信息 */
13
export function updateDevice(params) {
14
  return request({
15
    url: '/ajax/server/update',
16
    method: 'post',
17
    data: params
18
  })
19
}
20
21
/*  删除服务器信息 */
22
export function deleteDevice(params) {
23
  return request({
24
    url: '/ajax/server/delete',
25
    method: 'get',
26
    params
27
  })
28
}
29
30
/*  查询单个服务器 */
31
export function queryDevice(params) {
32
  return request({
33
    url: '/ajax/server/qo',
34
    method: 'get',
35
    params
36
  })
37
}
38
39
/*  分页查询服务器 */
40
export function pageQueryDevice(params) {
41
  return request({
42
    url: '/ajax/server/pq',
43
    method: 'get',
44
    params
45
  })
46
}
47
48
/*  服务器所属采桥梁列表 */
49
export function DeviceOfservice(params) {
50
  return request({
51
    url: '/ajax/bridge/list',
52
    method: 'get',
53
    params
54
  })
55
}
56
57
/*  校验服务器编号 */
58
export function checkDeviceCode(params) {
59
  return request({
60
    url: '/ajax/server/checkCode',
61
    method: 'get',
62
    params
63
  })
64
}
65
66
/*  校验服务器内部编号 */
67
export function checkDeviceInternalCode(params) {
68
  return request({
69
    url: '/ajax/server/checkSeq',
70
    method: 'get',
71
    params
72
  })
73
}

+ 82 - 0
src/api/userManagemen.js

@ -0,0 +1,82 @@
1
import request from '@/utils/request'
2
3
/*  停用用户 */
4
export function deleteUser(params) {
5
  return request({
6
    url: '/ajax/sys/ban',
7
    method: 'get',
8
    params
9
  })
10
}
11
12
/*  查询负责桥梁 */
13
export function queryResponsibleBridge(params) {
14
  return request({
15
    url: '/ajax/bridge/byUserId',
16
    method: 'get',
17
    params
18
  })
19
}
20
21
/*  分页查询用户 */
22
export function pageQueryUser(params) {
23
  return request({
24
    url: '/ajax/sys/pq',
25
    method: 'get',
26
    params
27
  })
28
}
29
30
/*  检查账号是否注册 */
31
export function checkRegister(params) {
32
  return request({
33
    url: '/ajax/sys/check',
34
    method: 'get',
35
    params
36
  })
37
}
38
39
/*  新增新用户 */
40
export function addRegister(params) {
41
  return request({
42
    url: '/ajax/sys/insert',
43
    method: 'post',
44
    data: params
45
  })
46
}
47
48
/*  更新新用户 */
49
export function updateRegister(params) {
50
  return request({
51
    url: '/ajax/sys/update',
52
    method: 'post',
53
    data: params
54
  })
55
}
56
57
/*  查找用户信息 */
58
export function queryRegister(params) {
59
  return request({
60
    url: '/ajax/sys/qo',
61
    method: 'get',
62
    params
63
  })
64
}
65
66
/*  传感器所属采集盒编号列表 */
67
export function DeviceOfservice(params) {
68
  return request({
69
    url: '/ajax/bridge/list',
70
    method: 'get',
71
    params
72
  })
73
}
74
75
/*  更新用户权限 */
76
export function updatePermission(params) {
77
  return request({
78
    url: '/ajax/sys/userBridge/refresh',
79
    method: 'post',
80
    data: params
81
  })
82
}

BIN
src/assets/404_images/404.png


BIN
src/assets/404_images/404_cloud.png


+ 58 - 0
src/components/Breadcrumb/index.vue

@ -0,0 +1,58 @@
1
<template>
2
  <el-breadcrumb class="app-breadcrumb" separator="/">
3
    <transition-group name="breadcrumb">
4
      <el-breadcrumb-item v-for="(item,index)  in levelList" :key="item.path" v-if="item.meta.title">
5
        <span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{item.meta.title}}</span>
6
        <router-link v-else :to="item.redirect||item.path" replace>{{item.meta.title}}</router-link>
7
      </el-breadcrumb-item>
8
    </transition-group>
9
  </el-breadcrumb>
10
</template>
11
12
<script>
13
import Cookies from 'js-cookie'
14
export default {
15
  created() {
16
    this.getBreadcrumb()
17
  },
18
  data() {
19
    return {
20
      levelList: null
21
    }
22
  },
23
  watch: {
24
    $route() {
25
      this.getBreadcrumb()
26
    }
27
  },
28
  methods: {
29
    getBreadcrumb() {
30
      const bridgeName = Cookies.get('bridgeName')
31
      let matched = this.$route.matched.filter(item => {
32
        if (bridgeName && item.path === '/bridgeHome') {
33
          item.meta.title = bridgeName
34
        }
35
        return item.name
36
      })
37
      const first = matched[0]
38
      if (first && first.name !== 'dashboard') {
39
        matched = [{ path: '/dashboard', meta: { title: '主页' }}].concat(matched)
40
      }
41
      this.levelList = matched
42
    }
43
  }
44
}
45
</script>
46
47
<style rel="stylesheet/scss" lang="scss" scoped>
48
  .app-breadcrumb.el-breadcrumb {
49
    display: inline-block;
50
    font-size: 14px;
51
    line-height: 50px;
52
    margin-left: 10px;
53
    .no-redirect {
54
      color: #97a8be;
55
      cursor: text;
56
    }
57
  }
58
</style>

+ 142 - 0
src/components/CityPicker/index.vue

@ -0,0 +1,142 @@
1
<template>
2
  <div class="linkage">
3
    <el-row :gutter="10">
4
      <el-col :span="8">
5
        <el-select
6
          v-model="sheng"
7
          @change="choseProvince"
8
          placeholder="省">
9
          <el-option
10
            v-for="item in province"
11
            :key="item.id"
12
            :label="item.value"
13
            :value="item.id">
14
          </el-option>
15
        </el-select>
16
      </el-col>
17
      <el-col :span="8">
18
        <el-select
19
          v-model="shi"
20
          @change="choseCity"
21
          placeholder="市">
22
          <el-option
23
            v-for="item in shi1"
24
            :key="item.id"
25
            :label="item.value"
26
            :value="item.id">
27
          </el-option>
28
        </el-select>
29
      </el-col>
30
      <el-col :span="8">
31
        <el-select
32
          v-model="qu"
33
          @change="choseBlock"
34
          placeholder="区(县)">
35
          <el-option
36
            v-for="item in qu1"
37
            :key="item.id"
38
            :label="item.value"
39
            :value="item.id">
40
          </el-option>
41
        </el-select>
42
      </el-col>
43
    </el-row>
44
  </div>
45
</template>
46
<script>
47
import queryDict from '@/utils/queryDict'
48
export default {
49
  props: ['addrCode'],
50
  data() {
51
    return {
52
      firstFlag: false,
53
      province: [],
54
      sheng: '',
55
      shi: '',
56
      shi1: [],
57
      qu: '',
58
      qu1: [],
59
      city: '',
60
      block: ''
61
    }
62
  },
63
  watch: {
64
    addrCode: function() {
65
      this.initpsq()
66
    }
67
  },
68
  methods: {
69
    getCityData: function() {
70
      var that = this
71
      queryDict.applyDict('XZQH', function(dictData) {
72
        if (dictData) {
73
          var data = dictData.sort((obj1, obj2) => {
74
            return obj1.code - obj2.code
75
          })
76
          that.province = {}
77
          data.map(item => {
78
            if (item.code.match(/0000$/)) {
79
              that.province[item.code] = { id: item.code, value: item.caption, children: {}}
80
            } else if (item.code.match(/00$/)) {
81
              var p = that.province[item.code.slice(0, 2) + '0000']
82
              p.children[item.code] = { id: item.code, value: item.caption, children: {}}
83
              if (!p.defaultChild) {
84
                p.defaultChild = p.children[item.code]
85
              }
86
            } else {
87
              var pp = that.province[item.code.slice(0, 2) + '0000'].children[item.code.slice(0, 4) + '00']
88
              pp.children[item.code] = { id: item.code, value: item.caption }
89
              if (!pp.defaultChild) {
90
                pp.defaultChild = pp.children[item.code]
91
              }
92
            }
93
          })
94
        } else {
95
          console.log(dictData.status)
96
        }
97
      })
98
    },
99
    choseProvince: function(e) {
100
      var p = this.province[e]
101
      this.shi1 = p.children
102
      this.shi = p.defaultChild.value
103
      this.qu1 = p.defaultChild.children
104
      this.qu = p.defaultChild.defaultChild.value
105
      this.E = p.defaultChild.defaultChild.id
106
      this.sheng = p.value
107
      this.$emit('paren', this.E)
108
    },
109
    choseCity: function(e) {
110
      var p = this.province[e.slice(0, 2) + '0000'].children[e]
111
      this.shi = p.value
112
      this.qu1 = p.children
113
      this.qu = p.defaultChild.value
114
      this.E = p.defaultChild.id
115
      this.$emit('paren', this.E)
116
    },
117
    choseBlock: function(e) {
118
      this.qu = this.province[e.slice(0, 2) + '0000'].children[e.slice(0, 4) + '00'].children[e].value
119
      this.E = e
120
      this.$emit('paren', this.E)
121
    },
122
    initpsq: function() {
123
      if (!this.addrCode) {
124
        this.sheng = ''
125
        this.shi = ''
126
        this.qu = ''
127
        return
128
      }
129
      const s = this.addrCode.substring(0, 2) + '0000'
130
      const si = this.addrCode.substring(0, 4) + '00'
131
      const x = this.addrCode
132
      var p = this.province[s]
133
      this.sheng = p.value
134
      this.shi = p.children[si].value
135
      this.qu = p.children[si].children[x].value
136
    }
137
  },
138
  created: function() {
139
    this.getCityData()
140
  }
141
}
142
</script>

+ 57 - 0
src/components/DefaultPage/index.vue

@ -0,0 +1,57 @@
1
<template>
2
  <div class="ev_content" v-show="show">
3
    <div class="notice_d" v-show="noResult">
4
      <div class="d_prompt">
5
        <p class="d_2">{{message2}}</p>
6
      </div>
7
    </div>
8
  </div>
9
</template>
10
11
<script>
12
13
export default {
14
  props: {
15
    show: {
16
      type: Boolean,
17
      default: true
18
    },
19
    noResult: {
20
      type: Boolean,
21
      default: true
22
    },
23
    message2: {
24
      type: String,
25
      default: '没有相关数据'
26
    }
27
  }
28
}
29
</script>
30
31
<style rel="stylesheet/scss" lang="scss" scoped>
32
  .ev_content{
33
    width: 100%;
34
    height: 42%;
35
    z-index: 11;
36
    padding:40px;
37
    box-sizing: border-box;
38
    display: flex;
39
    justify-content:center;
40
  }
41
42
  .d_prompt p{
43
    margin: 0;
44
    font-size: 0;
45
  }
46
47
  .d_prompt .d_2{
48
    height: auto;
49
    margin: 0 auto;
50
    word-break: break-word;
51
    font-size: 13px;
52
    color: #999999;
53
    text-align: center;
54
    margin-top: 10px;
55
  }
56
57
</style>

+ 44 - 0
src/components/Hamburger/index.vue

@ -0,0 +1,44 @@
1
<template>
2
  <div>
3
    <svg t="1492500959545" @click="toggleClick" class="hamburger" :class="{'is-active':isActive}" style="" viewBox="0 0 1024 1024"
4
      version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1691" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64">
5
      <path d="M966.8023 568.849776 57.196677 568.849776c-31.397081 0-56.850799-25.452695-56.850799-56.850799l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 543.397081 998.200404 568.849776 966.8023 568.849776z"
6
        p-id="1692"></path>
7
      <path d="M966.8023 881.527125 57.196677 881.527125c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 856.07443 998.200404 881.527125 966.8023 881.527125z"
8
        p-id="1693"></path>
9
      <path d="M966.8023 256.17345 57.196677 256.17345c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.850799 56.850799-56.850799l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.850799l0 0C1023.653099 230.720755 998.200404 256.17345 966.8023 256.17345z"
10
        p-id="1694"></path>
11
    </svg>
12
  </div>
13
</template>
14
15
<script>
16
export default {
17
  name: 'hamburger',
18
  props: {
19
    isActive: {
20
      type: Boolean,
21
      default: false
22
    },
23
    toggleClick: {
24
      type: Function,
25
      default: null
26
    }
27
  }
28
}
29
</script>
30
31
<style scoped>
32
.hamburger {
33
	display: inline-block;
34
	cursor: pointer;
35
	width: 20px;
36
	height: 20px;
37
	transform: rotate(90deg);
38
	transition: .38s;
39
	transform-origin: 50% 50%;
40
}
41
.hamburger.is-active {
42
	transform: rotate(0deg);
43
}
44
</style>

+ 146 - 0
src/components/Marqueebox/index.vue

@ -0,0 +1,146 @@
1
<template>
2
  <div>
3
    <el-dialog title="系统消息编辑" :visible.sync="dialogFormVisible">
4
      <el-form :model="formNotice" ref="formNotice" :rules="rules">
5
        <el-input type="textarea" rows="6" maxlength="100" v-model="formNotice.desc" @input="limitFn"></el-input>
6
      </el-form>
7
      <div class="limit_num">还可以输入{{ableNum}}字</div>
8
      <div slot="footer" class="dialog-footer">
9
        <el-button v-waves @click="cancelNotice('formNotice')">取 消</el-button>
10
        <el-button type="primary" v-waves @click="setNotice('formNotice')">确 定</el-button>
11
      </div>
12
    </el-dialog>
13
    <el-menu class="message-box" mode="horizontal">
14
      <div class="marquee_box">
15
        <span class="tit">系统公告:</span>
16
        <el-tooltip placement="bottom-end" effect="dark">
17
          <div slot="content" class="popper-tips">{{formNotice.text}}</div>
18
          <div class="marquee_text">{{formNotice.text}}</div>
19
        </el-tooltip>
20
        <span class="btn-span" v-if="isShow" @click="openNoticeDialog">设置</span>
21
      </div>
22
    </el-menu>
23
  </div>
24
</template>
25
 
26
<script>
27
import waves from '@/directive/waves'
28
import { getNotice, updateNotice } from '@/api/login'
29
export default {
30
  props: {
31
    isShow: {
32
      type: Boolean
33
    }
34
  },
35
  directives: {
36
    waves
37
  },
38
  data() {
39
    return {
40
      dialogFormVisible: false,
41
      ableNum: 100,
42
      formNotice: {
43
        desc: '',
44
        text: ''
45
      },
46
      rules: {
47
        desc: [
48
          { required: true, message: '请编辑内容发送', trigger: 'blur' },
49
          { max: 100, message: '不得超过100个字', trigger: 'blur' }
50
        ]
51
      }
52
    }
53
  },
54
  created() {
55
    this.getNotice()
56
  },
57
  methods: {
58
    limitFn() {
59
      this.ableNum = 100 - this.formNotice.desc.length
60
    },
61
    getNotice() {
62
      getNotice().then(res => {
63
        if (res.success) {
64
          this.formNotice.desc = res.data
65
          this.formNotice.text = res.data
66
          this.limitFn()
67
        }
68
      })
69
    },
70
    openNoticeDialog() {
71
      this.dialogFormVisible = true
72
    },
73
    cancelNotice(formName) {
74
      this.dialogFormVisible = false
75
      this.$refs[formName].resetFields()
76
      this.formNotice.desc = this.formNotice.text
77
    },
78
    setNotice(formName) {
79
      this.$refs[formName].validate((valid) => {
80
        if (valid) {
81
          const param = {
82
            cnt: this.formNotice.desc
83
          }
84
          updateNotice(param).then(res => {
85
            if (res.success) {
86
              this.dialogFormVisible = false
87
              this.$refs[formName].resetFields()
88
              this.formNotice.text = this.formNotice.desc
89
            }
90
          })
91
        } else {
92
          return false
93
        }
94
      })
95
    }
96
  }
97
}
98
</script>
99
 
100
<style rel="stylesheet/scss" lang="scss" scoped>
101
.message-box{
102
  height: 50px;
103
  line-height: 50px;
104
  border-radius: 0px !important;
105
  color: #303133;
106
  background: #c7e3ff;
107
  padding: 0 20px;
108
  font-size: 14px;
109
  .marquee_box {
110
    width: 100%;
111
    position: relative;
112
    height: 50px;
113
    overflow: hidden;
114
    .marquee_text {
115
      line-height: 50px;
116
      position:absolute;
117
      top:0;
118
      padding-left: 0;
119
      left:68px;
120
      right:80px;
121
      box-sizing: border-box;
122
      text-overflow: ellipsis;
123
      white-space:nowrap;
124
      overflow: hidden;
125
    }
126
    .btn-span{
127
      position:absolute;
128
      top:0;
129
      right:0;
130
      cursor: pointer;
131
    }
132
  }
133
}
134
.limit_num{
135
  font-size: 14px;
136
  color: #ff0000;
137
  text-align: right;
138
}
139
.popper-tips{
140
  font-size: 13px;
141
  line-height: 20px;
142
  display:block;
143
  max-width: 500px;
144
  word-break: break-all;
145
}
146
</style>

+ 42 - 0
src/components/SvgIcon/index.vue

@ -0,0 +1,42 @@
1
<template>
2
  <svg :class="svgClass" aria-hidden="true">
3
    <use :xlink:href="iconName"></use>
4
  </svg>
5
</template>
6
7
<script>
8
export default {
9
  name: 'svg-icon',
10
  props: {
11
    iconClass: {
12
      type: String,
13
      required: true
14
    },
15
    className: {
16
      type: String
17
    }
18
  },
19
  computed: {
20
    iconName() {
21
      return `#icon-${this.iconClass}`
22
    },
23
    svgClass() {
24
      if (this.className) {
25
        return 'svg-icon ' + this.className
26
      } else {
27
        return 'svg-icon'
28
      }
29
    }
30
  }
31
}
32
</script>
33
34
<style scoped>
35
.svg-icon {
36
  width: 1em;
37
  height: 1em;
38
  vertical-align: -0.15em;
39
  fill: currentColor;
40
  overflow: hidden;
41
}
42
</style>

+ 36 - 0
src/components/TreeMenu/index.vue

@ -0,0 +1,36 @@
1
<template>
2
  <div class="navMenu">
3
    <div v-for="item in navMenus" :key="">
4
      <el-submenu :index="item.res ? item.res : item.caption" v-if="item.children">
5
        <template slot="title">
6
          <i :class="item.icon">+</i>
7
          <span>{{item.caption}}</span>
8
        </template>
9
        <NavMenu :navMenus="item.children"></NavMenu>
10
      </el-submenu>
11
      <el-menu-item :index="item.res" v-else>
12
        <template slot="title">
13
          <i :class="item.icon">*</i>
14
          <span>{{item.caption}}++++</span>
15
        </template>
16
      </el-menu-item>
17
    </div>
18
  </div>
19
</template>
20
21
<script>
22
export default {
23
  name: 'NavMenu',
24
  props: ['navMenus'],
25
  data() {
26
    return {}
27
  },
28
  methods: {}
29
}
30
</script>
31
32
<style scoped>
33
.navMenu{
34
  box-sizing: inherit;
35
}
36
</style>

+ 82 - 0
src/components/complexTable/index.vue

@ -0,0 +1,82 @@
1
<template>
2
  <div>
3
    <el-table
4
      :data="tableData"
5
      height="600"
6
      border>
7
      <el-table-column v-if="hasSelect"
8
        type="selection"
9
        width="55">
10
      </el-table-column>
11
      <el-table-column
12
        v-for="item in tableItem"
13
        :key="item.index"
14
        :prop="item.prop ? item.prop : ''"
15
        :label="item.tit ? item.tit : ''"
16
        :width="item.width ? item.width : ''"
17
        align="center">
18
        <template slot-scope="scope">
19
          <div v-if="scope.row[item.prop]">
20
            {{scope.row[item.prop]}}
21
          </div>
22
          <div v-if="item.operate && typeof scope.row === 'object'">
23
            <el-button
24
              size="mini"
25
              type="primary"
26
              @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
27
            <el-button
28
              size="mini"
29
              type="danger"
30
              @click="handleDelete(scope.$index, scope.row)">删除</el-button>
31
          </div>
32
        </template>
33
      </el-table-column>
34
    </el-table>
35
    <div class="pagination-container">
36
      <el-pagination
37
        background
38
        :current-page.sync="pageNo"
39
        :page-size="pageSize"
40
        layout="prev, pager, next, jumper"
41
        :total="total">
42
      </el-pagination>
43
    </div>
44
  </div>
45
</template>
46
47
48
<script>
49
export default {
50
  name: 'complexTable',
51
  props: ['tableData', 'tableItem', 'hasSelect'],
52
  data() {
53
    return {
54
      pageNo: 1,
55
      pageSize: 20,
56
      total: 0
57
    }
58
  },
59
  computed: {
60
    dataSize() {
61
      return this.tableData.length % this.pageSize
62
    }
63
  },
64
  created() {
65
    this.gapFilling()
66
  },
67
  methods: {
68
    gapFilling() {
69
      const needNum = this.pageSize - this.tableData.length % this.pageSize
70
      for (let i = 0; i < needNum; ++i) {
71
        this.tableData.push(i)
72
      }
73
    }
74
  }
75
}
76
</script>
77
78
<style rel="stylesheet/scss" lang="scss">
79
  .el-table .cell{
80
    min-height: 23px
81
  }
82
</style>

+ 9 - 0
src/icons/index.js

@ -0,0 +1,9 @@
1
import Vue from 'vue'
2
import SvgIcon from '@/components/SvgIcon'// svg组件
3
4
// register globally
5
Vue.component('svg-icon', SvgIcon)
6
7
const requireAll = requireContext => requireContext.keys().map(requireContext)
8
const req = require.context('./svg', false, /\.svg$/)
9
requireAll(req)

+ 1 - 0
src/icons/svg/Department.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1536893949585" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2168" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M1024.244053 733.013333c0 46.933333-20.906667 55.701333-97.92 56.064-20.693333-182.037333-118.4-271.765333-222.933333-314.496a244.565333 244.565333 0 0 0 6.186667-299.029333 149.226667 149.226667 0 0 1 97.92 280.874667A281.344 281.344 0 0 1 1024.244053 733.013333zM603.124053 489.28C727.924053 513.557333 874.91072 596.181333 874.91072 832c0 64-85.12 64-362.666667 64-278.613333 0-362.666667 0.661333-362.666666-64 0-235.242667 146.56-318.293333 271.786666-342.72a192 192 0 1 1 181.76 0zM320.457387 473.6C216.564053 517.354667 119.07072 609.322667 98.377387 789.333333 20.937387 789.162667 0.244053 780.650667 0.244053 733.12a271.722667 271.722667 0 0 1 215.466667-277.333333A149.141333 149.141333 0 0 1 314.91072 175.573333a244.288 244.288 0 0 0 5.546667 298.026667z" p-id="2169"></path></svg>

+ 1 - 0
src/icons/svg/doctor.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1536893969359" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2954" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M376.394 215.756l25.155 0 0 13.94c0 2.759 0.835 5.241 2.019 7.545 1.196 6.564 6.634 11.548 13.47 11.548 4.665 0 8.592-2.395 11.121-5.895 4.111-3.078 6.94-7.713 6.94-13.199l0-13.94 19.52 0c9.276 0 16.793-7.546 16.793-16.789 0-9.243-7.517-16.793-16.793-16.793l-19.52 0 0-20.942c0-9.276-7.518-16.793-16.789-16.793-9.277 0-16.761 7.517-16.761 16.793l0 20.942-25.155 0c-9.243 0-16.761 7.55-16.761 16.793C359.633 208.21 367.146 215.756 376.394 215.756L376.394 215.756zM376.394 215.756" p-id="2955"></path><path d="M759.789 820.6l-1.121-3.369c-47.04-114.26-143.281-195.393-257.194-220.975 68.797-49.038 115.47-154.205 115.47-279.242 0-79.528-19.608-154.998-55.218-212.506l-4.228-6.822-7.531-2.774c-86.805-31.883-186.303-31.883-273.043 0l-7.537 2.774-4.227 6.822c-35.623 57.479-55.25 132.963-55.25 212.506 0 128.354 49.114 235.947 120.945 283.184C224.793 629.416 135.003 708.17 90.076 817.23l-1.107 3.369c-4.336 17.867-11.82 63.007 12.378 96.105 9.548 13.063 28.021 29.124 61.754 31.476 31.081 2.135 118.567 4.288 261.299 6.391l1.046 0 0.184 0c141.446-2.107 228.932-4.256 260.088-6.391 33.672-2.352 52.131-18.412 61.675-31.476C771.608 883.606 764.092 838.477 759.789 820.6L759.789 820.6zM285.708 126.407c81.416-27.76 173.959-27.76 255.476 0 29.167 50.512 45.655 114.767 48.71 183.259-157.249-30.982-293.67-11.666-352.928 0.258C239.987 241.314 256.49 176.971 285.708 126.407L285.708 126.407zM239.068 332.728c47.528-10.201 189.017-33.938 348.738-0.305C578.014 477.233 502.183 594.2 413.431 594.2 324.739 594.2 248.964 477.402 239.068 332.728L239.068 332.728zM730.003 896.754c-5.907 8.052-15.513 12.43-29.27 13.402-32.447 2.223-125.202 4.479-275.765 6.718l0.375 24.92-1.571-24.92c-150.563-2.238-243.319-4.495-275.686-6.718-13.836-0.973-23.443-5.351-29.331-13.402-10.759-14.715-9.929-40.235-5.452-59.896 53.979-129.082 174.573-212.702 307.499-213.35l3.598 0.226c1.09 0 2.291-0.08 3.313-0.094 133.23 0.516 253.81 84.136 307.737 213.199C739.932 856.519 740.743 882.039 730.003 896.754L730.003 896.754zM730.003 896.754" p-id="2956"></path><path d="M936.061 812.46c-37.068-116.129-118.628-159.982-172.603-189.004-8.609-4.636-16.577-8.91-23.672-13.15-9.76-5.717-19.759-10.441-28.613-14.608-4.969-2.351-11.153-5.259-15.517-7.686C818.104 406.105 802.403 244.29 801.737 238.228c-4.791-93.061-94.684-126.432-141.54-131.082l-15.428-1.53-3.06 30.879 15.456 1.535c4.425 0.436 108.93 11.833 113.654 102.636 0.062 0.727 3.092 34.413-4.786 87.134-35.524-14.17-88.898-17.535-96.171-17.896l-1.577 31.005c26.432 1.347 71.073 7.315 92.108 17.883-12.73 60.661-39.522 138.598-95.895 219.81l-1.699 3.163c-8.427 21.476 14.729 32.371 35.159 41.995 8.062 3.819 17.216 8.104 26.032 13.275 7.367 4.377 15.733 8.891 24.766 13.742 52.553 28.248 124.503 66.936 157.235 168.83 6.151 39.128 0.244 51.586-2.576 55.129-1.332 1.686-3.486 3.44-9.032 3.819-20.641 1.379-48.16 2.122-48.25 2.122l0.85 31.037c0 0 28.275-0.773 49.493-2.187 13.246-0.905 23.762-6.09 31.213-15.436C939.908 878.773 942.729 853.571 936.061 812.46L936.061 812.46zM936.061 812.46" p-id="2957"></path></svg>

+ 1 - 0
src/icons/svg/example.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1511504199105" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1815" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M770.56 460.8h250.88C998.4 220.16 803.84 25.6 563.2 2.56v250.88c104.96 20.48 186.88 102.4 207.36 207.36z m0 0M460.8 253.44V2.56C220.16 25.6 25.6 220.16 2.56 460.8h250.88c20.48-104.96 102.4-186.88 207.36-207.36z m0 0M563.2 770.56v250.88c243.2-23.04 435.2-217.6 460.8-460.8H773.12C750.08 668.16 668.16 750.08 563.2 770.56z m0 0M253.44 563.2H2.56c23.04 243.2 217.6 435.2 460.8 460.8V773.12C355.84 750.08 273.92 668.16 253.44 563.2z m0 0" fill="" p-id="1816"></path></svg>

+ 1 - 0
src/icons/svg/eye.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1503993826520" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7878" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M941.677063 391.710356c9.337669-14.005992 6.224772-32.68133-6.224772-43.575447-14.005992-10.894118-32.68133-7.78122-43.575447 6.224771-1.556449 1.556449-174.300768 205.426673-379.727441 205.426673-199.200878 0-379.727441-205.426673-381.28389-206.982098-10.894118-12.450567-31.124881-14.005992-43.575448-3.112898-12.450567 10.894118-14.005992 31.124881-3.112897 43.575448 3.112897 4.668323 40.46255 46.687322 99.600439 93.375667l-79.369676 82.48155c-12.450567 12.450567-10.894118 32.68133 1.556449 43.575448 3.112897 6.224772 10.894118 9.337669 18.675338 9.337669 7.78122 0 15.562441-3.112897 21.787213-9.337669l85.594447-88.706321c40.46255 28.013007 88.706321 54.469566 141.619438 73.14388L340.959485 707.631586c-4.668323 17.118889 4.669346 34.237779 21.787213 38.906101h9.337669c14.005992 0 26.456558-9.337669 29.568432-23.343661l32.68133-110.494556c24.90011 4.668323 51.356668 7.78122 77.813227 7.78122s52.913117-3.112897 77.813227-7.78122l32.68133 108.938108c3.112897 14.005992 17.118889 23.343661 29.569456 23.343661 3.112897 0 6.224772 0 7.78122-1.556449 17.118889-4.669346 26.456558-21.787212 21.788236-38.906102l-32.68133-108.938108c52.913117-18.675338 101.156888-45.131897 141.619438-73.14388l84.037998 87.150896c6.224772 6.224772 14.005992 9.337669 21.787212 9.337669 7.78122 0 15.562441-3.112897 21.787212-9.337669 12.450567-12.450567 12.450567-31.124881 1.556449-43.575448l-79.369675-82.48155c63.808258-46.688345 101.158934-91.820242 101.158934-91.820242z" p-id="7879"></path></svg>

+ 1 - 0
src/icons/svg/form.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1511504319223" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3230" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M942.827259 80.3367c-11.42419-11.406794-26.41051-17.117866-41.377386-17.117866-14.985296 0-29.952172 5.711072-41.358967 17.117866L719.392444 221.014696l-19.441794 19.441794L681.577187 258.832 569.516971 370.909611 375.99749 564.411697l0 0.019443 0 84.372619 81.145112 0 0.010233 0 95.418186-95.435583 213.398228-213.400275 3.14155-3.14155-0.019443 0 9.979282-9.977235 0 0L942.827259 163.073052C965.697129 140.259464 965.697129 103.186104 942.827259 80.3367z" p-id="3231"></path><path d="M793.542234 367.521444 580.14196 580.939115 484.72582 676.376745 473.299583 687.800935 457.152834 687.800935 375.99749 687.800935 337.000314 687.800935 337.000314 648.803759 337.000314 564.411697 337.000314 548.264948 348.424504 536.838711 541.943986 343.338672 654.004201 231.259014 665.428392 219.834824 64.020082 219.834824 64.020082 960.781166 804.966425 960.781166 804.966425 356.116697 796.607036 364.475062Z" p-id="3232"></path></svg>

+ 1 - 0
src/icons/svg/hospital.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1536894395933" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1307" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M481.3 494.7h61.4v64.6h-61.4zM481.8 627.3h61.9v63.3h-61.9zM480.8 362.6h61.8v61.2h-61.8zM348.1 363.2h59.8v62.1h-59.8zM612.6 362.1H673v62.7h-60.4zM347.2 494.9h62v63.5h-62zM612.5 495h62v63.3h-62zM346.9 627.6h61.5v63.7h-61.5zM613.2 627h61.2v63.6h-61.2z" p-id="1308"></path><path d="M897.3 893.9V594.4c0-49-39.7-88.7-88.7-88.7H784V339.4c0-49.1-39.8-88.8-88.8-88.8H529.9v-72.4h89.8v-43.3h-89.8v-73h-46.6v72.8h-89.8V178h89.8v72.4H318.2c-49.1 0-88.8 39.8-88.8 88.8v166.3h-19.8c-49 0-88.7 39.7-88.7 88.7v299.5H59.1v44.4h900v-44.4h-61.8z m-730.6 0V594.4c0-24.5 19.9-44.4 44.4-44.4h18.3v343.8h-62.7z m107 0V339.3c0-24.5 19.9-44.4 44.4-44.4h377.1c24.5 0 44.4 19.9 44.4 44.4v554.6H273.7z m580.7 0h-70.5V550H810c24.5 0 44.4 19.9 44.4 44.4v299.5z" p-id="1309"></path></svg>

+ 1 - 0
src/icons/svg/instrument.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1536894006748" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3211" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M666.12424 400.965138c4.973268 3.978614 8.951883 9.946536 9.946536 16.410762 0.994654 6.962575-0.497327 13.427824-4.475941 18.897396l-131.290185 188.978049-64.650439-46.746674L621.36585 368.639918 666.12424 400.965138zM359.282806 494.956835l5.470595-8.454556 31.827893 23.870664c3.978614 2.486634 7.957229 3.481288 11.935843 2.983961 3.978614-0.994654 7.957229-2.983961 10.443863-6.962575 4.973268-6.962575 3.481288-17.405415-3.978614-22.378683l-31.827893-23.870664 12.43317-18.400069 32.32522 23.870664c3.481288 2.486634 7.957229 3.481288 11.935843 2.486634 3.978614-0.497327 7.459902-2.983961 10.443863-6.465249 4.973268-7.459902 2.983961-17.405415-3.978614-22.87601l-32.32522-23.373337 12.930497-18.400069 32.32522 23.373337c3.481288 2.983961 7.459902 3.481288 11.438517 2.983961 4.475941-0.497327 7.957229-2.983961 10.443863-6.465249 4.973268-7.459902 3.481288-17.405415-3.481288-22.87601l-32.32522-23.373337 12.930497-18.400069 31.827893 23.373337c3.978614 2.486634 7.957229 3.481288 11.935843 2.983961 3.978614-0.994654 7.957229-2.983961 10.443863-6.962575 4.973268-6.962575 3.481288-17.405415-3.978614-22.378683l-31.827893-23.870664 14.919804-21.38403c7.957229-11.438517 23.373337-13.925151 34.314527-5.967922l44.261063 32.822546L423.933245 541.207206 359.282806 494.956835zM360.774787 592.927147l-75.094302 108.414175c-5.470595 7.459902-12.930497 11.935843-20.886703 13.427824-7.957229 1.49198-16.410762-0.497327-23.373337-5.470595-14.422478-10.443863-17.405415-30.833239-7.459902-45.753043l75.094302-108.413152c10.443863-14.422478 30.335912-17.902742 44.261063-7.459902C367.737362 558.115294 370.721323 578.50467 360.774787 592.927147zM270.761704 794.337343c-6.962575 10.94119-21.38403 13.427824-31.827893 5.470595-10.443863-7.459902-12.930497-22.378683-5.470595-32.822546 7.459902-10.94119 21.881356-13.427824 32.32522-5.470595C276.232299 768.974699 278.221606 783.894504 270.761704 794.337343zM847.642386 238.841713 615.895255 68.264756c-13.925151-10.443863-33.8172-6.962575-43.763736 7.459902-10.443863 14.919804-6.962575 35.30918 7.459902 45.753043l90.013083 66.142419-62.661132 90.013083-82.553181-60.671825c-8.951883-6.465249-19.892049-9.449209-30.335912-7.459902-10.94119 1.989307-20.389376 7.957229-26.854625 16.908088L189.203176 627.739001c-18.400069 26.357298-23.870664 59.677171-14.919804 90.51041l37.795814 127.808898-41.277102 60.174498c-10.443863 14.422478-6.962575 34.811854 7.459902 45.254693 6.962575 4.973268 15.416108 6.962575 23.373337 5.470595s15.417131-5.967922 20.389376-12.930497l43.266409-62.163805 128.803551-3.481288c31.827893-0.994654 61.666478-16.908088 80.066547-43.763736l276.504498-399.837454c12.930497-18.897396 8.951883-45.255717-9.449209-58.682517l-83.050508-60.671825 62.661132-90.013083 90.013083 66.142419c7.459902 5.470595 15.914458 6.962575 23.870664 5.470595 7.957229-0.994654 15.416108-5.470595 20.389376-12.930497C865.545128 269.177626 862.063841 249.285576 847.642386 238.841713z" p-id="3212"></path></svg>

+ 1 - 0
src/icons/svg/list.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1525761666409" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10880" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M107.2 212.8m-67.2 0a4.2 4.2 0 1 0 134.4 0 4.2 4.2 0 1 0-134.4 0Z" p-id="10881"></path><path d="M980.8 145.6 297.6 145.6c-9.6 0-16 8-16 16l0 102.4c0 9.6 8 16 16 16l683.2 0c9.6 0 16-8 16-16l0-102.4C996.8 152 988.8 145.6 980.8 145.6z" p-id="10882"></path><path d="M96 497.6m-67.2 0a4.2 4.2 0 1 0 134.4 0 4.2 4.2 0 1 0-134.4 0Z" p-id="10883"></path><path d="M968 430.4 284.8 430.4c-9.6 0-16 8-16 16l0 102.4c0 9.6 8 16 16 16l683.2 0c9.6 0 16-8 16-16l0-102.4C984 438.4 977.6 430.4 968 430.4z" p-id="10884"></path><path d="M96 795.2m-67.2 0a4.2 4.2 0 1 0 134.4 0 4.2 4.2 0 1 0-134.4 0Z" p-id="10885"></path><path d="M968 728 284.8 728c-9.6 0-16 8-16 16l0 102.4c0 9.6 8 16 16 16l683.2 0c9.6 0 16-8 16-16l0-102.4C984 736 977.6 728 968 728z" p-id="10886"></path></svg>

+ 1 - 0
src/icons/svg/msgvc.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1534314336166" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1053" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M835.1 200.9c-7.7 0.3-15.3 0.4-22.7 0.4-194.9 0-280.9-82.6-281.6-83.3l-19.4-19.7-19.6 19.7c-0.8 0.9-85 83.3-281.5 83.3-7.4 0-15-0.1-22.7-0.4l-27.4-0.9v374.4c0 98 35.4 241 341.6 350.4l9.6 3.4 9.6-3.4c306.2-109.4 341.6-252.4 341.6-350.4V200l-27.5 0.9M481.2 671.2L304.8 517.6l46.8-37.3 93.8 68S574.9 416.6 700 355l17.9 19.8S561.6 502.2 481.2 671.2m0 0" p-id="1054"></path></svg>

+ 1 - 0
src/icons/svg/nested.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1529559567446" class="icon" style="" viewBox="0 0 1167 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1767" xmlns:xlink="http://www.w3.org/1999/xlink" width="227.9296875" height="200"><defs><style type="text/css"></style></defs><path d="M0.015952 74.459413A2.286 2.286 1440 1 0 145.85218 74.459413 2.286 2.286 1440 1 0 0.015952 74.459413zM291.720312 1.525347 1166.801488 1.525347 1166.801488 147.361574 291.720312 147.361574zM291.720312 366.163773A2.286 2.286 1440 1 0 437.55654 366.163773 2.286 2.286 1440 1 0 291.720312 366.163773zM583.424672 293.229707 1166.801488 293.229707 1166.801488 439.065934 583.424672 439.065934zM291.720312 949.540588A2.286 2.286 1440 1 0 437.55654 949.540588 2.286 2.286 1440 1 0 291.720312 949.540588zM583.424672 876.638427 1166.801488 876.638427 1166.801488 1022.474654 583.424672 1022.474654zM583.424672 657.836228A2.286 2.286 1440 1 0 729.2609 657.836228 2.286 2.286 1440 1 0 583.424672 657.836228zM875.129032 584.934067 1166.801488 584.934067 1166.801488 730.770294 875.129032 730.770294z" p-id="1768"></path></svg>

+ 1 - 0
src/icons/svg/password-view.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1536041882597" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1501" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M968.548352 614.418432c0-124.667904-203.543552-233.57952-458.737664-233.57952-255.22688 0-458.737664 108.9024-458.737664 233.57952s203.50976 233.578496 458.737664 233.578496c255.194112 0 458.737664-108.910592 458.737664-233.578496z m51.073024 0c0 161.544192-230.147072 284.690432-509.810688 284.690432C230.11328 899.108864 0 775.97184 0 614.418432 0 452.864 230.11328 329.728 509.810688 329.728c279.66464 0 509.810688 123.14624 509.810688 284.690432z" p-id="1502"></path><path d="M460.292096 582.100992c3.84-21.878784 16.09728-40.85248 33.871872-53.301248 11.55584-8.091648 14.367744-24.026112 6.28224-35.590144-8.086528-11.564032-24.008704-14.377984-35.56352-6.286336-28.786688 20.159488-48.685056 50.962432-54.893568 86.335488-2.440192 13.9008 6.843392 27.150336 20.733952 29.591552 13.89056 2.44224 27.128832-6.847488 29.569024-20.749312z" p-id="1503"></path><path d="M682.94656 594.01216c0-89.438208-72.479744-161.973248-161.850368-161.973248-89.358336 0-161.799168 72.522752-161.799168 161.972224s72.440832 161.972224 161.799168 161.972224c89.370624 0 161.850368-72.534016 161.850368-161.972224z m51.073024 0c0 117.664768-95.345664 213.082112-212.923392 213.082112C403.526656 807.094272 308.224 711.684096 308.224 594.01216 308.224 476.338176 403.526656 380.928 521.096192 380.928c117.577728 0 212.923392 95.417344 212.923392 213.08416zM729.363456 235.583488c-6.665216 12.438528-22.144 17.115136-34.573312 10.4448-12.429312-6.669312-17.101824-22.15936-10.437632-34.598912l27.222016-50.804736c6.665216-12.438528 22.144-17.115136 34.573312-10.4448 12.429312 6.669312 17.101824 22.15936 10.436608 34.598912l-27.220992 50.804736z m190.130176 78.82752c-8.54528 11.22816-24.567808 13.398016-35.7888 4.845568-11.218944-8.551424-13.386752-24.58624-4.841472-35.8144l34.270208-45.029376c8.54528-11.22816 24.567808-13.398016 35.787776-4.845568 11.218944 8.551424 13.387776 24.58624 4.842496 35.8144l-34.270208 45.029376zM378.037248 211.429376c6.664192 12.438528 1.99168 27.9296-10.437632 34.598912-12.429312 6.670336-27.908096 1.993728-34.573312-10.4448l-27.222016-50.804736c-6.664192-12.438528-1.99168-27.9296 10.437632-34.598912 12.429312-6.670336 27.908096-1.993728 34.573312 10.4448l27.222016 50.804736zM183.54688 283.4432c8.54528 11.22816 6.377472 27.262976-4.842496 35.8144-11.219968 8.552448-27.242496 6.382592-35.787776-4.845568L108.6464 269.381632c-8.54528-11.22816-6.377472-27.262976 4.84352-35.8144 11.218944-8.552448 27.241472-6.382592 35.786752 4.845568l34.270208 45.029376z m322.10944-132.958208c0-14.113792 11.43296-25.555968 25.535488-25.555968 14.103552 0 25.536512 11.442176 25.536512 25.555968v56.835072c0 14.114816-11.43296 25.555968-25.536512 25.555968-14.102528 0-25.536512-11.441152-25.536512-25.555968v-56.835072z" p-id="1504"></path></svg>

+ 1 - 0
src/icons/svg/password.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1503994678729" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9229" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M780.8 354.579692 665.6 354.579692 665.6 311.689846c0-72.310154-19.849846-193.299692-153.6-193.299692-138.870154 0-153.6 135.049846-153.6 193.299692l0 42.889846L243.2 354.579692 243.2 311.689846C243.2 122.249846 348.790154 0 512 0s268.8 122.249846 268.8 311.689846L780.8 354.579692zM588.8 669.420308C588.8 625.900308 554.220308 590.769231 512 590.769231s-76.8 35.131077-76.8 78.651077c0 29.459692 15.399385 54.468923 38.439385 67.820308l0 89.639385c0 21.740308 17.250462 39.699692 38.4 39.699692s38.4-17.959385 38.4-39.699692l0-89.639385C573.44 723.889231 588.8 698.88 588.8 669.420308zM896 512l0 393.609846c0 65.260308-51.869538 118.390154-115.2 118.390154L243.2 1024c-63.291077 0-115.2-53.129846-115.2-118.390154L128 512c0-65.220923 51.869538-118.390154 115.2-118.390154l537.6 0C844.130462 393.609846 896 446.779077 896 512z" p-id="9230"></path></svg>

+ 1 - 0
src/icons/svg/peoples.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1510727502091" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1640" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M765.184 873.941333c0 33.28-28.501333 60.288-63.829333 60.288L63.829333 934.229333C28.501333 934.229333 0 907.221333 0 873.941333c0-120.576 123.264-233.258667 249.216-277.674667-72.789333-42.496-121.728-118.058667-121.728-204.8L127.488 331.136c0-133.248 114.346667-241.365333 255.146667-241.365333s255.146667 108.117333 255.146667 241.365333l0 60.288c0 86.826667-48.981333 162.304-121.728 204.842667C641.962667 640.725333 765.184 753.365333 765.184 873.941333L765.184 873.941333z" p-id="1641"></path><path d="M848.256 870.570667l126.933333 0c27.008 0 48.810667-20.650667 48.810667-46.08 0-92.245333-94.293333-178.346667-190.549333-212.309333 55.637333-32.512 93.098667-90.282667 93.098667-156.672L926.549333 409.344c0-101.888-87.424-184.576-195.114667-184.576-13.397333 0-26.453333 1.28-39.125333 3.712 15.488 31.146667 24.149333 65.92 24.149333 102.613333l0 60.288c0 86.826667-24.448 152.746667-88.533333 204.842667C746.666667 625.365333 846.421333 751.018667 848.256 870.570667z" p-id="1642"></path></svg>

+ 1 - 0
src/icons/svg/table.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1511504440567" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5070" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M568.6 0h454.9v454.9H568.6V0z m0 568.6h454.9v454.9H568.6V568.6zM0 568.6h454.9v454.9H0V568.6zM0 0h454.9v454.9H0V0z" fill="" p-id="5071"></path></svg>

+ 1 - 0
src/icons/svg/tree.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1511512690058" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3507" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M1013.703 693.345c6.865 6.865 10.297 14.874 10.297 24.027l0 205.944c0 9.916-3.432 18.115-10.297 24.599-6.865 6.483-15.255 9.725-25.171 9.725L782.588 957.64c-9.153 0-17.162-3.242-24.027-9.725-6.865-6.483-10.297-14.683-10.297-24.599L748.264 717.372c0-6.102 1.526-11.823 4.577-17.162s7.246-9.534 12.586-12.586 11.06-4.577 17.162-4.577l77.801 0L860.39 546.896c0-4.577-1.144-8.772-3.432-12.586s-5.339-6.865-9.153-9.153-8.009-3.432-12.585-3.432L543.464 521.725l0 161.323 77.801 0c9.153 0 17.162 3.432 24.027 10.297s10.297 14.874 10.297 24.027l0 205.944c0 6.102-1.526 11.823-4.577 17.162s-7.246 9.534-12.585 12.585-11.06 4.577-17.162 4.577L415.321 957.64c-6.102 0-11.823-1.526-17.162-4.577s-9.725-7.246-13.158-12.585-5.149-11.06-5.149-17.162L379.852 717.372c0-9.153 3.432-17.162 10.297-24.027s15.255-10.297 25.171-10.297l76.657 0L491.977 521.725 188.782 521.725c-7.628 0-13.92 2.479-18.878 7.437-4.958 4.958-7.437 10.869-7.437 17.734l0 136.152 77.801 0c9.916 0 18.115 3.432 24.599 10.297s9.725 14.874 9.725 24.027l0 205.944c0 9.916-3.242 18.115-9.725 24.599-6.483 6.483-14.683 9.725-24.599 9.725L34.324 957.64c-3.814 0-7.437-0.572-10.869-1.716-3.432-1.144-6.483-2.67-9.153-4.577-2.67-1.907-5.149-4.386-7.437-7.437-2.288-3.051-4.004-6.293-5.149-9.725C0.572 930.753 0 927.13 0 923.316L0 717.372c0-3.051 0.381-6.102 1.144-9.153s1.907-5.721 3.432-8.009 3.432-4.577 5.721-6.865 4.577-4.195 6.865-5.721 4.958-2.67 8.009-3.432 6.102-1.144 9.153-1.144l77.801 0L112.125 495.41c0-6.865 2.479-12.776 7.437-17.734s10.869-7.437 17.734-7.437l354.682 0L491.978 342.096l-76.657 0c-9.916 0-18.306-3.432-25.171-10.297s-10.297-14.874-10.297-24.027L379.853 101.828c0-9.916 3.432-18.306 10.297-25.171s15.255-10.297 25.171-10.297l205.944 0c6.102 0 11.823 1.716 17.162 5.149 5.339 3.432 9.534 7.818 12.585 13.158 3.051 5.339 4.577 11.06 4.577 17.162l0 205.944c0 9.153-3.432 17.162-10.297 24.027s-14.874 10.297-24.027 10.297l-77.801 0 0 128.143L885.56 470.24c7.628 0 13.92 2.479 18.878 7.437s7.437 10.869 7.437 17.734l0 187.638 76.657 0C998.448 683.048 1006.838 686.48 1013.703 693.345z" p-id="3508"></path></svg>

+ 1 - 0
src/icons/svg/unread.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1534314532421" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2816" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M511.999488 66.861804c-245.826801 0-445.138196 199.203948-445.138196 445.138196 0 245.826801 199.311395 445.138196 445.138196 445.138196 245.825778 0 445.138196-199.311395 445.138196-445.138196C957.137685 266.065751 757.824243 66.861804 511.999488 66.861804zM484.177839 230.311433c0-15.431457 12.443403-27.821649 27.821649-27.821649s27.821649 12.389168 27.821649 27.821649l0 389.495922c0 15.32401-12.443403 27.821649-27.821649 27.821649s-27.821649-12.497639-27.821649-27.821649L484.177839 230.311433zM511.999488 807.599392c-22.985504 0-41.73145-18.800181-41.73145-41.73145 0-23.039739 18.745946-41.73145 41.73145-41.73145s41.73145 18.692734 41.73145 41.73145C553.730938 788.79921 534.984992 807.599392 511.999488 807.599392z" p-id="2817"></path></svg>

+ 1 - 0
src/icons/svg/user.svg

@ -0,0 +1 @@
1
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1503993891882" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7986" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M504.951 511.98c93.49 0 169.28-74.002 169.28-165.26 0-91.276-75.79-165.248-169.28-165.248-93.486 0-169.287 73.972-169.279 165.248-0.001 91.258 75.793 165.26 169.28 165.26z m77.6 55.098H441.466c-120.767 0-218.678 95.564-218.678 213.45V794.3c0 48.183 97.911 48.229 218.678 48.229H582.55c120.754 0 218.66-1.78 218.66-48.229v-13.77c0-117.887-97.898-213.45-218.66-213.45z" p-id="7987"></path></svg>

+ 28 - 0
src/main.js

@ -0,0 +1,28 @@
1
import 'babel-polyfill'
2
3
import Vue from 'vue'
4
5
import 'normalize.css/normalize.css'// A modern alternative to CSS resets
6
7
import ElementUI from 'element-ui'
8
import 'element-ui/lib/theme-chalk/index.css'
9
10
import '@/styles/index.scss' // global css
11
12
import App from './App'
13
import router from './router'
14
import store from './store'
15
16
import '@/icons' // icon
17
import '@/permission' // permission control
18
19
Vue.use(ElementUI)
20
21
Vue.config.productionTip = false
22
23
new Vue({
24
  el: '#app',
25
  router,
26
  store,
27
  render: h => h(App)
28
})

+ 58 - 0
src/permission.js

@ -0,0 +1,58 @@
1
// import router from './router'
2
// import store from './store'
3
// import NProgress from 'nprogress' // Progress 进度条
4
// import 'nprogress/nprogress.css'// Progress 进度条样式
5
// import { Message } from 'element-ui'
6
// import { getCookiesName } from '@/utils/auth' // 验权
7
// import queryInfo from '@/utils/queryInfo'
8
9
// NProgress.configure({ showSpinner: false })// NProgress Configuration
10
11
// function hasPermission(roles, permissionRoles) {
12
//   if (roles.indexOf('1') >= 0) return true
13
//   if (!permissionRoles) return true
14
//   return roles.some(role => permissionRoles.indexOf(role) >= 0)
15
// }
16
17
// const whiteList = ['/login', '/findPwd'] // 不重定向白名单
18
19
// router.beforeEach((to, from, next) => {
20
//   NProgress.start()
21
//   if (getCookiesName()) {
22
//     if (to.path === '/login') {
23
//       next({ path: '/' })
24
//       NProgress.done()
25
//     } else {
26
//       if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息
27
//         store.dispatch('GetUserInfo').then(res => { // 拉取user_info
28
//           const roles = [res.data.type.toString()]
29
//           store.dispatch('GenerateRoutes', { roles }).then(() => { // 根据roles权限生成可访问的路由表
30
//             router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
31
//             next({ ...to, replace: true })
32
//           })
33
//         }).catch((err) => {
34
//           store.dispatch('FedLogOut').then(() => {
35
//             Message.error(err || '登录状态失效,请重新登录')
36
//             next({ path: '/' })
37
//           })
38
//         })
39
//       } else {
40
//         if (hasPermission(store.getters.roles, to.meta.roles)) {
41
//           next()
42
//         }
43
//       }
44
//       queryInfo.queryAllInfo()
45
//     }
46
//   } else {
47
//     if (whiteList.indexOf(to.path) !== -1) {
48
//       next()
49
//     } else {
50
//       next('/login')
51
//       NProgress.done()
52
//     }
53
//   }
54
// })
55
56
// router.afterEach(() => {
57
//   NProgress.done() // 结束Progress
58
// })

+ 119 - 0
src/router/index.js

@ -0,0 +1,119 @@
1
import Vue from 'vue'
2
import Router from 'vue-router'
3
4
Vue.use(Router)
5
6
/* Layout */
7
import Layout from '../views/layout/Layout'
8
9
/**
10
* hidden: true                   if `hidden:true` will not show in the sidebar(default is false)
11
* alwaysShow: true               if set true, will always show the root menu, whatever its child routes length
12
*                                if not set alwaysShow, only more than one route under the children
13
*                                it will becomes nested mode, otherwise not show the root menu
14
* redirect: noredirect           if `redirect:noredirect` will no redirct in the breadcrumb
15
* name:'router-name'             the name is used by <keep-alive> (must set!!!)
16
* meta : {
17
    roles: ['admin','editor']     will control the page roles (you can set multiple roles)
18
    title: 'title'               the name show in submenu and breadcrumb (recommend set)
19
    icon: 'svg-name'             the icon show in the sidebar,
20
    noCache: true                if true ,the page will no be cached(default is false)
21
  }
22
**/
23
24
// 所有权限通用路由表
25
// 如首页和登录页和一些不用权限的公用页面
26
27
export const constantRouterMap = [
28
  { path: '/login', component: () => import('@/views/login/index'), hidden: true },
29
  { path: '/findPwd', component: () => import('@/views/findPwd/index'), hidden: true },
30
  { path: '/404', component: () => import('@/views/404'), hidden: true },
31
  {
32
    path: '/',
33
    component: Layout,
34
    redirect: '/dashboard',
35
    hidden: true,
36
    children: [{
37
      path: 'dashboard',
38
      component: () => import('@/views/dashboard'),
39
      name: 'dashboard',
40
      meta: { title: '主页' }
41
    }]
42
  },
43
  {
44
    path: '',
45
    component: Layout,
46
    name: 'content',
47
    redirect: 'noredirect',
48
    meta: { title: '内容发布' },
49
    children: [
50
      {
51
        path: 'pubList',
52
        component: () => import('@/views/contentPub/pubList'),
53
        name: 'pubList',
54
        meta: { title: '内容发布列表' }
55
      },
56
      {
57
        path: 'draftList',
58
        component: () => import('@/views/contentPub/draftList'),
59
        name: 'draftList',
60
        meta: { title: '内容草稿箱列表' }
61
      },
62
      {
63
        path: 'recycleBin',
64
        component: () => import('@/views/contentPub/recycleBin'),
65
        name: 'recycleBin',
66
        meta: { title: '内容回收站列表' }
67
      }
68
    ]
69
  },
70
  {
71
    path: '',
72
    component: Layout,
73
    name: 'demand',
74
    redirect: 'noredirect',
75
    meta: { title: '需求中心' },
76
    children: [
77
      {
78
        path: 'publishedList',
79
        component: () => import('@/views/demandCen/publishedList'),
80
        name: 'publishedList',
81
        meta: { title: '发布中需求' }
82
      },
83
      {
84
        path: 'expiredList',
85
        component: () => import('@/views/demandCen/expiredList'),
86
        name: 'expiredList',
87
        meta: { title: '已过期需求' }
88
      },
89
      {
90
        path: 'completedList',
91
        component: () => import('@/views/demandCen/completedList'),
92
        name: 'completedList',
93
        meta: { title: '已完成需求' }
94
      },
95
      {
96
        path: 'closedList',
97
        component: () => import('@/views/demandCen/closedList'),
98
        name: 'closedList',
99
        meta: { title: '已关闭需求' }
100
      }
101
    ]
102
  }
103
]
104
105
// 实例化vue的时候只挂载constantRouter
106
107
export default new Router({
108
  // mode: 'history', //后端支持可开
109
  scrollBehavior: () => ({ y: 0 }),
110
  routes: constantRouterMap
111
})
112
113
// 异步挂载的路由
114
// 动态需要根据权限加载的路由表
115
116
export const asyncRouterMap = [
117
  
118
  { path: '*', redirect: '/404', hidden: true }
119
]

+ 13 - 0
src/store/getters.js

@ -0,0 +1,13 @@
1
const getters = {
2
  sidebar: state => state.app.sidebar,
3
  device: state => state.app.device,
4
  account: state => state.user.account,
5
  userid: state => state.user.userid,
6
  name: state => state.user.name,
7
  roles: state => state.user.roles,
8
  logins: state => state.user.logins,
9
  session: state => state.user.session,
10
  permission_routers: state => state.permission.routers,
11
  addRouters: state => state.permission.addRouters
12
}
13
export default getters

+ 19 - 0
src/store/index.js

@ -0,0 +1,19 @@
1
import Vue from 'vue'
2
import Vuex from 'vuex'
3
import app from './modules/app'
4
import permission from './modules/permission'
5
import user from './modules/user'
6
import getters from './getters'
7
8
Vue.use(Vuex)
9
10
const store = new Vuex.Store({
11
  modules: {
12
    app,
13
    permission,
14
    user
15
  },
16
  getters
17
})
18
19
export default store

+ 43 - 0
src/store/modules/app.js

@ -0,0 +1,43 @@
1
import Cookies from 'js-cookie'
2
3
const app = {
4
  state: {
5
    sidebar: {
6
      opened: !+Cookies.get('sidebarStatus'),
7
      withoutAnimation: false
8
    },
9
    device: 'desktop'
10
  },
11
  mutations: {
12
    TOGGLE_SIDEBAR: state => {
13
      if (state.sidebar.opened) {
14
        Cookies.set('sidebarStatus', 1)
15
      } else {
16
        Cookies.set('sidebarStatus', 0)
17
      }
18
      state.sidebar.opened = !state.sidebar.opened
19
      state.sidebar.withoutAnimation = false
20
    },
21
    CLOSE_SIDEBAR: (state, withoutAnimation) => {
22
      Cookies.set('sidebarStatus', 1)
23
      state.sidebar.opened = false
24
      state.sidebar.withoutAnimation = withoutAnimation
25
    },
26
    TOGGLE_DEVICE: (state, device) => {
27
      state.device = device
28
    }
29
  },
30
  actions: {
31
    ToggleSideBar: ({ commit }) => {
32
      commit('TOGGLE_SIDEBAR')
33
    },
34
    CloseSideBar({ commit }, { withoutAnimation }) {
35
      commit('CLOSE_SIDEBAR', withoutAnimation)
36
    },
37
    ToggleDevice({ commit }, device) {
38
      commit('TOGGLE_DEVICE', device)
39
    }
40
  }
41
}
42
43
export default app

+ 58 - 0
src/store/modules/permission.js

@ -0,0 +1,58 @@
1
import { asyncRouterMap, constantRouterMap } from '@/router'
2
3
/**
4
 * 通过meta.role判断是否与当前用户权限匹配
5
 * @param roles
6
 * @param route
7
 */
8
function hasPermission(roles, route) {
9
  if (route.meta.roles) {
10
    return roles.some(role => route.meta.roles.indexOf(role) >= 0)
11
  } else {
12
    return true
13
  }
14
}
15
16
/**
17
 * 递归过滤异步路由表,返回符合用户角色权限的路由表
18
 * @param asyncRouterMap
19
 * @param roles
20
 */
21
function filterAsyncRouter(asyncRouterMap, roles) {
22
  const accessedRouters = asyncRouterMap.filter(route => {
23
    if (hasPermission(roles, route)) {
24
      if (route.children && route.children.length) {
25
        route.children = filterAsyncRouter(route.children, roles)
26
      }
27
      return true
28
    }
29
    return false
30
  })
31
  return accessedRouters
32
}
33
34
const permission = {
35
  state: {
36
    routers: constantRouterMap,
37
    addRouters: []
38
  },
39
  mutations: {
40
    SET_ROUTERS: (state, routers) => {
41
      state.addRouters = routers
42
      state.routers = constantRouterMap.concat(routers)
43
    }
44
  },
45
  actions: {
46
    GenerateRoutes({ commit }, data) {
47
      return new Promise(resolve => {
48
        const { roles } = data
49
        // const roles = ['2']
50
        const accessedRouters = filterAsyncRouter(asyncRouterMap, roles)
51
        commit('SET_ROUTERS', accessedRouters)
52
        resolve()
53
      })
54
    }
55
  }
56
}
57
58
export default permission

+ 111 - 0
src/store/modules/user.js

@ -0,0 +1,111 @@
1
import { login, logout, getInfo } from '@/api/login'
2
import { getCookiesName, setCookiesName, removeCookiesName } from '@/utils/auth'
3
4
const user = {
5
  state: {
6
    account: '',
7
    userid: '',
8
    name: '',
9
    roles: [],
10
    logins: '',
11
    session: getCookiesName()
12
  },
13
  mutations: {
14
    SET_ACCOUNT: (state, account) => {
15
      state.account = account
16
    },
17
    SET_USERID: (state, userid) => {
18
      state.userid = userid
19
    },
20
    SET_NAME: (state, name) => {
21
      state.name = name
22
    },
23
    SET_ROLES: (state, roles) => {
24
      state.roles = roles
25
    },
26
    SET_LOGIN: (state, logins) => {
27
      state.logins = logins
28
    },
29
    SET_SESSION: (state, session) => {
30
      state.session = session
31
    }
32
  },
33
34
  actions: {
35
    // 用户名登录
36
    LoginByUsername({ commit }, userInfo) {
37
      const account = userInfo.username.trim()
38
      const pw = userInfo.password
39
      const vc = userInfo.imgVerifyCode.toLocaleUpperCase()
40
      return new Promise((resolve, reject) => {
41
        login(account, pw, vc).then((response) => {
42
          if (response.success) {
43
            if (response.data) {
44
              const dataS = response.data
45
              if (dataS.active) {
46
                commit('SET_ACCOUNT', dataS.account)
47
                commit('SET_USERID', dataS.id)
48
                commit('SET_NAME', dataS.name)
49
                setCookiesName(dataS.name)
50
              }
51
            }
52
          }
53
          resolve(response)
54
        }).catch(error => {
55
          reject(error)
56
        })
57
      })
58
    },
59
60
    // 获取用户信息
61
    GetUserInfo({ commit, state }) {
62
      return new Promise((resolve, reject) => {
63
        getInfo().then(response => {
64
          if (response.success) {
65
            if (response.data) {
66
              const dataS = response.data
67
              if (dataS.active) {
68
                commit('SET_ACCOUNT', dataS.account)
69
                commit('SET_USERID', dataS.id)
70
                // commit('SET_ROLES', ['2'])
71
                commit('SET_ROLES', [dataS.type.toString()])
72
                commit('SET_NAME', dataS.name)
73
              }
74
            }
75
          }
76
          resolve(response)
77
        }).catch(error => {
78
          reject(error)
79
        })
80
      })
81
    },
82
83
    // 登出
84
    LogOut({ commit, state }) {
85
      return new Promise((resolve, reject) => {
86
        logout().then(() => {
87
          commit('SET_ACCOUNT', '')
88
          commit('SET_USERID', '')
89
          commit('SET_ROLES', [])
90
          commit('SET_NAME', '')
91
          commit('SET_SESSION', '')
92
          removeCookiesName()
93
          resolve()
94
        }).catch(error => {
95
          reject(error)
96
        })
97
      })
98
    },
99
100
    // 前端 登出
101
    FedLogOut({ commit }) {
102
      return new Promise(resolve => {
103
        commit('SET_SESSION', '')
104
        removeCookiesName()
105
        resolve()
106
      })
107
    }
108
  }
109
}
110
111
export default user

+ 53 - 0
src/styles/element-ui.scss

@ -0,0 +1,53 @@
1
 //to reset element-ui default css
2
.el-upload {
3
  input[type="file"] {
4
    display: none !important;
5
  }
6
}
7
8
.el-upload__input {
9
  display: none;
10
}
11
12
//暂时性解决diolag 问题 https://github.com/ElemeFE/element/issues/2461
13
.el-dialog {
14
  transform: none;
15
  left: 0;
16
  position: relative;
17
  margin: 0 auto;
18
}
19
20
//element ui upload
21
.upload-container {
22
  .el-upload {
23
    width: 100%;
24
    .el-upload-dragger {
25
      width: 100%;
26
      height: 200px;
27
    }
28
  }
29
}
30
.el-dialog{
31
  margin: 0 auto 50px;
32
}
33
.el-dialog__header{
34
  border-bottom: 1px solid #ebeef5;
35
}
36
.el-dialog__body{
37
  padding:20px 
38
}
39
40
.pagination-container{
41
  margin:20px;
42
  text-align:center;
43
}
44
45
.el-btn-col{
46
  margin: 20px 0;
47
  .el-btn-col-box{
48
    text-align:center;
49
    .el-button{
50
      padding: 12px 50px;
51
    }
52
  }
53
}

+ 128 - 0
src/styles/index.scss

@ -0,0 +1,128 @@
1
@import './variables.scss';
2
@import './mixin.scss';
3
@import './transition.scss';
4
@import './element-ui.scss';
5
@import './sidebar.scss';
6
7
body {
8
  height: 100%;
9
  min-width:600px;
10
  -moz-osx-font-smoothing: grayscale;
11
  -webkit-font-smoothing: antialiased;
12
  text-rendering: optimizeLegibility;
13
  font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
14
}
15
16
label {
17
  font-weight: 700;
18
}
19
20
html {
21
  height: 100%;
22
  box-sizing: border-box;
23
}
24
25
#app{
26
  height: 100%;
27
}
28
29
*,
30
*:before,
31
*:after {
32
  box-sizing: inherit;
33
}
34
35
a,
36
a:focus,
37
a:hover {
38
  cursor: pointer;
39
  color: inherit;
40
  outline: none;
41
  text-decoration: none;
42
}
43
44
div:focus{
45
  outline: none;
46
 }
47
48
a:focus,
49
a:active {
50
  outline: none;
51
}
52
53
a,
54
a:focus,
55
a:hover {
56
  cursor: pointer;
57
  color: inherit;
58
  text-decoration: none;
59
}
60
61
.clearfix {
62
  &:after {
63
    visibility: hidden;
64
    display: block;
65
    font-size: 0;
66
    content: " ";
67
    clear: both;
68
    height: 0;
69
  }
70
}
71
72
//main-container全局样式
73
.app-main{
74
  min-height: 100%
75
}
76
77
.app-container {
78
  padding: 20px;
79
  .box-container{
80
    position: relative;
81
    overflow:hidden;
82
    line-height: 40px;
83
    padding:15px 20px;
84
    background:#ffffff;
85
    border-bottom:1px solid #dadada;
86
    .contain-title{
87
      font-size:18px;
88
      float:left;
89
      margin-right:20px;
90
    }
91
    .contain-search{
92
      float:left;
93
      .input-with-select{
94
        width:300px;
95
      }
96
    }
97
    .contian-operate{
98
      position:absolute;
99
      right:20px;
100
      top:15px;
101
    }
102
  }
103
  .content-container{
104
    background:#ffffff;
105
    padding:15px;
106
    overflow:hidden;
107
    .contain-select{
108
      margin-bottom:15px;
109
      float:right;
110
      span{
111
      font-size:15px;
112
      color:#999;
113
      }
114
    }
115
  }
116
}
117
118
.logo-wrapper {
119
  display:block;
120
  width: 100%;
121
  .logo-img{
122
    display:block;
123
    height:28px;
124
    width:300px;
125
    background-image: url('/static/touchwave.png');
126
    background-size: 300px 28px;
127
  }
128
}

+ 144 - 0
src/styles/loginform.scss

@ -0,0 +1,144 @@
1
$bg:#2d3a4b;
2
$dark_gray:#889aa4;
3
$light_gray:#eee;
4
$light_black:#555;
5
6
.login-container {
7
  position: fixed;
8
  height: 100%;
9
  width: 100%;
10
  background-color: $bg;
11
  background-image: url(/static/login_bg.jpg);
12
  background-size: cover;
13
  background-position: center center;
14
  .logo-wrapper{
15
    padding: 20px 30px;
16
    background-color: $bg;
17
  }
18
  .step-wrapper{
19
    margin-bottom:30px;
20
    .el-step__head.is-process{
21
      color: $light_black;
22
      border-color: $light_gray;
23
    }
24
    .el-step__title.is-process{
25
      color: $light_gray;
26
    }
27
    .el-step__description.is-process{
28
      color: $light_gray;
29
    }
30
    .el-step__icon{
31
      width:40px;
32
      height:40px;
33
      .el-step__icon-inner{
34
        font-size:16px;
35
      }
36
    }
37
  }
38
  .step-contain{
39
    .importTip{
40
      font-size: 18px;
41
      margin: 10px 0;
42
    }
43
    .mainTip{
44
      color:$light_gray;
45
    }
46
    .smallTip{
47
      color:$light_gray;
48
      line-height:16px;
49
      font-size:13px;
50
    }
51
  }
52
  .login-form {
53
    position: absolute;
54
    left: 0;
55
    right: 0;
56
    top: 10%;
57
    width: 520px;
58
    padding: 50px 35px 15px 35px;
59
    margin: 120px auto;
60
    border-radius: 4px;
61
    background-color: $bg;
62
    box-shadow: 1px 1px 18px 6px rgba(24, 24, 24, .4);
63
    .log-btn.el-button--primary {
64
      width:100%;
65
    }
66
  }
67
  .el-input {
68
    display: inline-block;
69
    height: 47px;
70
    width: 85%;
71
    input {
72
      background: transparent;
73
      border: 0px;
74
      -webkit-appearance: none;
75
      border-radius: 0px;
76
      padding: 12px 5px 12px 15px;
77
      color: $light_gray;
78
      height: 47px;
79
      &:-webkit-autofill {
80
        -webkit-box-shadow: 0 0 0px 1000px $bg inset !important;
81
        -webkit-text-fill-color: #fff !important;
82
      }
83
    }
84
  }
85
  .el-form-item {
86
    border: 1px solid rgba(255, 255, 255, 0.1);
87
    background: rgba(0, 0, 0, 0.1);
88
    border-radius: 5px;
89
    color: #454545;
90
  }
91
  .el-form-find {
92
    border: none;
93
    background: none;
94
    margin-top: -20px;
95
  }
96
  .code-btn{
97
    width: 92%;
98
    .el-input-group__append{
99
      padding: 0;
100
      overflow: hidden;
101
      position: absolute;
102
      right: 0;
103
      top: 0;
104
      width: 140px;
105
      img{
106
        width: 140px;
107
        height:42px;
108
        cursor: pointer;
109
      }
110
      .el-button{
111
        width: 100%;
112
        margin:0;
113
        padding:15px 20px;
114
      }
115
    }
116
  }
117
  .svg-container {
118
    padding: 6px 5px 6px 15px;
119
    color: $dark_gray;
120
    vertical-align: middle;
121
    width: 30px;
122
    display: inline-block;
123
    &_login {
124
      font-size: 20px;
125
    }
126
  }
127
  .title {
128
    font-size: 26px;
129
    font-weight: 400;
130
    color: $light_gray;
131
    margin: 0px auto 40px auto;
132
    text-align: center;
133
    font-weight: bold;
134
  }
135
  .show-pwd {
136
    position: absolute;
137
    right: 10px;
138
    top: 7px;
139
    font-size: 16px;
140
    color: $dark_gray;
141
    cursor: pointer;
142
    user-select: none;
143
  }
144
}

+ 29 - 0
src/styles/mixin.scss

@ -0,0 +1,29 @@
1
$mainColor:#409eff;
2
3
@mixin clearfix {
4
  &:after {
5
    content: "";
6
    display: table;
7
    clear: both;
8
  }
9
}
10
11
@mixin scrollBar {
12
  &::-webkit-scrollbar-track-piece {
13
    background: #d3dce6;
14
  }
15
  &::-webkit-scrollbar {
16
    width: 6px;
17
  }
18
  &::-webkit-scrollbar-thumb {
19
    background: #99a9bf;
20
    border-radius: 20px;
21
  }
22
}
23
24
@mixin relative {
25
  position: relative;
26
  width: 100%;
27
  height: 100%;
28
}
29

+ 106 - 0
src/styles/roleuser.scss

@ -0,0 +1,106 @@
1
.dashboard-editor-container{
2
  padding: 32px;
3
  .block-group{
4
    background: #fff;
5
    margin-bottom: 20px;
6
    .block-title{
7
      display: flex;
8
      justify-content: space-between;
9
      .el-button{
10
        padding: 3px 0;
11
      }
12
    }
13
    .item-ul{
14
      margin: 0;
15
      padding: 0 10px;
16
      li{
17
        padding: 8px 0;
18
        margin: 0;
19
        list-style: none;
20
        cursor: pointer;
21
        &.readed-li{
22
          color: #de0000;
23
        }
24
        span{
25
          display: inline-block;
26
          margin-right: 15px;
27
        }
28
      }
29
    }
30
    .grid-content{
31
      height: 100px;
32
      display: flex;
33
      text-align: center;
34
      justify-content: center;
35
      align-items: center;
36
      background-color: #f8f8f8;
37
      margin-bottom: 8px;
38
      padding:20px;
39
      cursor: pointer;
40
      &:hover {
41
        transition: all 0.2s ease-out;
42
        color: #fff;
43
        background: #36a3f7;
44
      }
45
    }
46
  }
47
  .panel-group {
48
    /*margin-top: 18px;*/
49
    .card-panel-col{
50
      margin-bottom: 32px;
51
    }
52
    .card-panel {
53
      cursor: pointer;
54
      padding: 15px 20px;
55
      font-size: 12px;
56
      position: relative;
57
      overflow: hidden;
58
      color: #666;
59
      background: #fff;
60
      box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
61
      border-color: rgba(0, 0, 0, .05);
62
      &:hover {
63
        .card-panel-icon-wrapper {
64
          color: #fff;
65
        }
66
      }
67
      .card-panel-icon-wrapper {
68
        margin: 10px 0;
69
        transition: all 0.38s ease-out;
70
        border-radius: 6px;
71
      }
72
      .card-image{
73
        width: 100%;
74
        max-width: 280px;
75
        margin: auto;
76
        height: 180px;
77
        border: 1px solid #d0d0d0;
78
        background-position: center;
79
        background-size: cover;
80
      }
81
      .card-panel-icon {
82
        font-size: 48px;
83
      }
84
      .card-panel-description {
85
        font-weight: bold;
86
        margin-top:12px;
87
        .card-panel-text {
88
          line-height: 24px;
89
          color: rgba(0, 0, 0, 0.45);
90
          font-size: 16px;
91
        }
92
        .card-panel-text-red {
93
          color: #de0000
94
        }
95
        .card-panel-num {
96
          font-size: 20px;
97
        }
98
      }
99
    }
100
  }
101
  .line-chart-box{
102
    .el-col{
103
      margin: 15px 0;
104
    }
105
  }
106
}

+ 58 - 0
src/styles/sidebar.scss

@ -0,0 +1,58 @@
1
#app {
2
  // 主体区域
3
  .main-container {
4
    min-height: 100%;
5
    padding-top:50px;
6
    transition: margin-left .28s;
7
    margin-left: 200px;
8
    position: relative;
9
    background-color: rgb(240, 242, 245);
10
  }
11
  // 侧边栏
12
  .sidebar-container {
13
    transition: width 0.28s;
14
    width: 200px !important;
15
    height: 100%;
16
    float: left;
17
    font-size: 0px;
18
    overflow: hidden;
19
    //reset element-ui css
20
    .horizontal-collapse-transition {
21
      transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
22
    }
23
    .scrollbar-wrapper {
24
      height: 100%;
25
      overflow: auto;
26
      .el-scrollbar__view {
27
        height: 100%;
28
      }
29
    }
30
    .is-horizontal {
31
      display: none;
32
    }
33
    a {
34
      display: inline-block;
35
      width: 100%;
36
      overflow: hidden;
37
    }
38
    .svg-icon {
39
      margin-right: 16px;
40
    }
41
    .el-menu-sidebar {
42
      border: none;
43
      height: 100%;
44
      width: 100% !important;
45
    }
46
  }
47
  .sidebar-container .nest-menu .el-submenu>.el-submenu__title,
48
  .sidebar-container .el-submenu .el-menu-item {
49
    min-width: 200px !important;
50
    background-color: $subMenuBg !important;
51
    &:hover {
52
      background-color: $menuHover !important;
53
    }
54
  }
55
  .el-menu--collapse .el-menu .el-submenu {
56
    min-width: 180px !important;
57
  }
58
}

+ 32 - 0
src/styles/transition.scss

@ -0,0 +1,32 @@
1
//globl transition css
2
3
/*fade*/
4
.fade-enter-active,
5
.fade-leave-active {
6
  transition: opacity 0.28s;
7
}
8
9
.fade-enter,
10
.fade-leave-active {
11
  opacity: 0;
12
}
13
14
/*fade*/
15
.breadcrumb-enter-active,
16
.breadcrumb-leave-active {
17
  transition: all .5s;
18
}
19
20
.breadcrumb-enter,
21
.breadcrumb-leave-active {
22
  opacity: 0;
23
  transform: translateX(20px);
24
}
25
26
.breadcrumb-move {
27
  transition: all .5s;
28
}
29
30
.breadcrumb-leave-active {
31
  position: absolute;
32
}

+ 4 - 0
src/styles/variables.scss

@ -0,0 +1,4 @@
1
//sidebar
2
$menuBg:#1a76a5;
3
$subMenuBg:#146792;
4
$menuHover:#105477;

+ 13 - 0
src/utils/auth.js

@ -0,0 +1,13 @@
1
import Cookies from 'js-cookie'
2
3
export function getCookiesName() {
4
  return Cookies.get('nameKey')
5
}
6
7
export function setCookiesName(name) {
8
  return Cookies.set('nameKey', name)
9
}
10
11
export function removeCookiesName() {
12
  return Cookies.remove('nameKey')
13
}

+ 87 - 0
src/utils/index.js

@ -0,0 +1,87 @@
1
/**
2
 * Created by luyanan on 18/8/13.
3
 */
4
export const comUrl = process.env.BASE_API
5
6
/**
7
 * 解析url参数
8
 * @example ?id=12345&a=b
9
 * @return Object {id:12345,a:b}
10
 */
11
export function urlParse(name) {
12
  return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || ['', ''])[1].replace(/\+/g, '%20')) || null
13
}
14
15
export function parseTime(startTime, flag, fa) {
16
  if (flag) {
17
    if (!fa) {
18
      return startTime.substring(0, 4) + '年' + startTime.substring(4, 6) + '月' + startTime.substring(6, 8) + '日 ' + startTime.substring(8, 10) + ':' + startTime.substring(10, 12) + ':' + startTime.substring(12, 14)
19
    } else {
20
      return startTime.substring(0, 4) + '/' + startTime.substring(4, 6) + '/' + startTime.substring(6, 8) + ' ' + startTime.substring(8, 10) + ':' + startTime.substring(10, 12) + ':' + startTime.substring(12, 14)
21
    }
22
  } else {
23
    return startTime.substring(0, 4) + '/' + startTime.substring(4, 6) + '/' + startTime.substring(6, 8)
24
  }
25
}
26
27
export function turnTime(date, hasT, hasF) { // hasT='date/time'是否有时分秒,hasF是否需要显示格式
28
  const format = (hasT === 'time') ? (hasF ? '{y}/{m}/{d} {h}:{i}:{s}' : '{y}{m}{d}{h}{i}{s}') : (hasF ? '{y}/{m}/{d}' : '{y}{m}{d}')
29
  const formatObj = {
30
    y: date.getFullYear(),
31
    m: date.getMonth() + 1,
32
    d: date.getDate(),
33
    h: date.getHours(),
34
    i: date.getMinutes(),
35
    s: date.getSeconds()
36
  }
37
  const time_str = format.replace(/{(y|m|d|h|i|s)+}/g, (result, key) => {
38
    let value = formatObj[key]
39
    if (result.length > 0 && value < 10) {
40
      value = '0' + value
41
    }
42
    return value || 0
43
  })
44
  return time_str
45
}
46
47
export function param2Obj(url) {
48
  const search = url.split('?')[1]
49
  if (!search) {
50
    return {}
51
  }
52
  return JSON.parse('{"' + decodeURIComponent(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') + '"}')
53
}
54
export function debounce(func, wait, immediate) {
55
  let timeout, args, context, timestamp, result
56
57
  const later = function() {
58
    // 据上一次触发时间间隔
59
    const last = +new Date() - timestamp
60
61
    // 上次被包装函数被调用时间间隔last小于设定时间间隔wait
62
    if (last < wait && last > 0) {
63
      timeout = setTimeout(later, wait - last)
64
    } else {
65
      timeout = null
66
      // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
67
      if (!immediate) {
68
        result = func.apply(context, args)
69
        if (!timeout) context = args = null
70
      }
71
    }
72
  }
73
74
  return function(...args) {
75
    context = this
76
    timestamp = +new Date()
77
    const callNow = immediate && !timeout
78
    // 如果延时不存在,重新设定延时
79
    if (!timeout) timeout = setTimeout(later, wait)
80
    if (callNow) {
81
      result = func.apply(context, args)
82
      context = args = null
83
    }
84
85
    return result
86
  }
87
}

+ 138 - 0
src/utils/queryBase.js

@ -0,0 +1,138 @@
1
/**
2
 * Created by luyanan on 18/8/27.
3
 * bridge、server、device
4
 */
5
/* eslint-disable one-var */
6
import request from '@/utils/request'
7
var $req = {
8
  get: function(url, data, sh, eh) {
9
    request({
10
      method: 'get',
11
      url: url,
12
      params: data
13
    }).then(res => {
14
      sh(res)
15
    }).catch(err => {
16
      console.log(err)
17
      eh(err)
18
    })
19
  }
20
}
21
var objCache = {
22
  bridge: {},
23
  server: {},
24
  device: {}
25
}
26
var objHcache = {
27
  bridge: {},
28
  server: {},
29
  device: {}
30
}
31
var objCacheHandler = {
32
  bridge: function(id) {
33
    var hc = objHcache.bridge[id]
34
    $req.get('/ajax/bridge/qo?id=' + id, null, function(data) {
35
      delete objHcache.bridge[id]
36
      if (data.success) {
37
        objCache.bridge[id] = data.data
38
        for (let i = 0; i < hc.length; ++i) {
39
          hc[i](true, data.data)
40
        }
41
      } else {
42
        for (let i = 0; i < hc.length; ++i) {
43
          hc[i](false)
44
        }
45
      }
46
    }, function() {
47
      for (let i = 0; i < hc.length; ++i) {
48
        hc[i](false)
49
      }
50
    })
51
  },
52
  server: function(id) {
53
    var hc = objHcache.server[id]
54
    $req.get('/ajax/server/qo?id=' + id, null, function(data) {
55
      delete objHcache.server[id]
56
      if (data.success) {
57
        objCache.server[id] = data.data
58
        for (let i = 0; i < hc.length; ++i) {
59
          hc[i](true, data.data)
60
        }
61
      } else {
62
        for (let i = 0; i < hc.length; ++i) {
63
          hc[i](false)
64
        }
65
      }
66
    }, function() {
67
      for (let i = 0; i < hc.length; ++i) {
68
        hc[i](false)
69
      }
70
    })
71
  },
72
  device: function(id) {
73
    var hc = objHcache.device[id]
74
    $req.get('/ajax/device/qo?id=' + id, null, function(data) {
75
      delete objHcache.device[id]
76
      if (data.success) {
77
        objCache.device[id] = data.data
78
        for (let i = 0; i < hc.length; ++i) {
79
          hc[i](true, data.data)
80
        }
81
      } else {
82
        for (let i = 0; i < hc.length; ++i) {
83
          hc[i](false)
84
        }
85
      }
86
    }, function() {
87
      for (let i = 0; i < hc.length; ++i) {
88
        hc[i](false)
89
      }
90
    })
91
  }
92
}
93
var cacheModel = {
94
  getBridge: function(id, handler) {
95
    var data = objCache.bridge[id]
96
    if (data) {
97
      handler(true, data)
98
    } else {
99
      if (objHcache.bridge[id]) {
100
        objHcache.bridge[id].push(handler)
101
      } else {
102
        objHcache.bridge[id] = []
103
        objHcache.bridge[id].push(handler)
104
        objCacheHandler.bridge(id)
105
      }
106
    }
107
  },
108
  getServer: function(id, handler) {
109
    var data = objCache.server[id]
110
    if (data) {
111
      handler(true, data)
112
    } else {
113
      if (objHcache.server[id]) {
114
        objHcache.server[id].push(handler)
115
      } else {
116
        objHcache.server[id] = []
117
        objHcache.server[id].push(handler)
118
        objCacheHandler.server(id)
119
      }
120
    }
121
  },
122
  getDevice: function(id, handler) {
123
    var data = objCache.device[id]
124
    if (data) {
125
      handler(true, data)
126
    } else {
127
      if (objHcache.device[id]) {
128
        objHcache.device[id].push(handler)
129
      } else {
130
        objHcache.device[id] = []
131
        objHcache.device[id].push(handler)
132
        objCacheHandler.device(id)
133
      }
134
    }
135
  }
136
}
137
138
export default cacheModel

+ 54 - 0
src/utils/queryDict.js

@ -0,0 +1,54 @@
1
/**
2
 * Created by luyanan on 18/8/23.
3
 * 'ZLLX'----'传感器主缆'
4
 * 'ZLWZ'----'传感器位置'
5
 * 'XZQH'----'城市级联'
6
 */
7
/* eslint-disable one-var */
8
import request from '@/utils/request'
9
10
var cacheDict = {
11
    bool: [
12
      { code: '0', caption: '否', enabled: true },
13
      { code: '1', caption: '是', enabled: true }
14
    ]
15
  },
16
  handCache = {},
17
  uri = '/ajax/dict/items',
18
  setDict = function(code, items) {
19
    cacheDict[code] = items
20
    var hs = handCache[code]
21
    if (hs && hs.length) {
22
      hs.forEach(h => h(items))
23
      delete handCache[code]
24
    }
25
  },
26
  loadDict = function(code) {
27
    request({
28
      url: uri,
29
      method: 'get',
30
      params: {
31
        dict: code
32
      }
33
    }).then(res => {
34
      setDict(code, res.data)
35
    })
36
  },
37
  applyDict = function(code, hander) {
38
    var dict = cacheDict[code]
39
    if (!dict) {
40
      var hs = handCache[code]
41
      if (!hs) {
42
        handCache[code] = hs = []
43
        loadDict(code)
44
      }
45
      hs.push(hander)
46
    } else {
47
      hander(dict)
48
    }
49
  },
50
  ret = {
51
    applyDict: applyDict
52
  }
53
54
export default ret

+ 81 - 0
src/utils/queryInfo.js

@ -0,0 +1,81 @@
1
/**
2
 * Created by luyanan on 18/8/23.
3
 * All information about bridges
4
 */
5
/* eslint-disable one-var */
6
import request from '@/utils/request'
7
import store from '@/store'
8
9
var bridgeObj = {},
10
  serverList = [],
11
  deviceList = [],
12
  transducerList = [],
13
  queryAllInfo = function() {
14
    if (!bridgeObj.server && store.getters.roles.indexOf('1') === -1) {
15
      request({
16
        url: '/ajax/all/byUser',
17
        method: 'get',
18
        params: {
19
          active: 1
20
        }
21
      }).then(res => {
22
        if (res.success) {
23
          bridgeObj = res.data
24
          serverList = res.data.server
25
          deviceList = res.data.device
26
          transducerList = res.data.transducer
27
        }
28
      })
29
    }
30
  },
31
  queryServers = function(bid, flag) {
32
    const obj = serverList
33
    var servers = [], serverSeqArr = []
34
    for (let i = 0; i < obj.length; ++i) {
35
      if (bid === obj[i].bridgeId) {
36
        servers.push(obj[i])
37
        serverSeqArr.push(obj[i].seq)
38
      }
39
    }
40
    return flag ? serverSeqArr : servers
41
  },
42
  queryDevices = function(bid) {
43
    var devices = []
44
    for (let i = 0; i < serverList.length; ++i) {
45
      if (bid === serverList[i].bridgeId) {
46
        for (let j = 0; j < deviceList.length; ++j) {
47
          if (serverList[i].id === deviceList[j].serverId) {
48
            deviceList[j].serverCode = serverList[i].code
49
            devices.push(deviceList[j])
50
          }
51
        }
52
      }
53
    }
54
    return devices
55
  },
56
  queryTrans = function(bid) {
57
    var trans = []
58
    for (let i = 0; i < serverList.length; ++i) {
59
      if (bid === serverList[i].bridgeId) {
60
        for (let j = 0; j < deviceList.length; ++j) {
61
          if (serverList[i].id === deviceList[j].serverId) {
62
            for (let m = 0; m < transducerList.length; ++m) {
63
              if (deviceList[j].id === transducerList[m].deviceId) {
64
                transducerList[m].deviceCode = deviceList[j].code
65
                trans.push(transducerList[m])
66
              }
67
            }
68
          }
69
        }
70
      }
71
    }
72
    return trans
73
  },
74
  ret = {
75
    queryAllInfo: queryAllInfo,
76
    queryServers: queryServers,
77
    queryDevices: queryDevices,
78
    queryTrans: queryTrans
79
  }
80
81
export default ret

+ 78 - 0
src/utils/request.js

@ -0,0 +1,78 @@
1
import axios from 'axios'
2
import qs from 'qs'
3
import { Message } from 'element-ui'
4
import { comUrl } from '@/utils/index'
5
6
// 创建axios实例
7
const service = axios.create({
8
  baseURL: comUrl, // api的base_url
9
  // timeout: 5000, // 请求超时时间
10
  paramsSerializer: function(params) {
11
    return qs.stringify(params, { arrayFormat: 'repeat' })
12
  }
13
})
14
15
// request拦截器
16
service.interceptors.request.use(config => {
17
  // 配置config
18
  config.headers.Accept = 'application/json'
19
  if (config.method === 'post') {
20
    config.data = qs.stringify(config.data)
21
    // 处理后后台无需添加RequestBody
22
    config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
23
  }
24
  return config
25
}, error => {
26
  Message.error({ error })
27
  Promise.reject(error)
28
})
29
30
// respone拦截器
31
service.interceptors.response.use(response => {
32
  let taR = response.data
33
  if (response && (response.status === 200 || response.status === 304 || response.status === 400)) {
34
    if (response.data === undefined) { // 解决IE9数据问题
35
      taR = response.request.responseText
36
    } else {
37
      taR = response.data
38
    }
39
    if (!(taR instanceof Object)) { // 判断taR不是Object时,解析成Object
40
      taR = JSON.parse(taR)
41
    }
42
    return taR
43
  } else {
44
    Message.error({ response })
45
    return Promise.resolve(response)
46
  }
47
}, error => {
48
  const text = JSON.parse(JSON.stringify(error)).response.status === 404 ? '404' : '网络异常,请重试'
49
  Message.error({ text })
50
  return Promise.reject(error)
51
})
52
53
var ret = {
54
  get: function(url, Da, sh, eh) {
55
    service({
56
      method: 'get',
57
      url: url,
58
      params: Da
59
    }).then(res => {
60
      sh(res)
61
    }).catch(err => {
62
      if (eh) eh(err)
63
    })
64
  },
65
  post: function(url, Da, sh, eh) {
66
    service({
67
      method: 'post',
68
      url: url,
69
      data: Da
70
    }).then(res => {
71
      sh(res)
72
    }).catch(err => {
73
      if (eh) eh(err)
74
    })
75
  }
76
}
77
78
export default ret

+ 78 - 0
src/utils/timingConstruct.js

@ -0,0 +1,78 @@
1
/**
2
 * Created by luyanan on 18/9/4.
3
 * construct monitor
4
 */
5
/* eslint-disable one-var */
6
import { parseTime } from '@/utils/index'
7
8
var monitorModel = {
9
  construct: function(mCache, $data) {
10
    for (let i = 0; i < $data.length; ++i) {
11
      if ($data[i].ctime === $data[0].ctime) {
12
        mCache.push({
13
          cid: $data[i].cid,
14
          cd: {
15
            tit: '',
16
            xData: [],
17
            seData: []
18
          }
19
        })
20
      }
21
    }
22
  },
23
  fixData: function(item, ftbegin, ftend, $daI) {
24
    if ($daI) {
25
      item.xData.push(parseTime(ftbegin, true, true))
26
      item.xData.push(parseTime(ftend, true, true))
27
      item.seData.push($daI.hvalue)
28
      item.seData.push($daI.lvalue)
29
      item.tit = $daI.cid
30
    } else {
31
      item.xData.push(parseTime(ftbegin, true, true))
32
      item.xData.push(parseTime(ftend, true, true))
33
      item.seData.push(0)
34
      item.seData.push(0)
35
    }
36
  },
37
  shiftData: function(item) {
38
    item.xData.shift()
39
    item.xData.shift()
40
    item.seData.shift()
41
    item.seData.shift()
42
  },
43
  setData: function(mCache, $data, ftbegin, ftend, maxNum) {
44
    if ($data.length) {
45
      for (let n = 0; n < mCache.length; ++n) {
46
        let found_c = false
47
        for (let m = 0; m < $data.length; ++m) {
48
          var tj = ($data[m].cid === mCache[n].cid && (ftbegin === $data[m].ctime))
49
          if (maxNum) {
50
            tj = ($data[m].cid === mCache[n].cid)
51
          }
52
          if (tj) {
53
            found_c = true
54
            this.fixData(mCache[n].cd, ftbegin, ftend, $data[m])
55
            break
56
          }
57
        }
58
        if (!found_c) {
59
          this.fixData(mCache[n].cd, ftbegin, ftend)
60
        }
61
62
        if (maxNum && mCache[n].cd.xData.length > maxNum) {
63
          this.shiftData(mCache[n].cd)
64
        }
65
      }
66
    } else {
67
      for (let k = 0; k < mCache.length; ++k) {
68
        this.fixData(mCache[k].cd, ftbegin, ftend)
69
70
        if (maxNum && mCache[k].cd.xData.length > maxNum) {
71
          this.shiftData(mCache[k].cd)
72
        }
73
      }
74
    }
75
  }
76
}
77
78
export default monitorModel

+ 236 - 0
src/views/404.vue

@ -0,0 +1,236 @@
1
<template>
2
  <div class="wscn-http404-container">
3
    <div class="wscn-http404">
4
      <div class="pic-404">
5
        <img class="pic-404__parent" :src="img_404" alt="404">
6
        <img class="pic-404__child left" :src="img_404_cloud" alt="404">
7
        <img class="pic-404__child mid" :src="img_404_cloud" alt="404">
8
        <img class="pic-404__child right" :src="img_404_cloud" alt="404">
9
      </div>
10
      <div class="bullshit">
11
        <!-- <div class="bullshit__oops">OOPS!</div>
12
        <div class="bullshit__info">版权所有
13
          <a class='link-type' href='https://wallstreetcn.com' target='_blank'>华尔街见闻</a>
14
        </div> -->
15
        <div class="bullshit__headline">{{ message }}</div>
16
        <div class="bullshit__info">请检查您输入的网址是否正确,请点击以下按钮返回主页或者发送错误报告</div>
17
        <a href="" class="bullshit__return-home">返回首页</a>
18
      </div>
19
    </div>
20
  </div>
21
</template>
22
23
<script>
24
import img_404 from '@/assets/404_images/404.png'
25
import img_404_cloud from '@/assets/404_images/404_cloud.png'
26
27
export default {
28
  name: 'page404',
29
  data() {
30
    return {
31
      img_404,
32
      img_404_cloud
33
    }
34
  },
35
  computed: {
36
    message() {
37
      return '管理员说这个页面你不能进......'
38
    }
39
  }
40
}
41
</script>
42
43
<style rel="stylesheet/scss" lang="scss" scoped>
44
.wscn-http404-container{
45
  transform: translate(-50%,-50%);
46
  position: absolute;
47
  top: 40%;
48
  left: 50%;
49
}
50
.wscn-http404 {
51
  position: relative;
52
  width: 1200px;
53
  padding: 0 50px;
54
  overflow: hidden;
55
  .pic-404 {
56
    position: relative;
57
    float: left;
58
    width: 600px;
59
    overflow: hidden;
60
    &__parent {
61
      width: 100%;
62
    }
63
    &__child {
64
      position: absolute;
65
      &.left {
66
        width: 80px;
67
        top: 17px;
68
        left: 220px;
69
        opacity: 0;
70
        animation-name: cloudLeft;
71
        animation-duration: 2s;
72
        animation-timing-function: linear;
73
        animation-fill-mode: forwards;
74
        animation-delay: 1s;
75
      }
76
      &.mid {
77
        width: 46px;
78
        top: 10px;
79
        left: 420px;
80
        opacity: 0;
81
        animation-name: cloudMid;
82
        animation-duration: 2s;
83
        animation-timing-function: linear;
84
        animation-fill-mode: forwards;
85
        animation-delay: 1.2s;
86
      }
87
      &.right {
88
        width: 62px;
89
        top: 100px;
90
        left: 500px;
91
        opacity: 0;
92
        animation-name: cloudRight;
93
        animation-duration: 2s;
94
        animation-timing-function: linear;
95
        animation-fill-mode: forwards;
96
        animation-delay: 1s;
97
      }
98
      @keyframes cloudLeft {
99
        0% {
100
          top: 17px;
101
          left: 220px;
102
          opacity: 0;
103
        }
104
        20% {
105
          top: 33px;
106
          left: 188px;
107
          opacity: 1;
108
        }
109
        80% {
110
          top: 81px;
111
          left: 92px;
112
          opacity: 1;
113
        }
114
        100% {
115
          top: 97px;
116
          left: 60px;
117
          opacity: 0;
118
        }
119
      }
120
      @keyframes cloudMid {
121
        0% {
122
          top: 10px;
123
          left: 420px;
124
          opacity: 0;
125
        }
126
        20% {
127
          top: 40px;
128
          left: 360px;
129
          opacity: 1;
130
        }
131
        70% {
132
          top: 130px;
133
          left: 180px;
134
          opacity: 1;
135
        }
136
        100% {
137
          top: 160px;
138
          left: 120px;
139
          opacity: 0;
140
        }
141
      }
142
      @keyframes cloudRight {
143
        0% {
144
          top: 100px;
145
          left: 500px;
146
          opacity: 0;
147
        }
148
        20% {
149
          top: 120px;
150
          left: 460px;
151
          opacity: 1;
152
        }
153
        80% {
154
          top: 180px;
155
          left: 340px;
156
          opacity: 1;
157
        }
158
        100% {
159
          top: 200px;
160
          left: 300px;
161
          opacity: 0;
162
        }
163
      }
164
    }
165
  }
166
  .bullshit {
167
    position: relative;
168
    float: left;
169
    width: 300px;
170
    padding: 30px 0;
171
    overflow: hidden;
172
    &__oops {
173
      font-size: 32px;
174
      font-weight: bold;
175
      line-height: 40px;
176
      color: #1482f0;
177
      opacity: 0;
178
      margin-bottom: 20px;
179
      animation-name: slideUp;
180
      animation-duration: 0.5s;
181
      animation-fill-mode: forwards;
182
    }
183
    &__headline {
184
      font-size: 20px;
185
      line-height: 24px;
186
      color: #222;
187
      font-weight: bold;
188
      opacity: 0;
189
      margin-bottom: 10px;
190
      animation-name: slideUp;
191
      animation-duration: 0.5s;
192
      animation-delay: 0.1s;
193
      animation-fill-mode: forwards;
194
    }
195
    &__info {
196
      font-size: 13px;
197
      line-height: 21px;
198
      color: grey;
199
      opacity: 0;
200
      margin-bottom: 30px;
201
      animation-name: slideUp;
202
      animation-duration: 0.5s;
203
      animation-delay: 0.2s;
204
      animation-fill-mode: forwards;
205
    }
206
    &__return-home {
207
      display: block;
208
      float: left;
209
      width: 110px;
210
      height: 36px;
211
      background: #1482f0;
212
      border-radius: 100px;
213
      text-align: center;
214
      color: #ffffff;
215
      opacity: 0;
216
      font-size: 14px;
217
      line-height: 36px;
218
      cursor: pointer;
219
      animation-name: slideUp;
220
      animation-duration: 0.5s;
221
      animation-delay: 0.3s;
222
      animation-fill-mode: forwards;
223
    }
224
    @keyframes slideUp {
225
      0% {
226
        transform: translateY(60px);
227
        opacity: 0;
228
      }
229
      100% {
230
        transform: translateY(0);
231
        opacity: 1;
232
      }
233
    }
234
  }
235
}
236
</style>

+ 3 - 0
src/views/contentPub/draftList.vue

@ -0,0 +1,3 @@
1
<template>
2
  <div>内容草稿箱列表</div>
3
</template>

+ 100 - 0
src/views/contentPub/pubList.vue

@ -0,0 +1,100 @@
1
<template>
2
  <div class="app-container">
3
    <div class="box-container">
4
      <div class="contain-title">发布中内容列表</div>
5
      <div class="contain-search">
6
        <el-input placeholder="搜索内容标题" v-model="searchText" class="input-with-select">
7
          <el-button slot="append" icon="el-icon-search"></el-button>
8
        </el-input>
9
      </div>
10
      <div class="contian-operate">
11
        <el-button type="primary">发布内容</el-button>
12
      </div>
13
    </div>
14
    <div class="content-container">
15
      <div class="contain-select">
16
        <span>栏目分类:</span>
17
        <el-select v-model="selectMode" placeholder="选择分类">
18
          <el-option label="餐厅名" value="1"></el-option>
19
          <el-option label="订单号" value="2"></el-option>
20
          <el-option label="用户电话" value="3"></el-option>
21
        </el-select>
22
      </div>
23
      <complex-table :tableData="tableData" :tableItem="tableItem"></complex-table>
24
    </div>
25
  </div>
26
</template>
27
28
<script>
29
import complexTable from '@/components/complexTable'
30
export default {
31
  data() {
32
    return {
33
      searchText: '',
34
      selectMode: '',
35
      tableData: [
36
        {
37
          date: '2018/08/25 16:32',
38
          name: '关于征集企业技术创新需求的通知',
39
          class: '通知公告',
40
          owner: '张贝贝',
41
          num: '4552'
42
        }, {
43
          date: '2018/08/25 16:32',
44
          name: '关于征集企业技术创新需求的通知',
45
          class: '通知公告',
46
          owner: '张贝贝',
47
          num: '4552'
48
        }, {
49
          date: '2018/08/25 16:32',
50
          name: '关于征集企业技术创新需求的通知',
51
          class: '通知公告',
52
          owner: '张贝贝',
53
          num: '4552'
54
        }, {
55
          date: '2018/08/25 16:32',
56
          name: '关于征集企业技术创新需求的通知',
57
          class: '通知公告',
58
          owner: '张贝贝',
59
          num: '4552'
60
        }
61
      ],
62
      tableItem: [
63
        {
64
          prop: 'name',
65
          tit: '标题'
66
        },
67
        {
68
          prop: 'class',
69
          tit: '栏目分类',
70
          width: '160'
71
        },
72
        {
73
          prop: 'owner',
74
          tit: '发布人',
75
          width: '160'
76
        },
77
        {
78
          prop: 'date',
79
          tit: '发布时间',
80
          width: '160'
81
        },
82
        {
83
          prop: 'num',
84
          tit: '浏览数量',
85
          width: '160'
86
        },
87
        {
88
          operate: 'edit',
89
          width: '200'
90
        }
91
      ]
92
    }
93
  },
94
  components: {
95
    complexTable
96
  },
97
  methods: {
98
  }
99
}
100
</script>

+ 3 - 0
src/views/contentPub/recycleBin.vue

@ -0,0 +1,3 @@
1
<template>
2
  <div>内容回收站列表</div>
3
</template>

+ 45 - 0
src/views/dashboard/admin/index.vue

@ -0,0 +1,45 @@
1
<template>
2
  <div class="dashboard-editor-container">
3
    <div>
4
      <img class="plat-pic" src="/static/touchwave.png" width="460">
5
      <p class="plat-tit">欢迎 <span>{{name}}</span> 使用声脉桥梁云监控平台</p>
6
    </div>
7
  </div>
8
</template>
9
10
<script>
11
import { mapGetters } from 'vuex'
12
export default {
13
  name: 'dashboard-admin',
14
  computed: {
15
    ...mapGetters([
16
      'name'
17
    ])
18
  }
19
}
20
</script>
21
22
<style rel="stylesheet/scss" lang="scss" scoped>
23
.dashboard-editor-container {
24
  display: flex;
25
  align-items: center;
26
  justify-content: center;
27
  flex-direction: column;
28
  text-align: center;
29
  margin: 20px;
30
  height: 100%;
31
  padding: 12% 0;
32
  background: #fff;
33
  .plat-pic{
34
    margin: 40px auto 0;
35
  }
36
  .plat-tit{
37
    font-size: 34px;
38
    line-height: 40px;
39
    letter-spacing: 2px;
40
    span{
41
      color: #0f76c4;
42
    }
43
  }
44
}
45
</style>

+ 26 - 0
src/views/dashboard/index.vue

@ -0,0 +1,26 @@
1
<template>
2
  <div class="dashboard-container">
3
    <component :is="currentRole"></component>
4
  </div>
5
</template>
6
7
<script>
8
import { mapGetters } from 'vuex'
9
import adminDashboard from './admin'
10
export default {
11
  name: 'dashboard',
12
  components: {
13
    adminDashboard
14
  },
15
  data() {
16
    return {
17
      currentRole: 'adminDashboard'
18
    }
19
  },
20
  computed: {
21
    ...mapGetters([
22
      'roles'
23
    ])
24
  }
25
}
26
</script>

+ 100 - 0
src/views/demandCen/closedList.vue

@ -0,0 +1,100 @@
1
<template>
2
  <div class="app-container">
3
    <div class="box-container">
4
      <div class="contain-title">发布中内容列表</div>
5
      <div class="contain-search">
6
        <el-input placeholder="搜索内容标题" v-model="searchText" class="input-with-select">
7
          <el-button slot="append" icon="el-icon-search"></el-button>
8
        </el-input>
9
      </div>
10
      <div class="contian-operate">
11
        <el-button type="primary">发布内容</el-button>
12
      </div>
13
    </div>
14
    <div class="content-container">
15
      <div class="contain-select">
16
        <span>栏目分类:</span>
17
        <el-select v-model="selectMode" placeholder="选择分类">
18
          <el-option label="餐厅名" value="1"></el-option>
19
          <el-option label="订单号" value="2"></el-option>
20
          <el-option label="用户电话" value="3"></el-option>
21
        </el-select>
22
      </div>
23
      <complex-table :tableData="tableData" :tableItem="tableItem"></complex-table>
24
    </div>
25
  </div>
26
</template>
27
28
<script>
29
import complexTable from '@/components/complexTable'
30
export default {
31
  data() {
32
    return {
33
      searchText: '',
34
      selectMode: '',
35
      tableData: [
36
        {
37
          date: '2018/08/25 16:32',
38
          name: '关于征集企业技术创新需求的通知',
39
          class: '通知公告',
40
          owner: '张贝贝',
41
          num: '4552'
42
        }, {
43
          date: '2018/08/25 16:32',
44
          name: '关于征集企业技术创新需求的通知',
45
          class: '通知公告',
46
          owner: '张贝贝',
47
          num: '4552'
48
        }, {
49
          date: '2018/08/25 16:32',
50
          name: '关于征集企业技术创新需求的通知',
51
          class: '通知公告',
52
          owner: '张贝贝',
53
          num: '4552'
54
        }, {
55
          date: '2018/08/25 16:32',
56
          name: '关于征集企业技术创新需求的通知',
57
          class: '通知公告',
58
          owner: '张贝贝',
59
          num: '4552'
60
        }
61
      ],
62
      tableItem: [
63
        {
64
          prop: 'name',
65
          tit: '标题'
66
        },
67
        {
68
          prop: 'class',
69
          tit: '栏目分类',
70
          width: '160'
71
        },
72
        {
73
          prop: 'owner',
74
          tit: '发布人',
75
          width: '160'
76
        },
77
        {
78
          prop: 'date',
79
          tit: '发布时间',
80
          width: '160'
81
        },
82
        {
83
          prop: 'num',
84
          tit: '浏览数量',
85
          width: '160'
86
        },
87
        {
88
          operate: 'edit',
89
          width: '200'
90
        }
91
      ]
92
    }
93
  },
94
  components: {
95
    complexTable
96
  },
97
  methods: {
98
  }
99
}
100
</script>

+ 100 - 0
src/views/demandCen/completedList.vue

@ -0,0 +1,100 @@
1
<template>
2
  <div class="app-container">
3
    <div class="box-container">
4
      <div class="contain-title">发布中内容列表</div>
5
      <div class="contain-search">
6
        <el-input placeholder="搜索内容标题" v-model="searchText" class="input-with-select">
7
          <el-button slot="append" icon="el-icon-search"></el-button>
8
        </el-input>
9
      </div>
10
      <div class="contian-operate">
11
        <el-button type="primary">发布内容</el-button>
12
      </div>
13
    </div>
14
    <div class="content-container">
15
      <div class="contain-select">
16
        <span>栏目分类:</span>
17
        <el-select v-model="selectMode" placeholder="选择分类">
18
          <el-option label="餐厅名" value="1"></el-option>
19
          <el-option label="订单号" value="2"></el-option>
20
          <el-option label="用户电话" value="3"></el-option>
21
        </el-select>
22
      </div>
23
      <complex-table :tableData="tableData" :tableItem="tableItem"></complex-table>
24
    </div>
25
  </div>
26
</template>
27
28
<script>
29
import complexTable from '@/components/complexTable'
30
export default {
31
  data() {
32
    return {
33
      searchText: '',
34
      selectMode: '',
35
      tableData: [
36
        {
37
          date: '2018/08/25 16:32',
38
          name: '关于征集企业技术创新需求的通知',
39
          class: '通知公告',
40
          owner: '张贝贝',
41
          num: '4552'
42
        }, {
43
          date: '2018/08/25 16:32',
44
          name: '关于征集企业技术创新需求的通知',
45
          class: '通知公告',
46
          owner: '张贝贝',
47
          num: '4552'
48
        }, {
49
          date: '2018/08/25 16:32',
50
          name: '关于征集企业技术创新需求的通知',
51
          class: '通知公告',
52
          owner: '张贝贝',
53
          num: '4552'
54
        }, {
55
          date: '2018/08/25 16:32',
56
          name: '关于征集企业技术创新需求的通知',
57
          class: '通知公告',
58
          owner: '张贝贝',
59
          num: '4552'
60
        }
61
      ],
62
      tableItem: [
63
        {
64
          prop: 'name',
65
          tit: '标题'
66
        },
67
        {
68
          prop: 'class',
69
          tit: '栏目分类',
70
          width: '160'
71
        },
72
        {
73
          prop: 'owner',
74
          tit: '发布人',
75
          width: '160'
76
        },
77
        {
78
          prop: 'date',
79
          tit: '发布时间',
80
          width: '160'
81
        },
82
        {
83
          prop: 'num',
84
          tit: '浏览数量',
85
          width: '160'
86
        },
87
        {
88
          operate: 'edit',
89
          width: '200'
90
        }
91
      ]
92
    }
93
  },
94
  components: {
95
    complexTable
96
  },
97
  methods: {
98
  }
99
}
100
</script>

+ 100 - 0
src/views/demandCen/expiredList.vue

@ -0,0 +1,100 @@
1
<template>
2
  <div class="app-container">
3
    <div class="box-container">
4
      <div class="contain-title">发布中内容列表</div>
5
      <div class="contain-search">
6
        <el-input placeholder="搜索内容标题" v-model="searchText" class="input-with-select">
7
          <el-button slot="append" icon="el-icon-search"></el-button>
8
        </el-input>
9
      </div>
10
      <div class="contian-operate">
11
        <el-button type="primary">发布内容</el-button>
12
      </div>
13
    </div>
14
    <div class="content-container">
15
      <div class="contain-select">
16
        <span>栏目分类:</span>
17
        <el-select v-model="selectMode" placeholder="选择分类">
18
          <el-option label="餐厅名" value="1"></el-option>
19
          <el-option label="订单号" value="2"></el-option>
20
          <el-option label="用户电话" value="3"></el-option>
21
        </el-select>
22
      </div>
23
      <complex-table :tableData="tableData" :tableItem="tableItem"></complex-table>
24
    </div>
25
  </div>
26
</template>
27
28
<script>
29
import complexTable from '@/components/complexTable'
30
export default {
31
  data() {
32
    return {
33
      searchText: '',
34
      selectMode: '',
35
      tableData: [
36
        {
37
          date: '2018/08/25 16:32',
38
          name: '关于征集企业技术创新需求的通知',
39
          class: '通知公告',
40
          owner: '张贝贝',
41
          num: '4552'
42
        }, {
43
          date: '2018/08/25 16:32',
44
          name: '关于征集企业技术创新需求的通知',
45
          class: '通知公告',
46
          owner: '张贝贝',
47
          num: '4552'
48
        }, {
49
          date: '2018/08/25 16:32',
50
          name: '关于征集企业技术创新需求的通知',
51
          class: '通知公告',
52
          owner: '张贝贝',
53
          num: '4552'
54
        }, {
55
          date: '2018/08/25 16:32',
56
          name: '关于征集企业技术创新需求的通知',
57
          class: '通知公告',
58
          owner: '张贝贝',
59
          num: '4552'
60
        }
61
      ],
62
      tableItem: [
63
        {
64
          prop: 'name',
65
          tit: '标题'
66
        },
67
        {
68
          prop: 'class',
69
          tit: '栏目分类',
70
          width: '160'
71
        },
72
        {
73
          prop: 'owner',
74
          tit: '发布人',
75
          width: '160'
76
        },
77
        {
78
          prop: 'date',
79
          tit: '发布时间',
80
          width: '160'
81
        },
82
        {
83
          prop: 'num',
84
          tit: '浏览数量',
85
          width: '160'
86
        },
87
        {
88
          operate: 'edit',
89
          width: '200'
90
        }
91
      ]
92
    }
93
  },
94
  components: {
95
    complexTable
96
  },
97
  methods: {
98
  }
99
}
100
</script>

+ 100 - 0
src/views/demandCen/publishedList.vue

@ -0,0 +1,100 @@
1
<template>
2
  <div class="app-container">
3
    <div class="box-container">
4
      <div class="contain-title">发布中内容列表</div>
5
      <div class="contain-search">
6
        <el-input placeholder="搜索内容标题" v-model="searchText" class="input-with-select">
7
          <el-button slot="append" icon="el-icon-search"></el-button>
8
        </el-input>
9
      </div>
10
      <div class="contian-operate">
11
        <el-button type="primary">发布内容</el-button>
12
      </div>
13
    </div>
14
    <div class="content-container">
15
      <div class="contain-select">
16
        <span>栏目分类:</span>
17
        <el-select v-model="selectMode" placeholder="选择分类">
18
          <el-option label="餐厅名" value="1"></el-option>
19
          <el-option label="订单号" value="2"></el-option>
20
          <el-option label="用户电话" value="3"></el-option>
21
        </el-select>
22
      </div>
23
      <complex-table :tableData="tableData" :tableItem="tableItem"></complex-table>
24
    </div>
25
  </div>
26
</template>
27
28
<script>
29
import complexTable from '@/components/complexTable'
30
export default {
31
  data() {
32
    return {
33
      searchText: '',
34
      selectMode: '',
35
      tableData: [
36
        {
37
          date: '2018/08/25 16:32',
38
          name: '关于征集企业技术创新需求的通知',
39
          class: '通知公告',
40
          owner: '张贝贝',
41
          num: '4552'
42
        }, {
43
          date: '2018/08/25 16:32',
44
          name: '关于征集企业技术创新需求的通知',
45
          class: '通知公告',
46
          owner: '张贝贝',
47
          num: '4552'
48
        }, {
49
          date: '2018/08/25 16:32',
50
          name: '关于征集企业技术创新需求的通知',
51
          class: '通知公告',
52
          owner: '张贝贝',
53
          num: '4552'
54
        }, {
55
          date: '2018/08/25 16:32',
56
          name: '关于征集企业技术创新需求的通知',
57
          class: '通知公告',
58
          owner: '张贝贝',
59
          num: '4552'
60
        }
61
      ],
62
      tableItem: [
63
        {
64
          prop: 'name',
65
          tit: '标题'
66
        },
67
        {
68
          prop: 'class',
69
          tit: '栏目分类',
70
          width: '160'
71
        },
72
        {
73
          prop: 'owner',
74
          tit: '发布人',
75
          width: '160'
76
        },
77
        {
78
          prop: 'date',
79
          tit: '发布时间',
80
          width: '160'
81
        },
82
        {
83
          prop: 'num',
84
          tit: '浏览数量',
85
          width: '160'
86
        },
87
        {
88
          operate: 'edit',
89
          width: '200'
90
        }
91
      ]
92
    }
93
  },
94
  components: {
95
    complexTable
96
  },
97
  methods: {
98
  }
99
}
100
</script>

+ 246 - 0
src/views/findPwd/index.vue

@ -0,0 +1,246 @@
1
<template>
2
  <div class="login-container">
3
    <div class="logo-wrapper">
4
      <div class="logo-img"></div>
5
    </div>
6
    <div class="form-wrapper">
7
      <div class="form-contain login-form">
8
        <h3 class="title">找回密码</h3>
9
        <div class="step-wrapper">
10
          <el-steps :active="stepVal" finish-status="success" align-center>
11
            <el-step title="输入手机号"></el-step>
12
            <el-step title="重置密码"></el-step>
13
          </el-steps>
14
        </div>
15
16
        <div class="step-contain">
17
          <el-form v-show="stepFisrt" :model="ruleForm" :rules="rules" ref="ruleForm" class="demo-ruleForm">
18
            <el-form-item prop="phoneNum">
19
              <el-input v-model="ruleForm.phoneNum" placeholder="请输入您的手机号码"></el-input>
20
            </el-form-item>
21
            <el-form-item prop="msgVC">
22
              <el-input v-model="ruleForm.msgVC" placeholder="请输入短信验证码" class="code-btn" style="width:100%">
23
                <el-button slot="append" type="primary" :disabled="phoneCodeBol" @click="clickMsgVcLogin">
24
                  <span v-if="sendMsgDisabled">{{seconds + '秒后获取'}}</span>
25
                  <span v-if="!sendMsgDisabled">获取验证码</span>
26
                </el-button>
27
             </el-input>
28
            </el-form-item>
29
            <el-form-item>
30
              <el-button class="log-btn" type="primary" :disabled="isDisabl" @click="nextStep('ruleForm')">下一步</el-button>
31
            </el-form-item>
32
            <el-form-item class="el-form-find">
33
              <el-button type="text" @click="goLogin">又想起来了</el-button>
34
            </el-form-item>
35
          </el-form>
36
          <el-form v-show="stepSecond" :model="ruleForm2" :rules="rules2" ref="ruleForm2" class="demo-ruleForm">
37
            <el-form-item prop="pass">
38
              <el-input type="password" v-model="ruleForm2.pass" placeholder="请设置您的新密码" auto-complete="off"></el-input>
39
            </el-form-item>
40
            <el-form-item prop="checkPass">
41
              <el-input type="password" v-model="ruleForm2.checkPass" placeholder="请再次输入密码确认" auto-complete="off"></el-input>
42
            </el-form-item>
43
            <el-form-item>
44
              <el-button class="log-btn" type="primary" :disabled="isDisabl" @click.native.prevent="resetPwd('ruleForm2')">重置密码</el-button>
45
            </el-form-item>
46
          </el-form>
47
        </div>
48
      </div>
49
    </div>
50
  </div>
51
</template>
52
53
<script>
54
  import { isReg, getResetMsgPhone, resetPwdByTel } from '@/api/login'
55
  import '@/styles/loginform.scss'
56
57
  export default {
58
    data() {
59
      var validPhone = (rule, value, callback) => {
60
        const reg = /^1[3|4|5|7|8][0-9]\d{8}$/
61
        if (!value) {
62
          callback(new Error('请输入您的手机号码'))
63
        } else if (!reg.test(value)) {
64
          callback(new Error('请输入正确的手机号码'))
65
        } else {
66
          callback()
67
        }
68
      }
69
      var validatePass = (rule, value, callback) => {
70
        if (value === '') {
71
          callback(new Error('请设置您的新密码'))
72
        } else if (value.length < 6 || value.length > 24) {
73
          callback(new Error('密码由6-24个字符组成,区分大小写'))
74
        } else {
75
          if (this.ruleForm2.checkPass !== '') {
76
            this.$refs.ruleForm2.validateField('checkPass')
77
          }
78
          callback()
79
        }
80
      }
81
      var validatePass2 = (rule, value, callback) => {
82
        if (value === '') {
83
          callback(new Error('请再次输入密码确认'))
84
        } else if (value !== this.ruleForm2.pass) {
85
          callback(new Error('两次输入密码不一致,请重新输入!'))
86
        } else {
87
          callback()
88
        }
89
      }
90
      return {
91
        phoneCodeBol: false,
92
        sendMsgDisabled: false,
93
        seconds: 60,
94
        platId: '',
95
        resetStepNum: '',
96
        resetCode: '',
97
        stepVal: 0,
98
        stepFisrt: true,
99
        stepSecond: false,
100
        isDisabl: false,
101
        ruleForm: {
102
          phoneNum: '',
103
          msgVC: ''
104
        },
105
        rules: {
106
          phoneNum: [
107
            { required: true, validator: validPhone, trigger: 'blur' }
108
          ],
109
          msgVC: [
110
            { required: true, message: '请输入短信验证码', trigger: 'blur' }
111
          ]
112
        },
113
        ruleForm2: {
114
          pass: '',
115
          checkPass: ''
116
        },
117
        rules2: {
118
          pass: [
119
            { validator: validatePass, trigger: 'blur' }
120
          ],
121
          checkPass: [
122
            { validator: validatePass2, trigger: 'blur' }
123
          ]
124
        }
125
      }
126
    },
127
    methods: {
128
      nextStep(formName) {
129
        this.$refs[formName].validate((valid) => {
130
          if (valid) {
131
            this.stepFisrt = false
132
            this.stepSecond = true
133
            this.stepVal = 1
134
          } else {
135
            return false
136
          }
137
        })
138
      },
139
      userRegisterOk() {
140
        const me = this
141
        const account = this.ruleForm.phoneNum
142
        isReg({ account }).then(res => {
143
          if (res.success) {
144
            if (res.data === true) {
145
              me.sendMsgDisabled = false
146
              me.phoneCodeBol = false
147
              me.$message({
148
                message: '该账号不存在,请检查后重试',
149
                type: 'warning'
150
              })
151
            } else {
152
              me.getResetMsgPhone()
153
              me.sendMsgDisabled = true
154
              me.phoneCodeBol = true
155
              const interval = window.setInterval(function() {
156
                if ((me.seconds--) <= 0) {
157
                  me.seconds = 60
158
                  me.sendMsgDisabled = false
159
                  me.phoneCodeBol = false
160
                  window.clearInterval(interval)
161
                }
162
              }, 1000)
163
            }
164
          }
165
        })
166
      },
167
      getResetMsgPhone() {
168
        const me = this
169
        const account = this.ruleForm.phoneNum
170
        const checkExists = true
171
        getResetMsgPhone({ account, checkExists }).then((res) => {
172
          if (!res.success) {
173
            if (res.code === -60000) {
174
              me.sendMsgDisabled = false
175
              me.phoneCodeBol = false
176
              me.$message({
177
                message: '该账号不存在,请检查后重试',
178
                type: 'warning'
179
              })
180
            } else {
181
              me.$message({
182
                message: res.detailMsg,
183
                type: 'warning'
184
              })
185
            }
186
          }
187
        })
188
      },
189
      clickMsgVcLogin() {
190
        const reg = /^1[3|4|5|7|8][0-9]\d{8}$/
191
        if (!this.ruleForm.phoneNum) {
192
          this.$message({
193
            message: '请输入你的手机号码',
194
            type: 'warning'
195
          })
196
        } else if (!reg.test(this.ruleForm.phoneNum)) {
197
          this.$message({
198
            message: '请输入正确的手机号码',
199
            type: 'warning'
200
          })
201
        } else {
202
          this.userRegisterOk()
203
        }
204
      },
205
      resetPwd(formName) {
206
        this.$refs[formName].validate((valid) => {
207
          if (valid) {
208
            resetPwdByTel(this.ruleForm2.pass, this.ruleForm.msgVC).then((res) => {
209
              if (res.success) {
210
                this.$alert('密码已重置,快去登录吧!', '提示', {
211
                  confirmButtonText: '确定',
212
                  type: 'success',
213
                  center: true,
214
                  callback: action => {
215
                    if (action === 'confirm') {
216
                      this.$router.push({ path: '/login' })
217
                    }
218
                  }
219
                })
220
              } else {
221
                this.$alert('密码重置失败!', '提示', {
222
                  confirmButtonText: '重新找回密码',
223
                  type: 'warning',
224
                  center: true,
225
                  callback: action => {
226
                    if (action === 'confirm') {
227
                      this.stepFisrt = true
228
                      this.stepSecond = false
229
                      this.stepVal = 0
230
                    }
231
                  }
232
                })
233
                return
234
              }
235
            })
236
          } else {
237
            return false
238
          }
239
        })
240
      },
241
      goLogin() {
242
        this.$router.push({ path: '/login' })
243
      }
244
    }
245
  }
246
</script>

+ 86 - 0
src/views/layout/Layout.vue

@ -0,0 +1,86 @@
1
<template>
2
  <div class="app-wrapper" :class="classObj">
3
     <!-- v-if="device==='mobile'&&sidebar.opened"  @click="handleClickOutside" -->
4
    <!-- <div class="drawer-bg"></div> -->
5
    <TopNavbar></TopNavbar>
6
    <!-- <Navigation v-if="roles.indexOf('2')<0" ></Navigation> -->
7
    <div class='containerBox'>
8
      <sidebar class="sidebar-container"></sidebar>
9
      <div class="main-container" style='padding-top:0px;'>
10
        <navbar></navbar>
11
        <app-main></app-main>
12
      </div>
13
    </div>
14
  </div>
15
</template>
16
17
<script>
18
import { mapGetters } from 'vuex'
19
import { TopNavbar, Navbar, Sidebar, AppMain } from './components'
20
// import Navigation from '../nav'
21
import ResizeMixin from './mixin/ResizeHandler'
22
23
export default {
24
  name: 'layout',
25
  components: {
26
    TopNavbar,
27
    Navbar,
28
    Sidebar,
29
    AppMain
30
    // Navigation
31
  },
32
  mixins: [ResizeMixin],
33
  computed: {
34
    ...mapGetters([
35
      'roles'
36
    ]),
37
    sidebar() {
38
      return this.$store.state.app.sidebar
39
    },
40
    device() {
41
      return this.$store.state.app.device
42
    },
43
    classObj() {
44
      return {
45
        // hideSidebar: !this.sidebar.opened,
46
        // openSidebar: this.sidebar.opened,
47
        // withoutAnimation: this.sidebar.withoutAnimation,
48
        // mobile: this.device === 'mobile'
49
      }
50
    }
51
  },
52
  methods: {
53
    // handleClickOutside() {
54
    //   this.$store.dispatch('CloseSideBar', { withoutAnimation: false })
55
    // }
56
  }
57
}
58
</script>
59
60
<style rel="stylesheet/scss" lang="scss" scoped>
61
  @import "src/styles/mixin.scss";
62
  .app-wrapper {
63
    padding-top: 50px;
64
    @include clearfix;
65
    position: relative;
66
    height: 100%;
67
    &.mobile.openSidebar{
68
      position: fixed;
69
      top: 0;
70
    }
71
    .containerBox {
72
      margin: auto;
73
      box-sizing: border-box;
74
      height:100%;
75
    }
76
  }
77
  .drawer-bg {
78
    background: #000;
79
    opacity: 0.3;
80
    width: 100%;
81
    top: 0;
82
    height: 100%;
83
    position: absolute;
84
    z-index: 999;
85
  }
86
</style>

+ 28 - 0
src/views/layout/components/AppMain.vue

@ -0,0 +1,28 @@
1
<template>
2
  <section class="app-main">
3
    <transition name="fade" mode="out-in">
4
      <router-view :key="key"></router-view>
5
      <!-- <router-view></router-view> -->
6
    </transition>
7
  </section>
8
</template>
9
10
<script>
11
export default {
12
  name: 'AppMain',
13
  computed: {
14
    key() {
15
      return this.$route.name !== undefined ? this.$route.name + +new Date() : this.$route + +new Date()
16
    }
17
  }
18
}
19
</script>
20
21
<style scoped>
22
.app-main {
23
  /*50 = navbar  */
24
  min-height: 100%;
25
  position: relative;
26
  overflow: hidden;
27
}
28
</style>

+ 67 - 0
src/views/layout/components/Navbar.vue

@ -0,0 +1,67 @@
1
<template>
2
  <div>
3
    <el-menu class="navbar" mode="horizontal">
4
      <!-- <hamburger  class="hamburger-container" :toggleClick="toggleSideBar" :isActive="sidebar.opened"></hamburger> -->
5
      <breadcrumb></breadcrumb>
6
    </el-menu>
7
  </div>
8
</template>
9
10
<script>
11
// import { mapGetters } from 'vuex'
12
// import Marqueebox from '@/components/Marqueebox'
13
import Breadcrumb from '@/components/Breadcrumb'
14
// import Hamburger from '@/components/Hamburger'
15
16
export default {
17
  components: {
18
    Breadcrumb
19
    // Hamburger,
20
    // Marqueebox
21
  },
22
  computed: {
23
    // ...mapGetters([
24
    //   'sidebar',
25
    //   'roles'
26
    // ])
27
  },
28
  methods: {
29
    // toggleSideBar() {
30
    //   this.$store.dispatch('ToggleSideBar')
31
    // },
32
    // logout() {
33
    //   this.$store.dispatch('LogOut').then(() => {
34
    //     location.reload() // 为了重新实例化vue-router对象 避免bug
35
    //   })
36
    // }
37
  }
38
}
39
</script>
40
41
<style rel="stylesheet/scss" lang="scss" scoped>
42
.navbar {
43
  height: 50px;
44
  line-height: 50px;
45
  padding: 0 12px;
46
  border-radius: 0px !important;
47
  .hamburger-container {
48
    line-height: 58px;
49
    height: 50px;
50
    float: left;
51
    padding: 0 10px;
52
  }
53
  .screenfull {
54
    position: absolute;
55
    right: 90px;
56
    top: 16px;
57
    color: red;
58
  }
59
}
60
.message-box{
61
  color: #303133;
62
  background: #c7e3ff;
63
  padding: 0 20px;
64
  font-size: 14px;
65
}
66
</style>
67

+ 78 - 0
src/views/layout/components/Sidebar/SidebarItem.vue

@ -0,0 +1,78 @@
1
<template>
2
  <div v-if="!item.hidden&&item.children" class="menu-wrapper">
3
4
      <router-link v-if="hasOneShowingChild(item.children) && !onlyOneChild.children&&!item.alwaysShow" :to="resolvePath(onlyOneChild.path)">
5
        <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
6
          <svg-icon v-if="onlyOneChild.meta&&onlyOneChild.meta.icon" :icon-class="onlyOneChild.meta.icon"></svg-icon>
7
          <span v-if="onlyOneChild.meta&&onlyOneChild.meta.title" slot="title">{{onlyOneChild.meta.title}}</span>
8
        </el-menu-item>
9
      </router-link>
10
11
      <el-submenu v-else :index="item.name||item.path">
12
        <template slot="title">
13
          <svg-icon v-if="item.meta&&item.meta.icon" :icon-class="item.meta.icon"></svg-icon>
14
          <span v-if="item.meta&&item.meta.title" slot="title">{{item.meta.title}}</span>
15
        </template>
16
17
        <template v-for="child in item.children" v-if="!child.hidden">
18
          <sidebar-item :is-nest="true" class="nest-menu" v-if="child.children&&child.children.length>0" :item="child" :key="child.path" :base-path="resolvePath(child.path)"></sidebar-item>
19
20
          <router-link v-else :to="resolvePath(child.path)" :key="child.name" replace>
21
            <el-menu-item :index="resolvePath(child.path)">
22
              <svg-icon v-if="child.meta&&child.meta.icon" :icon-class="child.meta.icon"></svg-icon>
23
              <span v-if="child.meta&&child.meta.title" slot="title">{{child.meta.title}}</span>
24
            </el-menu-item>
25
          </router-link>
26
        </template>
27
      </el-submenu>
28
29
  </div>
30
</template>
31
32
<script>
33
import path from 'path'
34
35
export default {
36
  name: 'SidebarItem',
37
  props: {
38
    // route配置json
39
    item: {
40
      type: Object,
41
      required: true
42
    },
43
    isNest: {
44
      type: Boolean,
45
      default: false
46
    },
47
    basePath: {
48
      type: String,
49
      default: ''
50
    }
51
  },
52
  data() {
53
    return {
54
      onlyOneChild: null
55
    }
56
  },
57
  methods: {
58
    hasOneShowingChild(children) {
59
      const showingChildren = children.filter(item => {
60
        if (item.hidden) {
61
          return false
62
        } else {
63
          // temp set(will be used if only has one showing child )
64
          this.onlyOneChild = item
65
          return true
66
        }
67
      })
68
      if (showingChildren.length === 1) {
69
        return true
70
      }
71
      return false
72
    },
73
    resolvePath(...paths) {
74
      return path.resolve(this.basePath, ...paths)
75
    }
76
  }
77
}
78
</script>

+ 28 - 0
src/views/layout/components/Sidebar/index.vue

@ -0,0 +1,28 @@
1
<template>
2
  <el-scrollbar wrapClass="scrollbar-wrapper">
3
    <el-menu
4
      mode="vertical"
5
      :show-timeout="200"
6
      :default-active="$route.path"
7
      background-color="#304156"
8
      text-color="#bfcbd9"
9
      active-text-color="#409EFF"
10
    >
11
      <sidebar-item v-for="route in routes" :key="route.name" :item="route" :base-path="route.path"></sidebar-item>
12
    </el-menu>
13
  </el-scrollbar>
14
</template>
15
16
<script>
17
import { mapGetters } from 'vuex'
18
import SidebarItem from './SidebarItem'
19
20
export default {
21
  components: { SidebarItem },
22
  computed: {
23
    routes() {
24
      return this.$router.options.routes
25
    }
26
  }
27
}
28
</script>

+ 43 - 0
src/views/layout/components/Sidebar2.vue

@ -0,0 +1,43 @@
1
<template>
2
  <el-scrollbar wrapClass="scrollbar-wrapper">
3
    <el-menu
4
      router
5
      :default-active="defaultActive"
6
      class="el-menu-sidebar"
7
      active-text-color='#29A88D'
8
      background-color="#1a76a5"
9
      text-color="#fff"
10
      unique-opened>
11
      <NavMenu :navMenus="menusArr"></NavMenu>
12
    </el-menu>
13
  </el-scrollbar>
14
</template>
15
16
<script>
17
import request from '@/utils/request'
18
import NavMenu from '@/components/TreeMenu'
19
export default {
20
  name: 'LeftMenus',
21
  components: {
22
    NavMenu
23
  },
24
  data() {
25
    return {
26
      defaultActive: '0',
27
      menusArr: []
28
    }
29
  },
30
  created() {
31
    var that = this
32
    var date = new Date()
33
    var timer = date.getTime().toString()
34
    request.get('../../../static/menu.json?t=' + timer, {}, function(res) {
35
      that.menusArr = res.data
36
    })
37
  }
38
}
39
</script>
40
41
<style scoped>
42
43
</style>

+ 132 - 0
src/views/layout/components/TopNavbar.vue

@ -0,0 +1,132 @@
1
<template>
2
  <div class="topnavbar">
3
    <div class='topnavbarBox'>
4
      <div class="logo-container">
5
        <div class="logo-wrapper" @click="toHome">科袖科技条件平台_后台管理系统</div>
6
      </div>
7
      <div class="name-box">
8
        <span>您好,{{ name }}</span>
9
        <span class="exit-btn" @click="logout">退出登录</span>
10
      </div>
11
    </div>
12
  </div>
13
</template>
14
15
<script>
16
import { mapGetters } from 'vuex'
17
import { MessageBox } from 'element-ui'
18
import Cookies from 'js-cookie'
19
20
export default {
21
  data() {
22
    return {
23
      bridgeId: '',
24
      showName: '',
25
      dataList: ''
26
    }
27
  },
28
  computed: {
29
    ...mapGetters([
30
      'name',
31
      'roles'
32
    ])
33
  },
34
  watch: {
35
    '$route'(to, from) {
36
      if (to.path === '/dashboard') {
37
        var dataList = this.dataList
38
        for (let i = 0; i < dataList.length; i++) {
39
          dataList[i].disab = false
40
        }
41
        Cookies.remove('bridgeId')
42
        Cookies.remove('bridgeName')
43
        this.showName = ''
44
      } else {
45
        this.bridgeId = Cookies.get('bridgeId')
46
        this.showName = Cookies.get('bridgeName')
47
      }
48
    }
49
  },
50
  created() {
51
    this.bridgeId = Cookies.get('bridgeId')
52
    this.showName = Cookies.get('bridgeName')
53
  },
54
  methods: {
55
    toHome() {
56
      this.$router.replace({ path: '/' })
57
    },
58
    toggleSideBar() {
59
      this.$store.dispatch('ToggleSideBar')
60
    },
61
    logout() {
62
      MessageBox.confirm('您确认要退出登录吗?', '提示', {
63
        confirmButtonText: '确定',
64
        cancelButtonText: '取消',
65
        type: 'warning',
66
        center: true
67
      }).then(() => {
68
        this.$store.dispatch('LogOut').then(() => {
69
          Cookies.remove('bridgeId')
70
          Cookies.remove('bridgeName')
71
          location.reload() // 为了重新实例化vue-router对象 避免bug
72
        })
73
      }).catch(() => {
74
        console.log('已取消退出')
75
      })
76
    },
77
    goToDashboardC(id, name) {
78
      this.showName = name
79
      Cookies.set('bridgeId', id)
80
      Cookies.set('bridgeName', name)
81
      this.$router.replace({
82
        name: 'bridgeDetail',
83
        query: { id: id, name: name }
84
      })
85
    }
86
  }
87
}
88
</script>
89
90
<style rel="stylesheet/scss" lang="scss" scoped>
91
.topnavbar {
92
  position: fixed;
93
  font-size: 0px;
94
  top: 0;
95
  left: 0;
96
  right: 0;
97
  height: 50px;
98
  line-height: 50px;
99
  z-index:1002;
100
  border-radius: 0px !important;
101
  background-color: #2d3a4b;
102
  border-bottom: 1px solid #e6e6e6;
103
  .topnavbarBox {
104
    position: relative;
105
    margin: auto;
106
    box-sizing: border-box;
107
    padding: 0 10px;
108
    .logo-container {
109
      font-size: 22px;
110
      font-weight: bold;
111
      color: #efefef;
112
      display: inline-block;
113
      position: absolute;
114
      left:10px;
115
      overflow: hidden;
116
    }
117
    .name-box{
118
      display: inline-block;
119
      position: absolute;
120
      right: 20px;
121
      font-size:14px;
122
      overflow: hidden;
123
      color:#fff;
124
      .exit-btn {
125
        margin-left:30px;
126
        cursor: pointer;
127
      }
128
    }
129
  }
130
}
131
</style>
132

+ 4 - 0
src/views/layout/components/index.js

@ -0,0 +1,4 @@
1
export { default as TopNavbar } from './TopNavbar'
2
export { default as Navbar } from './Navbar'
3
export { default as Sidebar } from './Sidebar/index'
4
export { default as AppMain } from './AppMain'

+ 41 - 0
src/views/layout/mixin/ResizeHandler.js

@ -0,0 +1,41 @@
1
import store from '@/store'
2
3
const { body } = document
4
const WIDTH = 1024
5
const RATIO = 3
6
7
export default {
8
  watch: {
9
    $route(route) {
10
      if (this.device === 'mobile' && this.sidebar.opened) {
11
        store.dispatch('CloseSideBar', { withoutAnimation: false })
12
      }
13
    }
14
  },
15
  beforeMount() {
16
    window.addEventListener('resize', this.resizeHandler)
17
  },
18
  mounted() {
19
    const isMobile = this.isMobile()
20
    if (isMobile) {
21
      store.dispatch('ToggleDevice', 'mobile')
22
      store.dispatch('CloseSideBar', { withoutAnimation: true })
23
    }
24
  },
25
  methods: {
26
    isMobile() {
27
      const rect = body.getBoundingClientRect()
28
      return rect.width - RATIO < WIDTH
29
    },
30
    resizeHandler() {
31
      if (!document.hidden) {
32
        const isMobile = this.isMobile()
33
        store.dispatch('ToggleDevice', isMobile ? 'mobile' : 'desktop')
34
35
        if (isMobile) {
36
          store.dispatch('CloseSideBar', { withoutAnimation: true })
37
        }
38
      }
39
    }
40
  }
41
}

+ 145 - 0
src/views/login/index.vue

@ -0,0 +1,145 @@
1
<template>
2
  <div class="login-container">
3
    <div class="logo-wrapper">
4
      <div class="logo-img"></div>
5
    </div>
6
    <el-form class="login-form" autoComplete="on" :model="loginForm" :rules="loginRules" ref="loginForm" label-position="left">
7
      <h3 class="title">登录</h3>
8
      <el-form-item prop="username">
9
        <span class="svg-container svg-container_login">
10
          <svg-icon icon-class="user" />
11
        </span>
12
        <el-input name="username" type="text" v-model="loginForm.username" autoComplete="on" placeholder="请输入您的手机号码" maxlength="11" />
13
      </el-form-item>
14
      <el-form-item prop="password">
15
        <span class="svg-container">
16
          <svg-icon icon-class="password"/>
17
        </span>
18
        <el-input name="password" :type="pwdType" v-model="loginForm.password" autoComplete="on"
19
          placeholder="请输入您的登录密码" maxlength="24"></el-input>
20
          <span class="show-pwd" @click="showPwd"><svg-icon icon-class="eye" v-show="!falg"/><svg-icon icon-class="password-view" v-show="falg"/></span>
21
      </el-form-item>
22
      <el-form-item prop="imgVerifyCode">
23
        <span class="svg-container">
24
          <svg-icon icon-class="msgvc"></svg-icon>
25
        </span>
26
        <el-input v-model="loginForm.imgVerifyCode" placeholder="请输入图形验证码" @keyup.enter.native="handleLogin" class="code-btn" maxlength="4">
27
        <img slot="append" :src="imgVcUrl" @click="changeImgVc" /></el-input>
28
      </el-form-item>
29
      <el-form-item>
30
        <el-button class="log-btn" type="primary" :loading="loading" @click.native.prevent="handleLogin">登录</el-button>
31
      </el-form-item>
32
      <el-form-item class="el-form-find">
33
        <el-button type="text" @click.native.prevent="goBackPwd">忘记密码?</el-button>
34
      </el-form-item>
35
    </el-form>
36
  </div>
37
</template>
38
39
<script>
40
import { Message } from 'element-ui'
41
import { getPictureVC } from '@/api/pictureVc'
42
import '@/styles/loginform.scss'
43
44
export default {
45
  name: 'login',
46
  data() {
47
    var validPhone = (rule, value, callback) => {
48
      const reg = /^1[3|4|5|7|8][0-9]\d{8}$/
49
      if (!value) {
50
        callback(new Error('请输入您的手机号码'))
51
      } else if (!reg.test(value)) {
52
        callback(new Error('请输入正确的手机号码'))
53
      } else {
54
        callback()
55
      }
56
    }
57
    return {
58
      falg: false,
59
      imgVcUrl: '',
60
      loginForm: {
61
        username: 'admin',
62
        password: 'admin',
63
        imgVerifyCode: ''
64
      },
65
      loginRules: {
66
        // username: [{ required: true, trigger: 'blur', validator: validPhone }],
67
        // password: [
68
        //   { required: true, message: '请输入您的登录密码', trigger: 'blur' },
69
        //   { min: 6, max: 24, message: '密码由6-24个字符组成,区分大小写', trigger: 'blur' }
70
        // ],
71
        // imgVerifyCode: [{ required: true, message: '请输入图形验证码', trigger: 'blur' }]
72
      },
73
      loading: false,
74
      pwdType: 'password'
75
    }
76
  },
77
  created() {
78
    this.changeImgVc()
79
  },
80
  methods: {
81
    showPwd() {
82
      this.falg = !this.falg
83
      if (this.pwdType === 'password') {
84
        this.pwdType = ''
85
      } else {
86
        this.pwdType = 'password'
87
      }
88
    },
89
    handleLogin() {
90
      this.$router.push({ path: '/dashboard' })
91
      // this.$refs.loginForm.validate(valid => {
92
      //   if (valid) {
93
      //     this.loading = true
94
      //     this.$store.dispatch('LoginByUsername', this.loginForm).then((response) => {
95
      //       this.loading = false
96
      //       if (response.success) {
97
      //         if (response.data) {
98
      //           this.$store.dispatch('GetUserInfo').then(res => {
99
      //           })
100
      //           this.$router.push({ path: '/dashboard' })
101
      //         } else {
102
      //           Message.error('登录账号与密码不匹配,请检查后重试')
103
      //           this.changeImgVc()
104
      //           return
105
      //         }
106
      //       } else {
107
      //         const errorCode = [{
108
      //           code: -60001,
109
      //           msg: '图形验证码不存在'
110
      //         }, {
111
      //           code: -60002,
112
      //           msg: '图形验证码超时'
113
      //         }, {
114
      //           code: -60003,
115
      //           msg: '图形验证码不正确'
116
      //         }, {
117
      //           code: -60005,
118
      //           msg: '该账号已停用,请联系管理员'
119
      //         }]
120
      //         for (let i = 0; i < errorCode.length; i++) {
121
      //           if (response.code === errorCode[i].code) {
122
      //             Message.error(errorCode[i].msg)
123
      //             this.changeImgVc()
124
      //             return
125
      //           }
126
      //         }
127
      //       }
128
      //     }).catch(() => {
129
      //       this.loading = false
130
      //     })
131
      //   } else {
132
      //     console.log('error submit!!')
133
      //     return false
134
      //   }
135
      // })
136
    },
137
    goBackPwd() {
138
      this.$router.push({ path: '/findPwd' })
139
    },
140
    changeImgVc() {
141
      this.imgVcUrl = getPictureVC('PIC_LOGIN')
142
    }
143
  }
144
}
145
</script>

+ 0 - 0
static/.gitkeep


BIN
static/login_bg.jpg


+ 224 - 0
static/menu.json

@ -0,0 +1,224 @@
1
{
2
	"success": true,
3
	"data": [{
4
		"icon": "branch",
5
		"caption": "参数",
6
		"modal": false,
7
		"children": [{
8
			"icon": "book",
9
			"caption": "资源管理",
10
			"modal": false,
11
			"children": [{
12
				"icon": "book",
13
				"res": "sys_reso_index",
14
				"caption": "资源管理一",
15
				"modal": false
16
			}, {
17
				"icon": "book",
18
				"res": "sys_dict85_index",
19
				"caption": "资源管理二",
20
				"modal": false
21
			}]
22
		}, {
23
			"icon": "book",
24
			"res": "sys_dict_index",
25
			"caption": "数据字典管理",
26
			"modal": false
27
		}, {
28
			"icon": "book",
29
			"res": "sys_right_index",
30
			"caption": "权限名称",
31
			"modal": false
32
		}]
33
	}, {
34
		"icon": "branch",
35
		"caption": "管理",
36
		"modal": false,
37
		"children": [{
38
			"icon": "book",
39
			"res": "sys_role_index",
40
			"caption": "角色管理",
41
			"modal": false
42
		}, {
43
			"icon": "book",
44
			"res": "sys_user_index",
45
			"caption": "用户管理",
46
			"modal": false
47
		}]
48
	}, {
49
		"icon": "branch",
50
		"caption": "业务运营",
51
		"modal": false,
52
		"children": [{
53
			"icon": "book",
54
			"res": "sys_demand_index",
55
			"caption": "需求管理",
56
			"modal": false
57
		}, {
58
			"icon": "book",
59
			"res": "sys_consult_msgidx",
60
			"caption": "消息管理",
61
			"modal": false
62
		}, {
63
			"icon": "book",
64
			"res": "sys_feedback_index",
65
			"caption": "意见反馈管理",
66
			"modal": false
67
		}]
68
	}, {
69
		"icon": "branch",
70
		"caption": "企业用户运营",
71
		"modal": false,
72
		"children": [{
73
			"icon": "book",
74
			"res": "sys_orgapply_index",
75
			"caption": "企业认证审核",
76
			"modal": false
77
		}, {
78
			"icon": "book",
79
			"res": "sys_org_index",
80
			"caption": "企业信息管理",
81
			"modal": false
82
		}]
83
	}, {
84
		"icon": "branch",
85
		"caption": "用户运营",
86
		"modal": false,
87
		"children": [{
88
			"icon": "book",
89
			"res": "sys_realname_index",
90
			"caption": "实名认证审核",
91
			"modal": false
92
		}, {
93
			"icon": "book",
94
			"res": "sys_expert_index",
95
			"caption": "专家认证审核",
96
			"modal": false
97
		}, {
98
			"icon": "book",
99
			"res": "sys_userinfo_index",
100
			"caption": "专家录入",
101
			"modal": false
102
		}, {
103
			"icon": "book",
104
			"res": "sys_userinfo_check",
105
			"caption": "专家录入审核",
106
			"modal": false
107
		}, {
108
			"icon": "book",
109
			"res": "sys_professornew_index",
110
			"caption": "用户信息管理",
111
			"modal": false
112
		}]
113
	}, {
114
		"icon": "branch",
115
		"caption": "内容运营",
116
		"modal": false,
117
		"children": [{
118
			"icon": "book",
119
			"res": "sys_article_index",
120
			"caption": "文章管理",
121
			"modal": false
122
		}, {
123
			"icon": "book",
124
			"res": "sys_question_index",
125
			"caption": "问题管理",
126
			"modal": false
127
		}, {
128
			"icon": "book",
129
			"res": "sys_answer_index",
130
			"caption": "回答管理",
131
			"modal": false
132
		}, {
133
			"icon": "book",
134
			"res": "sys_disbanner_index",
135
			"caption": "发现banner设置",
136
			"modal": false
137
		}, {
138
			"icon": "book",
139
			"res": "sys_resourceinfo_index",
140
			"caption": "资源管理",
141
			"modal": false
142
		}, {
143
			"icon": "book",
144
			"res": "sys_papent_index",
145
			"caption": "专利管理",
146
			"modal": false
147
		}, {
148
			"icon": "book",
149
			"res": "sys_paper_index",
150
			"caption": "论文管理",
151
			"modal": false
152
		}, {
153
			"icon": "book",
154
			"res": "sys_result_index",
155
			"caption": "科技成果管理",
156
			"modal": false
157
		}, {
158
			"icon": "book",
159
			"res": "sys_ware_index",
160
			"caption": "服务管理",
161
			"modal": false
162
		}, {
163
			"icon": "book",
164
			"res": "sys_product_index",
165
			"caption": "产品管理",
166
			"modal": false
167
		}]
168
	}, {
169
		"icon": "branch",
170
		"caption": "统计分析",
171
		"modal": false,
172
		"children": [{
173
			"icon": "book",
174
			"res": "sys_article_viewcount",
175
			"caption": "文章流量统计",
176
			"modal": false
177
		}, {
178
			"icon": "book",
179
			"res": "sys_usercount_index",
180
			"caption": "新增用户统计",
181
			"modal": false
182
		}, {
183
			"icon": "book",
184
			"res": "sys_chart_index",
185
			"caption": "用户分类统计",
186
			"modal": false
187
		}, {
188
			"icon": "book",
189
			"res": "sys_searchword_index",
190
			"caption": "搜索词记录",
191
			"modal": false
192
		}, {
193
			"icon": "book",
194
			"res": "sys_content_index",
195
			"caption": "内容流量查询",
196
			"modal": false
197
		}]
198
	}, {
199
		"icon": "branch",
200
		"caption": "平台运营",
201
		"modal": false,
202
		"children": [{
203
			"icon": "book",
204
			"res": "sys_platform_index",
205
			"caption": "平台信息管理",
206
			"modal": false
207
		}, {
208
			"icon": "book",
209
			"res": "sys_buttedpro_index",
210
			"caption": "对接专家管理",
211
			"modal": false
212
		}, {
213
			"icon": "book",
214
			"res": "sys_buttenorg_index",
215
			"caption": "对接机构管理",
216
			"modal": false
217
		}, {
218
			"icon": "book",
219
			"res": "sys_residentorg_index",
220
			"caption": "入驻企业管理",
221
			"modal": false
222
		}]
223
	}]
224
}

BIN
static/touchwave.png