lipengtao преди 6 години
ревизия
7e7ac2efd0
променени са 118 файла, в които са добавени 7849 реда и са изтрити 0 реда
  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. 4 0
      config/prod.env.js
  21. BIN
      favicon.ico
  22. 12 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. 91 0
      src/directive/sticky.js
  42. 13 0
      src/directive/waves/index.js
  43. 26 0
      src/directive/waves/waves.css
  44. 42 0
      src/directive/waves/waves.js
  45. 9 0
      src/icons/index.js
  46. 1 0
      src/icons/svg/Department.svg
  47. 1 0
      src/icons/svg/doctor.svg
  48. 1 0
      src/icons/svg/example.svg
  49. 1 0
      src/icons/svg/eye.svg
  50. 1 0
      src/icons/svg/form.svg
  51. 1 0
      src/icons/svg/hospital.svg
  52. 1 0
      src/icons/svg/instrument.svg
  53. 1 0
      src/icons/svg/list.svg
  54. 1 0
      src/icons/svg/msgvc.svg
  55. 1 0
      src/icons/svg/nested.svg
  56. 1 0
      src/icons/svg/password-view.svg
  57. 1 0
      src/icons/svg/password.svg
  58. 1 0
      src/icons/svg/peoples.svg
  59. 1 0
      src/icons/svg/table.svg
  60. 1 0
      src/icons/svg/tree.svg
  61. 1 0
      src/icons/svg/unread.svg
  62. 1 0
      src/icons/svg/user.svg
  63. 27 0
      src/main.js
  64. 63 0
      src/permission.js
  65. 197 0
      src/router/index.js
  66. 13 0
      src/store/getters.js
  67. 19 0
      src/store/index.js
  68. 43 0
      src/store/modules/app.js
  69. 60 0
      src/store/modules/permission.js
  70. 111 0
      src/store/modules/user.js
  71. 53 0
      src/styles/element-ui.scss
  72. 91 0
      src/styles/index.scss
  73. 144 0
      src/styles/loginform.scss
  74. 27 0
      src/styles/mixin.scss
  75. 106 0
      src/styles/roleuser.scss
  76. 118 0
      src/styles/sidebar.scss
  77. 32 0
      src/styles/transition.scss
  78. 4 0
      src/styles/variables.scss
  79. 13 0
      src/utils/auth.js
  80. 87 0
      src/utils/index.js
  81. 138 0
      src/utils/queryBase.js
  82. 54 0
      src/utils/queryDict.js
  83. 81 0
      src/utils/queryInfo.js
  84. 54 0
      src/utils/request.js
  85. 78 0
      src/utils/timingConstruct.js
  86. 236 0
      src/views/404.vue
  87. 397 0
      src/views/baseInfoManage/boxesConfig/index.vue
  88. 525 0
      src/views/baseInfoManage/bridgesInfo/index.vue
  89. 453 0
      src/views/baseInfoManage/sensorsConfig/index.vue
  90. 393 0
      src/views/baseInfoManage/serversConfig/index.vue
  91. 45 0
      src/views/dashboard/admin/index.vue
  92. 26 0
      src/views/dashboard/index.vue
  93. 250 0
      src/views/findPwd/index.vue
  94. 3 0
      src/views/home/index.vue
  95. 3 0
      src/views/hospital/index.vue
  96. 3 0
      src/views/intelligentJudgment/index.vue
  97. 86 0
      src/views/layout/Layout.vue
  98. 78 0
      src/views/layout/common.vue
  99. 45 0
      src/views/layout/components/Abb.vue
  100. 28 0
      src/views/layout/components/AppMain.vue
  101. 67 0
      src/views/layout/components/Navbar.vue
  102. 78 0
      src/views/layout/components/Sidebar/SidebarItem.vue
  103. 37 0
      src/views/layout/components/Sidebar/index.vue
  104. 189 0
      src/views/layout/components/TopNavbar.vue
  105. 5 0
      src/views/layout/components/index.js
  106. 41 0
      src/views/layout/mixin/ResizeHandler.js
  107. 148 0
      src/views/login/index.vue
  108. 3 0
      src/views/medicalTreatment/index.vue
  109. 51 0
      src/views/nav/index.vue
  110. 3 0
      src/views/peoplesManage/accountSettings/index.vue
  111. 15 0
      src/views/peoplesManage/infoManage/editSystemMessage.vue
  112. 285 0
      src/views/peoplesManage/infoManage/editUser.vue
  113. 216 0
      src/views/peoplesManage/infoManage/editUserPermissions.vue
  114. 214 0
      src/views/peoplesManage/infoManage/index.vue
  115. 3 0
      src/views/sharedDevice/index.vue
  116. 0 0
      static/.gitkeep
  117. BIN
      static/login_bg.jpg
  118. 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: './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: '"https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin"',
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: 9526, // 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
}

+ 4 - 0
config/prod.env.js

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

BIN
favicon.ico


+ 12 - 0
index.html

@ -0,0 +1,12 @@
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
    <title>声脉桥梁云监控平台</title>
7
  </head>
8
  <body>
9
    <div id="app"></div>
10
    <!-- built files will be auto injected -->
11
  </body>
12
</html>

+ 82 - 0
package.json

@ -0,0 +1,82 @@
1
{
2
  "name": "vueAdmin-touchwave",
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>

+ 91 - 0
src/directive/sticky.js

@ -0,0 +1,91 @@
1
const vueSticky = {}
2
let listenAction
3
vueSticky.install = Vue => {
4
  Vue.directive('sticky', {
5
    inserted(el, binding) {
6
      const params = binding.value || {}
7
      const stickyTop = params.stickyTop || 0
8
      const zIndex = params.zIndex || 1000
9
      const elStyle = el.style
10
11
      elStyle.position = '-webkit-sticky'
12
      elStyle.position = 'sticky'
13
      // if the browser support css sticky(Currently Safari, Firefox and Chrome Canary)
14
      // if (~elStyle.position.indexOf('sticky')) {
15
      //     elStyle.top = `${stickyTop}px`;
16
      //     elStyle.zIndex = zIndex;
17
      //     return
18
      // }
19
      const elHeight = el.getBoundingClientRect().height
20
      const elWidth = el.getBoundingClientRect().width
21
      elStyle.cssText = `top: ${stickyTop}px; z-index: ${zIndex}`
22
23
      const parentElm = el.parentNode || document.documentElement
24
      const placeholder = document.createElement('div')
25
      placeholder.style.display = 'none'
26
      placeholder.style.width = `${elWidth}px`
27
      placeholder.style.height = `${elHeight}px`
28
      parentElm.insertBefore(placeholder, el)
29
30
      let active = false
31
32
      const getScroll = (target, top) => {
33
        const prop = top ? 'pageYOffset' : 'pageXOffset'
34
        const method = top ? 'scrollTop' : 'scrollLeft'
35
        let ret = target[prop]
36
        if (typeof ret !== 'number') {
37
          ret = window.document.documentElement[method]
38
        }
39
        return ret
40
      }
41
42
      const sticky = () => {
43
        if (active) {
44
          return
45
        }
46
        if (!elStyle.height) {
47
          elStyle.height = `${el.offsetHeight}px`
48
        }
49
50
        elStyle.position = 'fixed'
51
        elStyle.width = `${elWidth}px`
52
        placeholder.style.display = 'inline-block'
53
        active = true
54
      }
55
56
      const reset = () => {
57
        if (!active) {
58
          return
59
        }
60
61
        elStyle.position = ''
62
        placeholder.style.display = 'none'
63
        active = false
64
      }
65
66
      const check = () => {
67
        const scrollTop = getScroll(window, true)
68
        const offsetTop = el.getBoundingClientRect().top
69
        if (offsetTop < stickyTop) {
70
          sticky()
71
        } else {
72
          if (scrollTop < elHeight + stickyTop) {
73
            reset()
74
          }
75
        }
76
      }
77
      listenAction = () => {
78
        check()
79
      }
80
81
      window.addEventListener('scroll', listenAction)
82
    },
83
84
    unbind() {
85
      window.removeEventListener('scroll', listenAction)
86
    }
87
  })
88
}
89
90
export default vueSticky
91

+ 13 - 0
src/directive/waves/index.js

@ -0,0 +1,13 @@
1
import waves from './waves'
2
3
const install = function(Vue) {
4
  Vue.directive('waves', waves)
5
}
6
7
if (window.Vue) {
8
  window.waves = waves
9
  Vue.use(install); // eslint-disable-line
10
}
11
12
waves.install = install
13
export default waves

+ 26 - 0
src/directive/waves/waves.css

@ -0,0 +1,26 @@
1
.waves-ripple {
2
    position: absolute;
3
    border-radius: 100%;
4
    background-color: rgba(0, 0, 0, 0.15);
5
    background-clip: padding-box;
6
    pointer-events: none;
7
    -webkit-user-select: none;
8
    -moz-user-select: none;
9
    -ms-user-select: none;
10
    user-select: none;
11
    -webkit-transform: scale(0);
12
    -ms-transform: scale(0);
13
    transform: scale(0);
14
    opacity: 1;
15
}
16
17
.waves-ripple.z-active {
18
    opacity: 0;
19
    -webkit-transform: scale(2);
20
    -ms-transform: scale(2);
21
    transform: scale(2);
22
    -webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
23
    transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
24
    transition: opacity 1.2s ease-out, transform 0.6s ease-out;
25
    transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out;
26
}

+ 42 - 0
src/directive/waves/waves.js

@ -0,0 +1,42 @@
1
import './waves.css'
2
3
export default{
4
  bind(el, binding) {
5
    el.addEventListener('click', e => {
6
      const customOpts = Object.assign({}, binding.value)
7
      const opts = Object.assign({
8
        ele: el, // 波纹作用元素
9
        type: 'hit', // hit点击位置扩散center中心点扩展
10
        color: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
11
      }, customOpts)
12
      const target = opts.ele
13
      if (target) {
14
        target.style.position = 'relative'
15
        target.style.overflow = 'hidden'
16
        const rect = target.getBoundingClientRect()
17
        let ripple = target.querySelector('.waves-ripple')
18
        if (!ripple) {
19
          ripple = document.createElement('span')
20
          ripple.className = 'waves-ripple'
21
          ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
22
          target.appendChild(ripple)
23
        } else {
24
          ripple.className = 'waves-ripple'
25
        }
26
        switch (opts.type) {
27
          case 'center':
28
            ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px'
29
            ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px'
30
            break
31
          default:
32
            ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px'
33
            ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px'
34
        }
35
        ripple.style.backgroundColor = opts.color
36
        ripple.className = 'waves-ripple z-active'
37
        return false
38
      }
39
    }, false)
40
  }
41
}
42

+ 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>

+ 27 - 0
src/main.js

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

+ 63 - 0
src/permission.js

@ -0,0 +1,63 @@
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
      console.log(222)
24
      next({ path: '/' })
25
      NProgress.done()
26
    } else {
27
      if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息
28
        console.log(3333)
29
        store.dispatch('GetUserInfo').then(res => { // 拉取user_info
30
          const roles = [res.data.type.toString()]
31
          console.log(roles)
32
          store.dispatch('GenerateRoutes', { roles }).then(() => { // 根据roles权限生成可访问的路由表
33
            router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
34
            next({ ...to, replace: true })
35
          })
36
        }).catch((err) => {
37
          store.dispatch('FedLogOut').then(() => {
38
            Message.error(err || '登录状态失效,请重新登录')
39
            next({ path: '/' })
40
          })
41
        })
42
      } else {
43
        console.log(store.getters.roles)
44
        console.log(to.meta.roles)
45
        if (hasPermission(store.getters.roles, to.meta.roles)) {
46
          next()
47
        }
48
      }
49
      queryInfo.queryAllInfo()
50
    }
51
  } else {
52
    if (whiteList.indexOf(to.path) !== -1) {
53
      next()
54
    } else {
55
      next('/login')
56
      NProgress.done()
57
    }
58
  }
59
})
60
61
router.afterEach(() => {
62
  NProgress.done() // 结束Progress
63
})

+ 197 - 0
src/router/index.js

@ -0,0 +1,197 @@
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
import common from '../views/layout/common'
9
10
/**
11
* hidden: true                   if `hidden:true` will not show in the sidebar(default is false)
12
* alwaysShow: true               if set true, will always show the root menu, whatever its child routes length
13
*                                if not set alwaysShow, only more than one route under the children
14
*                                it will becomes nested mode, otherwise not show the root menu
15
* redirect: noredirect           if `redirect:noredirect` will no redirct in the breadcrumb
16
* name:'router-name'             the name is used by <keep-alive> (must set!!!)
17
* meta : {
18
    roles: ['admin','editor']     will control the page roles (you can set multiple roles)
19
    title: 'title'               the name show in submenu and breadcrumb (recommend set)
20
    icon: 'svg-name'             the icon show in the sidebar,
21
    noCache: true                if true ,the page will no be cached(default is false)
22
  }
23
**/
24
25
// 所有权限通用路由表
26
// 如首页和登录页和一些不用权限的公用页面
27
28
export const constantRouterMap = [
29
  { path: '/login', component: () => import('@/views/login/index'), hidden: true },
30
  { path: '/findPwd', component: () => import('@/views/findPwd/index'), hidden: true },
31
  { path: '/404', component: () => import('@/views/404'), hidden: true },
32
  {
33
    path: '/',
34
    component: Layout,
35
    redirect: '/dashboard',
36
    hidden: true,
37
    children: [{
38
      path: 'dashboard',
39
      component: () => import('@/views/dashboard'),
40
      name: 'dashboard',
41
      meta: { title: '主页' }
42
    }]
43
  }
44
]
45
46
// 实例化vue的时候只挂载constantRouter
47
48
export default new Router({
49
  // mode: 'history', //后端支持可开
50
  scrollBehavior: () => ({ y: 0 }),
51
  routes: constantRouterMap
52
})
53
54
// 异步挂载的路由
55
// 动态需要根据权限加载的路由表
56
57
export const asyncRouterMap = [
58
  {
59
    path: '/show',
60
    component: common,
61
    redirect: '/show/home',
62
    meta: { roles: ['0', '1'] },
63
    hidden: true,
64
    children: [{
65
      path: 'home',
66
      component: () => import('@/views/home/index.vue'),
67
      name: 'home',
68
      meta: { title: '首页', roles: ['0', '1'] }
69
    },
70
    {
71
      path: 'medicalTreatment',
72
      component: () => import('@/views/medicalTreatment/index.vue'),
73
      name: 'medicalTreatment',
74
      meta: { title: '协同诊疗', roles: ['0', '1'] }
75
    },
76
    {
77
      path: 'intelligentJudgment',
78
      component: () => import('@/views/intelligentJudgment/index.vue'),
79
      name: 'intelligentJudgment',
80
      meta: { title: 'AI智能判断', roles: ['0', '1'] }
81
    },
82
    {
83
      path: 'sharedDevice',
84
      component: () => import('@/views/sharedDevice/index.vue'),
85
      name: 'sharedDevice',
86
      meta: { title: '共享器械', roles: ['0', '1'] }
87
    },
88
    {
89
      path: 'hospital',
90
      component: () => import('@/views/hospital/index.vue'),
91
      name: 'hospital',
92
      meta: { title: '医院', roles: ['0', '1'] }
93
    }]
94
  },
95
  {
96
    path: '',
97
    component: Layout,
98
    name: 'peoplesManage',
99
    meta: {
100
      title: '个人设置',
101
      icon: 'peoples',
102
      roles: ['0', '1']
103
    },
104
    alwaysShow: true,
105
    children: [
106
      {
107
        path: 'infoManage',
108
        name: 'infoManage',
109
        component: () => import('@/views/peoplesManage/infoManage/index'),
110
        meta: { title: '个人信息修改', roles: ['0', '1'] }
111
      },
112
      {
113
        path: 'accountSettings',
114
        name: 'accountSettings',
115
        component: () => import('@/views/peoplesManage/accountSettings/index'),
116
        meta: { title: '账户设置', roles: ['0', '1'] }
117
      }
118
    ]
119
  },
120
  {
121
    path: '',
122
    component: Layout,
123
    name: 'BridgesInfo',
124
    meta: {
125
      title: '',
126
      roles: ['1', '2']
127
    },
128
    alwaysShow: false,
129
    children: [
130
      {
131
        path: 'BridgesInfo',
132
        name: 'BridgesInfo',
133
        component: () => import('@/views/baseInfoManage/bridgesInfo/index'),
134
        meta: { title: '医院信息', icon: 'hospital' }
135
      }
136
    ]
137
  },
138
  {
139
    path: '',
140
    component: Layout,
141
    name: 'serversConfig',
142
    meta: {
143
      title: '',
144
      icon: 'list',
145
      roles: ['1', '2']
146
    },
147
    alwaysShow: false,
148
    children: [
149
      {
150
        path: 'serversConfig',
151
        name: 'serversConfig',
152
        component: () => import('@/views/baseInfoManage/serversConfig/index'),
153
        meta: { title: '科室信息', icon: 'Department' }
154
      }
155
    ]
156
  },
157
  {
158
    path: '',
159
    component: Layout,
160
    name: 'boxesConfig',
161
    meta: {
162
      title: '',
163
      icon: 'list',
164
      roles: ['1', '2']
165
    },
166
    alwaysShow: false,
167
    children: [
168
      {
169
        path: 'boxesConfig',
170
        name: 'boxesConfig',
171
        component: () => import('@/views/baseInfoManage/boxesConfig/index'),
172
        meta: { title: '医生信息', icon: 'doctor' }
173
      }
174
    ]
175
  },
176
  {
177
    path: '',
178
    component: Layout,
179
    name: 'sensorsConfig',
180
    meta: {
181
      title: '',
182
      icon: 'list',
183
      roles: ['1', '2']
184
    },
185
    alwaysShow: false,
186
    children: [
187
      {
188
        path: 'sensorsConfig',
189
        name: 'sensorsConfig',
190
        component: () => import('@/views/baseInfoManage/sensorsConfig/index'),
191
        meta: { title: '器械信息', icon: 'instrument' }
192
      }
193
    ]
194
  },
195
  { path: '*', redirect: '/404', hidden: true, meta: { roles: ['0', '1', '2'] }
196
  }
197
]

+ 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

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

@ -0,0 +1,60 @@
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
      console.log(state.routers)
44
    }
45
  },
46
  actions: {
47
    GenerateRoutes({ commit }, data) {
48
      return new Promise(resolve => {
49
        //  const { roles } = data
50
        const roles = ['2']
51
        const accessedRouters = filterAsyncRouter(asyncRouterMap, roles)
52
        console.log(accessedRouters)
53
        commit('SET_ROUTERS', accessedRouters)
54
        resolve()
55
      })
56
    }
57
  }
58
}
59
60
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
}

+ 91 - 0
src/styles/index.scss

@ -0,0 +1,91 @@
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
}
80
81
.logo-wrapper {
82
  display:block;
83
  width: 100%;
84
  .logo-img{
85
    display:block;
86
    height:28px;
87
    width:300px;
88
    background-image: url('/static/touchwave.png');
89
    background-size: 300px 28px;
90
  }
91
}

+ 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
}

+ 27 - 0
src/styles/mixin.scss

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

+ 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
}

+ 118 - 0
src/styles/sidebar.scss

@ -0,0 +1,118 @@
1
#app {
2
  // 主体区域
3
  .main-container {
4
    min-height: 100%;
5
    padding-top:50px;
6
    transition: margin-left .28s;
7
    margin-left: 140px;
8
    position: relative;
9
    background-color: rgb(240, 242, 245);
10
  }
11
  // 侧边栏
12
  .sidebar-container {
13
    transition: width 0.28s;
14
    width: 140px !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 {
42
      border: none;
43
      height: 100%;
44
      width: 100% !important;
45
    }
46
  }
47
  .hideSidebar {
48
    .sidebar-container {
49
      width: 36px !important;
50
    }
51
    .main-container {
52
      margin-left: 36px;
53
    }
54
    .submenu-title-noDropdown {
55
      padding-left: 10px !important;
56
      position: relative;
57
      .el-tooltip {
58
        padding: 0 10px !important;
59
      }
60
    }
61
    .el-submenu {
62
      overflow: hidden;
63
      &>.el-submenu__title {
64
        padding-left: 10px !important;
65
        .el-submenu__icon-arrow {
66
          display: none;
67
        }
68
      }
69
    }
70
    .el-menu--collapse {
71
      .el-submenu {
72
        &>.el-submenu__title {
73
          &>span {
74
            height: 0;
75
            width: 0;
76
            overflow: hidden;
77
            visibility: hidden;
78
            display: inline-block;
79
          }
80
        }
81
      }
82
    }
83
  }
84
  .sidebar-container .nest-menu .el-submenu>.el-submenu__title,
85
  .sidebar-container .el-submenu .el-menu-item {
86
    min-width: 180px !important;
87
    background-color: $subMenuBg !important;
88
    &:hover {
89
      background-color: $menuHover !important;
90
    }
91
  }
92
  .el-menu--collapse .el-menu .el-submenu {
93
    min-width: 180px !important;
94
  }
95
96
  //适配移动端
97
  .mobile {
98
    .main-container {
99
      margin-left: 0px;
100
    }
101
    .sidebar-container {
102
      transition: transform .28s;
103
      width: 180px !important;
104
    }
105
    &.hideSidebar {
106
      .sidebar-container {
107
        transition-duration: 0.3s;
108
        transform: translate3d(-180px, 0, 0);
109
      }
110
    }
111
  }
112
  .withoutAnimation {
113
    .main-container,
114
    .sidebar-container {
115
      transition: none;
116
    }
117
  }
118
}

+ 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:#304156;
3
$subMenuBg:#1f2d3d;
4
$menuHover:#001528;

+ 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 = 'http://localhost:90'
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

+ 54 - 0
src/utils/request.js

@ -0,0 +1,54 @@
1
import axios from 'axios'
2
import qs from 'qs'
3
import { comUrl } from '@/utils/index'
4
5
// 创建axios实例
6
const service = axios.create({
7
  baseURL: comUrl, // api的base_url
8
  // timeout: 5000, // 请求超时时间
9
  paramsSerializer: function(params) {
10
    return qs.stringify(params, { arrayFormat: 'repeat' })
11
  }
12
})
13
14
// request拦截器
15
service.interceptors.request.use(config => {
16
  // 配置config
17
  config.headers.Accept = 'application/json'
18
  if (config.method === 'post') {
19
    config.data = qs.stringify(config.data, { arrayFormat: 'repeat' })
20
    // 处理后后台无需添加RequestBody
21
    config.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
22
  }
23
  if (localStorage.token) {
24
    config.headers.Authorization = localStorage.token
25
  }
26
  return config
27
}, error => {
28
  Promise.reject(error)
29
})
30
31
// respone拦截器
32
service.interceptors.response.use(response => {
33
  let data = response.data
34
  const status = response.status
35
  if (status === 200) {
36
    if (response.data === undefined) {
37
      // 解决IE9数据问题
38
      data = response.request.responseText
39
    } else {
40
      data = response.data
41
    }
42
    if (!(data instanceof Object)) {
43
      // 判断data不是Object时,解析成Object
44
      // data = JSON.parse(data)
45
    }
46
    return response.data
47
  } else {
48
    return Promise.resolve(response)
49
  }
50
}, error => {
51
  return Promise.reject(error)
52
})
53
54
export default service

+ 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>

+ 397 - 0
src/views/baseInfoManage/boxesConfig/index.vue

@ -0,0 +1,397 @@
1
<template>
2
  <div class="app-container">
3
    <div class="filter-container" style="margin-bottom:20px">
4
      <el-input style="width: 200px;" class="filter-item" placeholder="采集盒编号" v-model="listQuery.code">
5
      </el-input>
6
      <el-input style="width: 200px;" class="filter-item" placeholder="所属服务器编号" v-model="listQuery.scode">
7
      </el-input>
8
      <el-button v-waves class="filter-item" style="margin-left: 10px;" @click="handleFilter" type="primary" icon="el-icon-search">查找</el-button>
9
      <el-button v-waves class="filter-item" style="margin-left: 10px;" @click="handleCreate" type="primary" icon="el-icon-edit">添加采集盒</el-button>
10
    </div>
11
12
    <el-table :key='tableKey' :data="list" v-loading="listLoading" border fit highlight-current-row
13
      style="width: 100%;min-height:550px;">
14
      <el-table-column width="150px" align="center" label="采集盒编号" prop="code"></el-table-column>
15
      <el-table-column width="150px" align="center" label="内部编号" prop="seq"></el-table-column>
16
      <el-table-column width="150px" align="center" label="采集盒信道数量" prop="channels"></el-table-column>
17
      <el-table-column min-width="150px" align="center" label="所属服务器编号" prop="serverName"></el-table-column>
18
      <el-table-column min-width="200px" align="center" label="备注信息" prop="remark"></el-table-column>
19
      <el-table-column align="center" label="操作" width="230" class-name="small-padding fixed-width">
20
        <template slot-scope="scope"> 
21
          <el-button v-waves v-waves type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button> 
22
          <el-button v-waves size="mini" type="danger" @click="handleModifyStatus(scope.row,'deleted')">删除
23
          </el-button>
24
        </template>
25
      </el-table-column>
26
    </el-table>
27
    <el-dialog title="采集盒配置" ref="ruleForm" :visible.sync="dialogTableVisible" width="860px" @close='closed'>
28
      <el-form :model="ruleForm2" :rules="rules2" ref="ruleForm2" class="form-main" label-position='right' status-icon>
29
        <el-row>
30
          <el-col :span="12">
31
            <el-form-item label="采集盒编号"  prop="code">
32
              <el-input placeholder="请输入采集盒编号" v-model="ruleForm2.code" maxlength=20></el-input>
33
            </el-form-item>
34
          </el-col>
35
          <el-col :span="12">
36
            <el-form-item label="采集盒信道数量" prop="channels">
37
              <el-input placeholder="请输入采集盒信道数量" v-model="ruleForm2.channels" maxlength=10></el-input>
38
            </el-form-item>
39
          </el-col>
40
           <el-col :span="12">
41
            <el-form-item label="所属服务器编号" prop="server">
42
              <el-autocomplete
43
                v-model="ruleForm2.server"
44
                :fetch-suggestions="querySearchAsync"
45
                placeholder="请选择所属服务器编号"
46
                @select="handleSelect">
47
              </el-autocomplete>
48
            </el-form-item>
49
          </el-col>
50
          <el-col :span="12">
51
            <el-form-item label="内部编号" prop="seq">
52
              <el-input placeholder="请输入内部编号" v-model="ruleForm2.seq" maxlength=10></el-input>
53
            </el-form-item>
54
          </el-col>
55
           <el-col :span="24" >
56
            <el-form-item label="备注" prop="remark">
57
              <el-input type="textarea" maxlength=500 v-model="ruleForm2.remark" rows=4></el-input>
58
             </el-form-item>
59
          </el-col>
60
          <el-col :span="24" class="el-btn-col">
61
            <div class="el-btn-col-box">
62
              <el-button v-waves type="primary" @click="submitForm('ruleForm2')">确认</el-button>
63
              <el-button v-waves type="info" @click="resetForm('ruleForm2')">返回</el-button>
64
            </div>
65
          </el-col>
66
        </el-row>
67
      </el-form>
68
    </el-dialog>
69
    <div class="pagination-container" style="text-align:center;">
70
      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.pageNo" :page-size="listQuery.pageSize" layout="prev, pager, next, jumper" :total="total">
71
      </el-pagination>
72
    </div>
73
  </div>
74
</template>
75
76
<script>
77
import { addDevice, updateDevice, deleteDevice, pageQueryDevice, DeviceOfservice, checkDeviceCode, checkDeviceInternalCode } from '@/api/collectionbox'
78
import waves from '@/directive/waves'
79
import queryBase from '@/utils/queryBase'
80
export default {
81
  name: 'complexTable',
82
  directives: {
83
    waves
84
  },
85
  data() {
86
    var server = (rule, value, callback) => {
87
      const that = this
88
      setTimeout(function() {
89
        if (that.ruleForm2.server === '' || that.ruleForm2.serverId === '') {
90
          callback(new Error('请选择服务器编号'))
91
        } else {
92
          callback()
93
        }
94
      }, 300)
95
    }
96
    var seq = (rule, value, callback) => {
97
      const num = /^[0-9]*$/
98
      if (value === '') {
99
        callback(new Error('请输入内部编号'))
100
      } else {
101
        if (!this.ruleForm2.serverId) {
102
          callback('请先选择所属服务器编号')
103
          return
104
        }
105
        if (!num.test(value)) {
106
          callback('请输入数字')
107
          return
108
        }
109
        if (this.edit) {
110
          checkDeviceInternalCode({ seq: value, id: this.edit, serverId: this.ruleForm2.serverId, active: 1 }).then(response => {
111
            if (response.data) {
112
              callback(new Error('内部编号已存在,请重新输入'))
113
            } else {
114
              callback()
115
            }
116
          })
117
        } else {
118
          checkDeviceInternalCode({ seq: value, serverId: this.ruleForm2.serverId, active: 1 }).then(response => {
119
            if (response.data) {
120
              callback(new Error('内部编号已存在,请重新输入'))
121
            } else {
122
              callback()
123
            }
124
          })
125
        }
126
      }
127
    }
128
    var code = (rule, value, callback) => {
129
      if (value === '') {
130
        callback(new Error('请输入采集盒编号'))
131
      } else {
132
        if (this.edit) {
133
          checkDeviceCode({ code: value, id: this.edit, active: 1 }).then(response => {
134
            if (response.data) {
135
              callback(new Error('采集盒编号已存在,请重新输入'))
136
            } else {
137
              callback()
138
            }
139
          })
140
        } else {
141
          checkDeviceCode({ code: value, active: 1 }).then(response => {
142
            if (response.data) {
143
              callback(new Error('采集盒编号已存在,请重新输入'))
144
            } else {
145
              callback()
146
            }
147
          })
148
        }
149
      }
150
    }
151
    return {
152
      edit: '',
153
      ruleForm2: {
154
        code: '',
155
        channels: '',
156
        server: '',
157
        seq: '',
158
        serverId: '',
159
        remark: ''
160
      },
161
      rules2: {
162
        code: [
163
          { required: true, validator: code, trigger: 'blur' }
164
        ],
165
        channels: [
166
          { required: true, message: '请输入采集盒数量', trigger: 'blur' }
167
        ],
168
        server: [
169
          { required: true, validator: server, trigger: 'blur' }
170
        ],
171
        seq: [
172
          { required: true, validator: seq, trigger: 'blur' }
173
        ]
174
      },
175
      timeout: null,
176
      dialogTableVisible: false,
177
      tableKey: 0,
178
      list: null,
179
      total: null,
180
      listLoading: true,
181
      listQuery: {
182
        scode: '',
183
        code: '',
184
        active: 1,
185
        pageSize: 10,
186
        pageNo: 1
187
      }
188
    }
189
  },
190
  filters: {
191
    typeFilter(type) {
192
193
    }
194
  },
195
  created() {
196
    this.getList()
197
  },
198
  methods: {
199
    submitForm(formName) {
200
      const that = this
201
      this.$refs[formName].validate((valid) => {
202
        if (valid) {
203
          if (!this.edit) {
204
            addDevice(this.ruleForm2).then(response => {
205
              if (response.success) {
206
                this.getList()
207
                setTimeout(function() {
208
                  that.pop('已成功添加采集盒')
209
                }, 1000)
210
                this.resetForm('ruleForm2')
211
                this.dialogTableVisible = false
212
              }
213
            }).catch(error => {
214
              console.log(error)
215
            })
216
          } else {
217
            const par = this.ruleForm2
218
            par.id = this.edit
219
            updateDevice(par).then(response => {
220
              if (response.success) {
221
                setTimeout(function() {
222
                  that.pop('已成功更新采集盒')
223
                }, 1000)
224
                this.resetForm('ruleForm2')
225
                this.getList()
226
                this.dialogTableVisible = false
227
                this.edit = ''
228
                this.ruleForm2 = {
229
                  code: '',
230
                  channels: '',
231
                  server: '',
232
                  seq: '',
233
                  serverId: '',
234
                  remark: ''
235
                }
236
              }
237
            })
238
          }
239
        }
240
      })
241
    },
242
    resetForm(formName) {
243
      this.dialogTableVisible = false
244
      this.$refs[formName].resetFields()
245
      this.edit = ''
246
    },
247
    closed() {
248
      this.$refs['ruleForm2'].resetFields()
249
      this.edit = ''
250
    },
251
    getList() {
252
      var that = this
253
      this.listLoading = true
254
      pageQueryDevice(this.listQuery).then(response => {
255
        if (response.success) {
256
          const $data = response.data.data
257
          var hdata = { num: 1, data: $data }
258
          for (let i = 0; i < $data.length; i++) {
259
            hdata.num++
260
            const str = $data[i]
261
            queryBase.getServer(str.serverId, function(sc, value) {
262
              if (sc) {
263
                str.serverName = value.code
264
                hdata.num--
265
                if (hdata.num === 0) {
266
                  that.list = hdata.data
267
                }
268
              }
269
            })
270
          }
271
          hdata.num--
272
          if (hdata.num === 0) {
273
            that.list = hdata.data
274
          }
275
          that.total = response.data.total
276
          setTimeout(() => {
277
            that.listLoading = false
278
          }, 1.5 * 1000)
279
        }
280
      })
281
    },
282
    handleFilter() {
283
      this.listQuery.pageNo = 1
284
      this.getList()
285
    },
286
    handleSizeChange(val) {
287
      this.listQuery.pageSize = val
288
      this.getList()
289
    },
290
    handleCurrentChange(val) {
291
      this.listQuery.pageNo = val
292
      this.getList()
293
    },
294
    handleModifyStatus(row, status) {
295
      this.$confirm('确定要删除:采集盒' + row.code + '吗?', '提示', {
296
        confirmButtonText: '确定',
297
        cancelButtonText: '取消',
298
        type: 'warning',
299
        center: true
300
      }).then(() => {
301
        deleteDevice({ id: row.id }).then(response => {
302
          if (response.success) {
303
            this.getList()
304
            this.pop('已成功删除该采集盒')
305
            /*  this.$message({
306
              type: 'success',
307
              message: '已成功删除该采集盒!'
308
            })  */
309
          }
310
        })
311
      }).catch(() => {
312
313
      })
314
    },
315
    pop($par) {
316
      this.$confirm($par, '提示', {
317
        confirmButtonText: '确定',
318
        cancelButtonText: '取消',
319
        type: 'success',
320
        showCancelButton: false,
321
        center: true
322
      }).then(() => {
323
324
      }).catch(() => {
325
326
      })
327
    },
328
    resetTemp(row) {
329
      this.ruleForm2 = {
330
        code: row.code,
331
        channels: row.channels,
332
        server: row.serverName,
333
        seq: row.seq,
334
        serverId: row.serverId,
335
        remark: row.remark
336
      }
337
      this.edit = row.id
338
    },
339
    handleCreate() {
340
      this.dialogTableVisible = true
341
    },
342
    handleUpdate(row) {
343
      const that = this
344
      setTimeout(function() {
345
        that.resetTemp(row)
346
      }, 500)
347
      this.dialogTableVisible = true
348
    },
349
    querySearchAsync(queryString, cb) {
350
      this.ruleForm2.serverId = ''
351
      clearTimeout(this.timeout)
352
      this.timeout = setTimeout(() => {
353
        DeviceOfservice({ code: this.ruleForm2.server, active: 1 }).then(response => {
354
          const $info = response.data
355
          if ($info.length) {
356
            const $data = $info.map(item => {
357
              return { 'value': item.code, 'id': item.id }
358
            })
359
            cb($data)
360
            if ($info.length === 1 && this.ruleForm2.server === $info[0].code) {
361
              this.ruleForm2.serverId = $info[0].id
362
            } else {
363
              this.ruleForm2.serverId = ''
364
            }
365
          } else {
366
            cb([])
367
          }
368
        })
369
      }, 3000 * Math.random())
370
    },
371
    handleSelect(item) {
372
      this.ruleForm2.serverId = item.id
373
    }
374
  }
375
}
376
</script>
377
378
<style rel="stylesheet/scss" lang="scss" scoped>
379
  .el-autocomplete{
380
    display: block
381
  }
382
  .el-btn-col{
383
    margin-top: 45px
384
  }
385
  .el-form-item{
386
    margin: 0px 10px
387
  }
388
  .el-select{
389
    width: 100%
390
  }
391
  .el-col{
392
    margin-bottom: 15px
393
  }
394
  .el-form-item__label{
395
    padding: 0px
396
  }
397
</style>

+ 525 - 0
src/views/baseInfoManage/bridgesInfo/index.vue

@ -0,0 +1,525 @@
1
<template>
2
  <div class="app-container">
3
    <div class="filter-container" style="margin-bottom:20px">
4
      <el-input style="width: 200px;" class="filter-item" placeholder="桥梁编号" v-model="listQuery.code">
5
      </el-input>
6
      <el-input style="width: 200px;" class="filter-item" placeholder="桥梁简称" v-model="listQuery.name">
7
      </el-input>
8
      <el-button v-waves class="filter-item" style="margin-left: 10px;" @click="handleFilter" type="primary" icon="el-icon-search">查找</el-button>
9
      <el-button v-waves class="filter-item" style="margin-left: 10px;" @click="handleCreate" type="primary" icon="el-icon-edit">添加桥梁</el-button>
10
    </div>
11
12
    <el-table :key='tableKey' :data="list" v-loading="listLoading" border fit highlight-current-row
13
      style="width: 100%;min-height:550px;">
14
      <el-table-column width="150px" align="center" label="桥梁编号">
15
        <template slot-scope="scope">
16
          <span>{{scope.row.code}}</span>
17
        </template>
18
      </el-table-column>
19
      <el-table-column width="150px" align="center" label="桥梁简称">
20
        <template slot-scope="scope">
21
          <span>{{scope.row.shortName}}</span>
22
        </template>
23
      </el-table-column>
24
      <el-table-column min-width="150px" align="center" label="桥梁位置">
25
        <template slot-scope="scope">
26
          <span>{{citys[scope.row.addrCode]}}</span>
27
        </template>
28
      </el-table-column>
29
      <el-table-column min-width="150px" align="center" label="维护机构">
30
        <template slot-scope="scope">
31
          <span>{{scope.row.org}}</span>
32
        </template>
33
      </el-table-column>
34
      <el-table-column min-width="200px" align="center" label="备注信息">
35
        <template slot-scope="scope">
36
          <span>{{scope.row.remark}}</span>
37
        </template>
38
      </el-table-column>
39
      <el-table-column align="center" label="操作" width="230" class-name="small-padding fixed-width">
40
        <template slot-scope="scope"> 
41
          <el-button v-waves type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button> 
42
          <el-button v-waves size="mini" type="danger" @click="handleModifyStatus(scope.row,'deleted')">删除
43
          </el-button>
44
        </template>
45
      </el-table-column>
46
    </el-table>
47
    <el-dialog title="桥梁信息" ref="ruleForm" :visible.sync="dialogTableVisible" width="860px" @close='closed'>
48
      <el-form :model="ruleForm2" :rules="rules2" ref="ruleForm2" class="form-main"  label-position='top' status-icon>
49
        <el-row :gutter="10">
50
          <el-col :xs="16" :sm="16" :lg="16">
51
            <el-row>
52
              <el-col :span="12">
53
                <el-form-item label="桥梁编号" prop="code">
54
                  <el-input placeholder="请输入桥梁编号" v-model="ruleForm2.code" maxlength=20></el-input>
55
                </el-form-item>
56
              </el-col>
57
              <el-col :span="12">
58
                <el-form-item label="桥梁简称" prop="shortName">
59
                  <el-input placeholder="请输入桥梁简称" v-model="ruleForm2.shortName" maxlength=20></el-input>
60
                </el-form-item>
61
              </el-col>
62
              <el-col :span="24">
63
                <el-form-item label="桥梁全称" prop="name">
64
                  <el-input placeholder="请输入桥梁全称" v-model="ruleForm2.name" maxlength=200></el-input>
65
                </el-form-item>
66
              </el-col>
67
              <el-col :span="24">
68
                <el-form-item label="桥梁位置信息" prop="addrCode">
69
                  <!-- <city @paren="toshow" :addrCode='ruleForm2.addrCode'></city> -->
70
                  <CityPicker @paren="toshow" :addrCode='ruleForm2.addrCode'></CityPicker>
71
                </el-form-item>
72
              </el-col>
73
              <el-col :span="12">
74
                <el-form-item label="地理位置信息" prop="location">
75
                  <el-input placeholder="请输入地理位置信息" v-model="ruleForm2.location" maxlength=200></el-input>
76
                </el-form-item>
77
              </el-col>
78
              <el-col :span="12">
79
                <el-form-item label="桥梁开通日期" prop="serviceDay">
80
                  <el-date-picker
81
                    value-format='yyyyMMdd'
82
                    v-model="ruleForm2.serviceDay"
83
                    type="date"
84
                    placeholder="选择日期">
85
                  </el-date-picker>
86
                </el-form-item>
87
              </el-col>
88
              <el-col :span="24">
89
                <el-form-item label="维护机构" prop="org">
90
                  <el-input placeholder="请输入维护机构" v-model="ruleForm2.org" maxlength=200></el-input>
91
                </el-form-item>
92
              </el-col>
93
              <el-col :span="12">
94
                <el-form-item label="联系电话" prop="phone">
95
                  <el-input placeholder="请输入联系电话" v-model="ruleForm2.phone" maxlength=20></el-input>
96
                </el-form-item>
97
              </el-col>
98
              <el-col :span="12">
99
                <el-form-item label="联系电邮" prop="email">
100
                  <el-input placeholder="请输入联系电邮" v-model="ruleForm2.email" maxlength=100></el-input>
101
                </el-form-item>
102
              </el-col>
103
            </el-row>
104
          </el-col>
105
          <el-col :xs="8" :sm="8" :lg="8">
106
              <el-upload
107
                class="avatar-uploader"
108
                action="/ajax/bridge/upload"
109
                accept='image'
110
                :show-file-list="false"
111
                :on-success="handleAvatarSuccess"
112
                :before-upload="beforeAvatarUpload">
113
                <img v-if="imageUrl" :src="imageUrl" class="avatar">
114
                <i v-else class="el-icon-plus avatar-uploader-icon"></i>
115
              </el-upload>
116
            <p style="width:100%;text-align:center;font-size:14px;color:#999;">上传桥梁图片<br>
117
                JPEG/JPG/PNG格式大小5M以内</p>
118
          </el-col>
119
        </el-row>
120
        <el-row>
121
          <el-col :span="24">
122
            <el-form-item label="详细描述" class="el-to-block" prop="descp">
123
              <el-input type="textarea" maxlength=500  rows=6 v-model="ruleForm2.descp"></el-input>
124
            </el-form-item>
125
          </el-col>
126
          <el-col :span="24">
127
            <el-form-item label="备注" class="el-to-block" prop="remark">
128
              <el-input type="textarea" maxlength=500 rows=3 v-model="ruleForm2.remark"></el-input>
129
            </el-form-item>
130
          </el-col>
131
          <el-col :span="24" class="el-btn-col">
132
            <div class="el-btn-col-box">
133
              <el-button v-waves type="primary" @click="submitForm('ruleForm2')">确认</el-button>
134
              <el-button v-waves type="primary" @click="resetForm('ruleForm2')">返回</el-button>
135
            </div>
136
          </el-col>
137
        </el-row>
138
      </el-form>
139
    </el-dialog>
140
    <div class="pagination-container" style="text-align:center;">
141
      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.pageNo" :page-size="listQuery.pageSize" layout="prev, pager, next, jumper" :total="total">
142
      </el-pagination>
143
    </div>
144
  </div>
145
</template>
146
147
<script>
148
import { addDevice, updateDevice, deleteDevice, pageQueryDevice, checkDeviceCode, checkBridgeShortName, checkBridgeName } from '@/api/bridge'
149
import waves from '@/directive/waves'
150
import CityPicker from '@/components/CityPicker'
151
import queryDict from '@/utils/queryDict'
152
export default {
153
  name: 'complexTable',
154
  directives: {
155
    waves
156
  },
157
  data() {
158
    var code = (rule, value, callback) => {
159
      if (value === '') {
160
        callback(new Error('请输入桥梁编号'))
161
      } else {
162
        if (this.edit) {
163
          checkDeviceCode({ code: value, id: this.edit, active: 1 }).then(response => {
164
            if (response.data) {
165
              callback(new Error('桥梁编号已存在,请重新输入'))
166
            } else {
167
              callback()
168
            }
169
          })
170
        } else {
171
          checkDeviceCode({ code: value, active: 1 }).then(response => {
172
            if (response.data) {
173
              callback(new Error('桥梁编号已存在,请重新输入'))
174
            } else {
175
              callback()
176
            }
177
          })
178
        }
179
      }
180
    }
181
    var shortName = (rule, value, callback) => {
182
      if (value === '') {
183
        callback(new Error('请输入桥梁简称'))
184
      } else {
185
        if (this.edit) {
186
          checkBridgeShortName({ shortName: value, id: this.edit, active: 1 }).then(response => {
187
            if (response.data) {
188
              callback(new Error('桥梁简称已存在,请重新输入'))
189
            } else {
190
              callback()
191
            }
192
          })
193
        } else {
194
          checkBridgeShortName({ shortName: value, active: 1 }).then(response => {
195
            if (response.data) {
196
              callback(new Error('桥梁简称已存在,请重新输入'))
197
            } else {
198
              callback()
199
            }
200
          })
201
        }
202
      }
203
    }
204
    var name = (rule, value, callback) => {
205
      if (value === '') {
206
        callback(new Error('请输入桥梁全称'))
207
      } else {
208
        if (this.edit) {
209
          checkBridgeName({ name: value, id: this.edit, active: 1 }).then(response => {
210
            if (response.data) {
211
              callback(new Error('桥梁全称已存在,请重新输入'))
212
            } else {
213
              callback()
214
            }
215
          })
216
        } else {
217
          checkBridgeName({ name: value, active: 1 }).then(response => {
218
            if (response.data) {
219
              callback(new Error('桥梁全称已存在,请重新输入'))
220
            } else {
221
              callback()
222
            }
223
          })
224
        }
225
      }
226
    }
227
    return {
228
      citys: {},
229
      edit: '',
230
      imageUrl: '',
231
      ruleForm2: {
232
        code: '',
233
        shortName: '',
234
        name: '',
235
        addrCode: '',
236
        serviceDay: '',
237
        location: '',
238
        descp: '',
239
        remark: '',
240
        img: '',
241
        org: '',
242
        phone: '',
243
        email: ''
244
      },
245
      rules2: {
246
        code: [
247
          { required: true, validator: code, trigger: 'blur' }
248
        ],
249
        shortName: [
250
          { required: true, validator: shortName, trigger: 'blur' }
251
        ],
252
        name: [
253
          { required: true, validator: name, trigger: 'blur' }
254
        ],
255
        location: [
256
          { required: true, message: '请输入地理位置信息', trigger: 'blur' }
257
        ],
258
        org: [
259
          { required: true, message: '请输入维护机构名称', trigger: 'blur' }
260
        ],
261
        phone: [
262
          { required: true, message: '请输入联系电话', trigger: 'blur' }
263
        ],
264
        addrCode: [
265
          { required: true, message: '请选择桥梁位置信息', trigger: 'blur' }
266
        ],
267
        email: [
268
          { required: true, message: '请输入联系电邮', trigger: 'blur' }
269
        ]
270
      },
271
      timeout: null,
272
      dialogTableVisible: false,
273
      tableKey: 0,
274
      list: null,
275
      total: null,
276
      listLoading: true,
277
      listQuery: {
278
        name: '',
279
        code: '',
280
        active: 1,
281
        pageSize: 10,
282
        pageNo: 1
283
      }
284
    }
285
  },
286
  filters: {
287
    typeFilter(type) {
288
289
    }
290
  },
291
  created() {
292
    this.getDictoryData()
293
  },
294
  components: {
295
    CityPicker
296
  },
297
  methods: {
298
    getDictoryData() {
299
      const that = this
300
      queryDict.applyDict('XZQH', function(dictData) {
301
        dictData.map(item => {
302
          that.citys[item.code] = item.fullCaption
303
        })
304
        that.getList()
305
      }) // 城市级联
306
    },
307
    submitForm(formName) {
308
      const that = this
309
      this.$refs[formName].validate((valid) => {
310
        if (valid) {
311
          if (this.ruleForm2.img === '') {
312
            this.ruleForm2.img = '/default-bridge.jpg'
313
          }
314
          if (!this.edit) {
315
            addDevice(this.ruleForm2).then(response => {
316
              if (response.success) {
317
                this.getList()
318
                setTimeout(function() {
319
                  that.pop('已成功添加桥梁')
320
                }, 1000)
321
                this.resetForm('ruleForm2')
322
                this.ruleForm2.img = ''
323
                this.dialogTableVisible = false
324
              }
325
            }).catch(error => {
326
              console.log(error)
327
            })
328
          } else {
329
            const par = this.ruleForm2
330
            par.id = this.edit
331
            updateDevice(par).then(response => {
332
              if (response.success) {
333
                setTimeout(function() {
334
                  that.pop('已成功更新桥梁')
335
                }, 1000)
336
                this.resetForm('ruleForm2')
337
                this.getList()
338
                this.dialogTableVisible = false
339
                this.edit = ''
340
                this.ruleForm2 = {
341
                  code: '',
342
                  shortName: '',
343
                  name: '',
344
                  addrCode: '',
345
                  serviceDay: '',
346
                  location: '',
347
                  descp: '',
348
                  remark: '',
349
                  img: '',
350
                  org: '',
351
                  phone: '',
352
                  email: ''
353
                }
354
              }
355
            })
356
          }
357
        }
358
      })
359
    },
360
    resetForm(formName) {
361
      this.dialogTableVisible = false
362
      this.$refs[formName].resetFields()
363
      this.imageUrl = ''
364
      this.edit = ''
365
    },
366
    closed() {
367
      this.$refs['ruleForm2'].resetFields()
368
      this.edit = ''
369
      this.imageUrl = ''
370
    },
371
    getList() {
372
      this.listLoading = true
373
      pageQueryDevice(this.listQuery).then(response => {
374
        if (response.success) {
375
          this.list = response.data.data
376
          this.total = response.data.total
377
          setTimeout(() => {
378
            this.listLoading = false
379
          }, 1.5 * 1000)
380
        }
381
      })
382
    },
383
    handleFilter() {
384
      this.listQuery.pageNo = 1
385
      this.getList()
386
    },
387
    handleSizeChange(val) {
388
      this.listQuery.pageSize = val
389
      this.getList()
390
    },
391
    handleCurrentChange(val) {
392
      this.listQuery.pageNo = val
393
      this.getList()
394
    },
395
    handleModifyStatus(row, status) {
396
      this.$confirm('确定要删除:桥梁' + row.code + '吗?', '提示', {
397
        confirmButtonText: '确定',
398
        cancelButtonText: '取消',
399
        type: 'warning',
400
        center: true
401
      }).then(() => {
402
        deleteDevice({ id: row.id }).then(response => {
403
          if (response.success) {
404
            this.getList()
405
            this.pop('已成功删除该桥梁')
406
          }
407
        })
408
      }).catch(() => {
409
410
      })
411
    },
412
    pop($par) {
413
      this.$confirm($par, '提示', {
414
        confirmButtonText: '确定',
415
        cancelButtonText: '取消',
416
        type: 'success',
417
        showCancelButton: false,
418
        center: true
419
      }).then(() => {
420
421
      }).catch(() => {
422
423
      })
424
    },
425
    resetTemp(row) {
426
      this.ruleForm2 = {
427
        code: row.code,
428
        shortName: row.shortName,
429
        name: row.name,
430
        addrCode: row.addrCode,
431
        serviceDay: row.serviceDay,
432
        location: row.location,
433
        descp: row.descp,
434
        remark: row.remark,
435
        img: row.img,
436
        org: row.org,
437
        phone: row.phone,
438
        email: row.email
439
      }
440
      this.edit = row.id
441
    },
442
    handleCreate() {
443
      this.dialogTableVisible = true
444
      this.ruleForm2.img = ''
445
    },
446
    handleUpdate(row) {
447
      const that = this
448
      setTimeout(function() {
449
        that.resetTemp(row)
450
        that.imageUrl = '/data/bridge' + row.img
451
      }, 500)
452
      this.dialogTableVisible = true
453
    },
454
    handleSelect(item) {
455
      this.ruleForm2.deviceId = item.id
456
    },
457
    handleAvatarSuccess(res, file) {
458
      this.imageUrl = URL.createObjectURL(file.raw)
459
      this.ruleForm2.img = res.data[0].uri
460
    },
461
    beforeAvatarUpload(file) {
462
      const isJPG = file.type === 'image/jpeg'
463
      const isPNG = file.type === 'image/png'
464
      const isLt2M = file.size / 1024 / 1024 < 5
465
      if (!isJPG && !isPNG) {
466
        this.$message.error('图片过大或格式不对请重新上传')
467
      }
468
      if (!isLt2M) {
469
        this.$message.error('图片过大或格式不对请重新上传')
470
      }
471
      return (!isJPG || !isPNG) && isLt2M
472
    },
473
    toshow(value) {
474
      this.ruleForm2.addrCode = value
475
    }
476
  }
477
}
478
</script>
479
480
<style rel="stylesheet/scss" lang="scss" scoped>
481
  .el-autocomplete{
482
    display: block
483
  }
484
  .el-btn-col{
485
    margin-top: 45px
486
  }
487
  .avatar-uploader{
488
    border: 1px dashed #409EFF;
489
    border-radius: 6px;
490
    cursor: pointer;
491
    position: relative;
492
    overflow: hidden;
493
  }
494
  .avatar-uploader {
495
    font-size: 28px;
496
    color: #8c939d;
497
    width: 260px;
498
    height: 260px;
499
    line-height: 260px;
500
    text-align: center;
501
  }
502
  .avatar {
503
    width: 260px;
504
    height: 260px;
505
    display: block;
506
  }
507
  .el-autocomplete{
508
    display: block
509
  }
510
  .el-btn-col{
511
    margin-top: 45px
512
  }
513
  .el-form-item{
514
    margin: 0px 10px
515
  }
516
  .el-select,.el-date-editor--date{
517
    width: 100%
518
  }
519
  .el-col{
520
    margin-bottom: 15px
521
  }
522
  .el-form--label-top .el-form-item__label{
523
    line-height: 20px
524
  }
525
</style>

+ 453 - 0
src/views/baseInfoManage/sensorsConfig/index.vue

@ -0,0 +1,453 @@
1
<template>
2
  <div class="app-container">
3
    <div class="filter-container" style="margin-bottom:20px">
4
      <el-input style="width: 200px;" class="filter-item" placeholder="传感器编号" v-model="listQuery.code">
5
      </el-input>
6
      <el-input style="width: 200px;" class="filter-item" placeholder="所属采集盒编号" v-model="listQuery.cdCode">
7
      </el-input>
8
      <el-button v-waves class="filter-item" style="margin-left: 10px;" @click="handleFilter" type="primary" icon="el-icon-search">查找</el-button>
9
      <el-button v-waves class="filter-item" style="margin-left: 10px;" @click="handleCreate" type="primary" icon="el-icon-edit">添加传感器</el-button>
10
    </div>
11
12
    <el-table :key='tableKey' :data="listG" v-loading="listLoading" border fit highlight-current-row
13
      style="width: 100%;min-height:550px;">
14
      <el-table-column width="150px" align="center" label="传感器编号" prop="code"></el-table-column>
15
      <el-table-column width="150px" align="center" label="内部编号" prop="seq"></el-table-column>
16
      <el-table-column width="150px" align="center" label="传感器所在主缆" prop="cableType"></el-table-column>
17
      <el-table-column width="150px" align="center" label="传感器位置" prop="locType"></el-table-column>
18
      <el-table-column min-width="150px" align="center" label="所属采集盒编号" prop="deviceName"></el-table-column>
19
      <el-table-column min-width="200px" align="center" label="备注信息" prop="remark"></el-table-column>
20
      <el-table-column align="center" label="操作" width="230" class-name="small-padding fixed-width">
21
        <template slot-scope="scope"> 
22
          <el-button v-waves type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button> 
23
          <el-button v-waves size="mini" type="danger" @click="handleModifyStatus(scope.row,'deleted')">删除
24
          </el-button>
25
        </template>
26
      </el-table-column>
27
    </el-table>
28
    <el-dialog title="传感器配置" ref="ruleForm" :visible.sync="dialogTableVisible" width="860px" @close='closed'>
29
      <el-form :model="ruleForm2" :rules="rules2" ref="ruleForm2" class="form-main"  label-position='right' status-icon>
30
        <el-row>
31
          <el-col :span="12">
32
            <el-form-item label="传感器编号" prop="code">
33
              <el-input placeholder="请输入传感器编号" v-model="ruleForm2.code" maxlength=20></el-input>
34
            </el-form-item>
35
          </el-col>
36
          <el-col :span="12">
37
            <el-form-item label="所属采集盒编号" prop="device">
38
              <el-autocomplete
39
                 v-model="ruleForm2.device"
40
                :fetch-suggestions="querySearchAsync"
41
                placeholder="请选择所属采集盒编号"
42
                @select="handleSelect">
43
              </el-autocomplete>
44
            </el-form-item>
45
          </el-col>
46
          <el-col :span="12">
47
            <el-form-item label="传感器所属主缆" prop="cableType">
48
              <el-select v-model="ruleForm2.cableType" placeholder="请选择传感器所属主缆">
49
                <el-option
50
                  v-for="item in options"
51
                  :key="item.value"
52
                  :label="item.label"
53
                  :value="item.value">
54
                </el-option>
55
              </el-select>
56
            </el-form-item>
57
          </el-col>
58
          <el-col :span="12">
59
            <el-form-item label="传感器所属位置" prop="locType">
60
              <el-select v-model="ruleForm2.locType" placeholder="请选择传感器所属位置">
61
                <el-option
62
                  v-for="item in options1"
63
                  :key="item.value"
64
                  :label="item.label"
65
                  :value="item.value">
66
                </el-option>
67
              </el-select>
68
            </el-form-item>
69
          </el-col>
70
          <el-col :span="12">
71
            <el-form-item label="内部编号" prop="seq">
72
              <el-input placeholder="请输入内部编号" v-model="ruleForm2.seq" maxlength=10></el-input>
73
            </el-form-item>
74
          </el-col>
75
          <el-col :span="24" >
76
            <el-form-item label="备注" prop="remark">
77
              <el-input type="textarea" maxlength=500 v-model="ruleForm2.remark" rows=4></el-input>
78
             </el-form-item>
79
          </el-col>
80
          <el-col :span="24" class="el-btn-col">
81
            <div class="el-btn-col-box">
82
              <el-button v-waves type="primary" @click="submitForm('ruleForm2')">确认</el-button>
83
              <el-button v-waves type="info" @click="resetForm('ruleForm2')">返回</el-button>
84
            </div>
85
          </el-col>
86
        </el-row>
87
      </el-form>
88
    </el-dialog>
89
    <div class="pagination-container" style="text-align:center;">
90
      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.pageNo" :page-size="listQuery.pageSize" layout="prev, pager, next, jumper" :total="total">
91
      </el-pagination>
92
    </div>
93
  </div>
94
</template>
95
96
<script>
97
import { addDevice, updateDevice, deleteDevice, pageQueryDevice, DeviceOfservice, checkDeviceCode, checkDeviceInternalCode } from '@/api/sensor'
98
import waves from '@/directive/waves'
99
import queryDict from '@/utils/queryDict'
100
import queryBase from '@/utils/queryBase'
101
export default {
102
  name: 'complexTable',
103
  directives: {
104
    waves
105
  },
106
  data() {
107
    var device = (rule, value, callback) => {
108
      const that = this
109
      setTimeout(function() {
110
        if (that.ruleForm2.device === '' || that.ruleForm2.deviceId === '') {
111
          callback(new Error('请选择所属采集盒编号'))
112
        } else {
113
          callback()
114
        }
115
      }, 300)
116
    }
117
    var seq = (rule, value, callback) => {
118
      const num = /^[0-9]*$/
119
      if (value === '') {
120
        callback(new Error('请输入内部编号'))
121
      } else {
122
        if (!this.ruleForm2.deviceId) {
123
          callback('请先选择所属采集盒编号')
124
          return
125
        }
126
        if (!num.test(value)) {
127
          callback('请输入数字')
128
          return
129
        }
130
        if (this.edit) {
131
          checkDeviceInternalCode({ seq: value, id: this.edit, deviceId: this.ruleForm2.deviceId, active: 1 }).then(response => {
132
            if (response.data) {
133
              callback(new Error('内部编号已存在,请重新输入'))
134
            } else {
135
              callback()
136
            }
137
          })
138
        } else {
139
          checkDeviceInternalCode({ seq: value, deviceId: this.ruleForm2.deviceId, active: 1 }).then(response => {
140
            if (response.data) {
141
              callback(new Error('内部编号已存在,请重新输入'))
142
            } else {
143
              callback()
144
            }
145
          })
146
        }
147
      }
148
    }
149
    var code = (rule, value, callback) => {
150
      if (value === '') {
151
        callback(new Error('请输入传感器编号'))
152
      } else {
153
        if (this.edit) {
154
          checkDeviceCode({ code: value, id: this.edit, active: 1 }).then(response => {
155
            if (response.data) {
156
              callback(new Error('传感器编号已存在,请重新输入'))
157
            } else {
158
              callback()
159
            }
160
          })
161
        } else {
162
          checkDeviceCode({ code: value, active: 1 }).then(response => {
163
            if (response.data) {
164
              callback(new Error('传感器编号已存在,请重新输入'))
165
            } else {
166
              callback()
167
            }
168
          })
169
        }
170
      }
171
    }
172
    return {
173
      cableMain: [],
174
      addr: [],
175
      options: [],
176
      options1: [],
177
      edit: '',
178
      ruleForm2: {
179
        code: '',
180
        cableType: '01',
181
        device: '',
182
        seq: '',
183
        deviceId: '',
184
        locType: '01',
185
        remark: ''
186
      },
187
      rules2: {
188
        code: [
189
          { required: true, validator: code, trigger: 'blur' }
190
        ],
191
        device: [
192
          { required: true, validator: device, trigger: 'blur' }
193
        ],
194
        cableType: [
195
          { required: true, message: '请选择传感器所属主缆', trigger: 'blur' }
196
        ],
197
        locType: [
198
          { required: true, message: '请选择传感器所属位置', trigger: 'blur' }
199
        ],
200
        seq: [
201
          { required: true, validator: seq, trigger: 'blur' }
202
        ]
203
      },
204
      timeout: null,
205
      dialogTableVisible: false,
206
      tableKey: 0,
207
      listG: null,
208
      total: null,
209
      listLoading: true,
210
      listQuery: {
211
        cdCode: '',
212
        code: '',
213
        active: 1,
214
        pageSize: 10,
215
        pageNo: 1
216
      }
217
    }
218
  },
219
  filters: {
220
    typeFilter(type) {
221
222
    }
223
  },
224
  created() {
225
    this.getDictoryData()
226
  },
227
  methods: {
228
    getDictoryData() {
229
      const that = this
230
      queryDict.applyDict('ZLLX', function(dictData) { // 主缆
231
        dictData.map(item => {
232
          that.options.push({ value: item.code, label: item.caption })
233
          that.cableMain[item.code] = item.caption
234
        })
235
        queryDict.applyDict('ZLWZ', function(dictData) { // 位置
236
          dictData.map(item => {
237
            that.options1.push({ value: item.code, label: item.caption })
238
            that.addr[item.code] = item.caption
239
          })
240
          that.getList()
241
        })
242
      })
243
    },
244
    submitForm(formName) {
245
      const that = this
246
      this.$refs[formName].validate((valid) => {
247
        if (valid) {
248
          if (!this.edit) {
249
            addDevice(this.ruleForm2).then(response => {
250
              if (response.success) {
251
                this.getList()
252
                setTimeout(function() {
253
                  that.pop('已成功添加传感器')
254
                }, 1000)
255
                this.resetForm('ruleForm2')
256
                this.dialogTableVisible = false
257
              }
258
            }).catch(error => {
259
              console.log(error)
260
            })
261
          } else {
262
            const par = this.ruleForm2
263
            this.options.forEach(function(item) {
264
              if (item.label === par.cableType) {
265
                par.cableType = item.value
266
              }
267
            })
268
            this.options1.forEach(function(item) {
269
              if (item.label === par.locType) {
270
                par.locType = item.value
271
              }
272
            })
273
            par.id = this.edit
274
            updateDevice(par).then(response => {
275
              if (response.success) {
276
                setTimeout(function() {
277
                  that.pop('已成功更新传感器')
278
                }, 1000)
279
                this.resetForm('ruleForm2')
280
                this.getList()
281
                this.dialogTableVisible = false
282
                this.edit = ''
283
                this.ruleForm2 = {
284
                  code: '',
285
                  cableType: '',
286
                  device: '',
287
                  seq: '',
288
                  deviceId: '',
289
                  locType: '',
290
                  remark: ''
291
                }
292
              }
293
            })
294
          }
295
        }
296
      })
297
    },
298
    resetForm(formName) {
299
      this.dialogTableVisible = false
300
      this.$refs[formName].resetFields()
301
      this.edit = ''
302
    },
303
    closed() {
304
      this.$refs['ruleForm2'].resetFields()
305
      this.edit = ''
306
    },
307
    getList() {
308
      var that = this
309
      this.listLoading = true
310
      pageQueryDevice(that.listQuery).then(response => {
311
        if (response.success) {
312
          var $data = response.data.data
313
          var hdata = { num: 1, data: $data }
314
          for (let i = 0; i < $data.length; i++) {
315
            hdata.num++
316
            $data[i].cableType = that.cableMain[$data[i].cableType]
317
            $data[i].locType = that.addr[$data[i].locType]
318
            const str = $data[i]
319
            queryBase.getDevice(str.deviceId, function(sc, value) {
320
              if (sc) {
321
                str.deviceName = value.code
322
                hdata.num--
323
                if (hdata.num === 0) {
324
                  that.listG = hdata.data
325
                }
326
              }
327
            })
328
          }
329
          hdata.num--
330
          if (hdata.num === 0) {
331
            that.listG = hdata.data
332
          }
333
          that.total = response.data.total
334
          setTimeout(() => {
335
            that.listLoading = false
336
          }, 1.5 * 1000)
337
        }
338
      })
339
    },
340
    handleFilter() {
341
      this.listQuery.pageNo = 1
342
      this.getList()
343
    },
344
    handleSizeChange(val) {
345
      this.listQuery.pageSize = val
346
      this.getList()
347
    },
348
    handleCurrentChange(val) {
349
      this.listQuery.pageNo = val
350
      this.getList()
351
    },
352
    handleModifyStatus(row, status) {
353
      this.$confirm('确定要删除:传感器' + row.code + '吗?', '提示', {
354
        confirmButtonText: '确定',
355
        cancelButtonText: '取消',
356
        type: 'warning',
357
        center: true
358
      }).then(() => {
359
        deleteDevice({ id: row.id }).then(response => {
360
          if (response.success) {
361
            this.getList()
362
            this.pop('已成功删除该传感器')
363
          }
364
        })
365
      }).catch(() => {
366
367
      })
368
    },
369
    pop($par) {
370
      this.$confirm($par, '提示', {
371
        confirmButtonText: '确定',
372
        cancelButtonText: '取消',
373
        type: 'success',
374
        showCancelButton: false,
375
        center: true
376
      }).then(() => {
377
378
      }).catch(() => {
379
380
      })
381
    },
382
    resetTemp(row) {
383
      this.ruleForm2 = {
384
        code: row.code,
385
        cableType: row.cableType,
386
        device: row.deviceName,
387
        seq: row.seq,
388
        deviceId: row.deviceId,
389
        locType: row.locType,
390
        remark: row.remark
391
      }
392
      this.edit = row.id
393
    },
394
    handleCreate() {
395
      this.dialogTableVisible = true
396
    },
397
    handleUpdate(row) {
398
      const that = this
399
      setTimeout(function() {
400
        that.resetTemp(row)
401
      }, 500)
402
      this.dialogTableVisible = true
403
    },
404
    querySearchAsync(queryString, cb) {
405
      this.ruleForm2.deviceId = ''
406
      clearTimeout(this.timeout)
407
      this.timeout = setTimeout(() => {
408
        DeviceOfservice({ code: this.ruleForm2.device, active: 1 }).then(response => {
409
          const $info = response.data
410
          if ($info.length) {
411
            const $data = $info.map(item => {
412
              return { 'value': item.code, 'id': item.id }
413
            })
414
            cb($data)
415
            if ($info.length === 1 && this.ruleForm2.bridge === $info[0].code) {
416
              this.ruleForm2.deviceId = $info[0].id
417
            } else {
418
              this.ruleForm2.deviceId = ''
419
            }
420
          } else {
421
            cb([])
422
          }
423
        })
424
      }, 3000 * Math.random())
425
    },
426
    handleSelect(item) {
427
      this.ruleForm2.deviceId = item.id
428
      this.ruleForm2.device = item.value
429
    }
430
  }
431
}
432
</script>
433
434
<style rel="stylesheet/scss" lang="scss" scoped>
435
  .el-autocomplete{
436
    display: block
437
  }
438
  .el-btn-col{
439
    margin-top: 45px
440
  }
441
  .el-form-item{
442
    margin: 0px 10px
443
  }
444
  .el-select{
445
    width: 100%
446
  }
447
  .el-col{
448
    margin-bottom: 15px
449
  }
450
  .el-form-item__label{
451
    padding: 0px
452
  }
453
</style>

+ 393 - 0
src/views/baseInfoManage/serversConfig/index.vue

@ -0,0 +1,393 @@
1
<template>
2
  <div class="app-container">
3
    <div class="filter-container" style="margin-bottom:20px">
4
      <el-input style="width: 200px;" class="filter-item" placeholder="服务器编号" v-model="listQuery.code">
5
      </el-input>
6
      <el-input style="width: 200px;" class="filter-item" placeholder="所属桥梁名称" v-model="listQuery.key">
7
      </el-input>
8
      <el-button v-waves class="filter-item" style="margin-left: 10px;" @click="handleFilter" type="primary" icon="el-icon-search">查找</el-button>
9
      <el-button v-waves class="filter-item" style="margin-left: 10px;" @click="handleCreate" type="primary" icon="el-icon-edit">添加服务器</el-button>
10
    </div>
11
12
    <el-table :key='tableKey' :data="list" v-loading="listLoading" border fit highlight-current-row
13
      style="width: 100%;min-height:550px;">
14
      <el-table-column width="150px" align="center" label="服务器编号" prop="code"></el-table-column>
15
      <el-table-column width="150px" align="center" label="内部编号" prop="seq"></el-table-column>
16
      <el-table-column width="150px" align="center" label="采集盒数量" prop="devices"></el-table-column>
17
      <el-table-column min-width="150px" align="center" label="所属桥梁" prop="bridgeName"></el-table-column>
18
      <el-table-column min-width="200px" align="center" label="备注信息" prop="remark"></el-table-column>
19
      <el-table-column align="center" label="操作" width="230" class-name="small-padding fixed-width">
20
        <template slot-scope="scope"> 
21
          <el-button v-waves type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button> 
22
          <el-button v-waves size="mini" type="danger" @click="handleModifyStatus(scope.row,'deleted')">删除
23
          </el-button>
24
        </template>
25
      </el-table-column>
26
    </el-table>
27
    <el-dialog title="采集服务器配置" ref="ruleForm" :visible.sync="dialogTableVisible" width="860px" @close='closed'>
28
      <el-form :model="ruleForm2" :rules="rules2" ref="ruleForm2" class="form-main"  label-position='right' status-icon>
29
        <el-row>
30
          <el-col :span="12">
31
            <el-form-item label="服务器编号" prop="code">
32
              <el-input placeholder="请输入服务器编号" v-model="ruleForm2.code" maxlength=20></el-input>
33
            </el-form-item>
34
          </el-col>
35
          <el-col :span="12">
36
            <el-form-item label="采集盒数量" prop="devices">
37
              <el-input placeholder="请输入采集盒数量" v-model="ruleForm2.devices" maxlength=10></el-input>
38
            </el-form-item>
39
          </el-col>
40
          <el-col :span="12">
41
            <el-form-item label="所属桥梁" prop="bridge">
42
              <el-autocomplete
43
                 v-model="ruleForm2.bridge"
44
                :fetch-suggestions="querySearchAsync"
45
                placeholder="请选择所属桥梁"
46
                @select="handleSelect">
47
              </el-autocomplete>
48
            </el-form-item>
49
          </el-col>
50
          <el-col :span="12">
51
            <el-form-item label="内部编号" prop="seq">
52
              <el-input placeholder="请输入内部编号" v-model="ruleForm2.seq" maxlength=20></el-input>
53
            </el-form-item>
54
          </el-col>
55
          <el-col :span="24" >
56
            <el-form-item label="备注" prop="remark">
57
              <el-input type="textarea" maxlength=500 v-model="ruleForm2.remark" rows=4></el-input>
58
             </el-form-item>
59
          </el-col>
60
          <el-col :span="24" class="el-btn-col">
61
            <div class="el-btn-col-box">
62
              <el-button v-waves type="primary" @click="submitForm('ruleForm2')">确认</el-button>
63
              <el-button v-waves type="info" @click="resetForm('ruleForm2')">返回</el-button>
64
            </div>
65
          </el-col>
66
        </el-row>
67
      </el-form>
68
    </el-dialog>
69
    <div class="pagination-container" style="text-align:center;">
70
      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.pageNo" :page-size="listQuery.pageSize" layout="prev, pager, next, jumper" :total="total">
71
      </el-pagination>
72
    </div>
73
  </div>
74
</template>
75
76
<script>
77
import { addDevice, updateDevice, deleteDevice, pageQueryDevice, DeviceOfservice, checkDeviceCode, checkDeviceInternalCode } from '@/api/server'
78
import waves from '@/directive/waves'
79
import queryBase from '@/utils/queryBase'
80
export default {
81
  name: 'complexTable',
82
  directives: {
83
    waves
84
  },
85
  data() {
86
    var bridge = (rule, value, callback) => {
87
      const that = this
88
      setTimeout(function() {
89
        if (that.ruleForm2.bridge === '' || that.ruleForm2.bridgeId === '') {
90
          callback(new Error('请选择所属桥梁'))
91
        } else {
92
          callback()
93
        }
94
      }, 300)
95
    }
96
    var seq = (rule, value, callback) => {
97
      const num = /^[0-9a-zA-Z]*$/
98
      if (value === '') {
99
        callback(new Error('请输入内部编号'))
100
      } else {
101
        if (!this.ruleForm2.bridgeId) {
102
          callback('请先选择所属桥梁')
103
          return
104
        }
105
        if (!num.test(value)) {
106
          callback('请输入数字或字母')
107
          return
108
        }
109
        if (this.edit) {
110
          checkDeviceInternalCode({ seq: value, id: this.edit, bridgeId: this.ruleForm2.bridgeId, active: 1 }).then(response => {
111
            if (response.data) {
112
              callback(new Error('内部编号已存在,请重新输入'))
113
            } else {
114
              callback()
115
            }
116
          })
117
        } else {
118
          checkDeviceInternalCode({ seq: value, bridgeId: this.ruleForm2.bridgeId, active: 1 }).then(response => {
119
            if (response.data) {
120
              callback(new Error('内部编号已存在,请重新输入'))
121
            } else {
122
              callback()
123
            }
124
          })
125
        }
126
      }
127
    }
128
    var code = (rule, value, callback) => {
129
      if (value === '') {
130
        callback(new Error('请输入服务器编号'))
131
      } else {
132
        if (this.edit) {
133
          checkDeviceCode({ code: value, id: this.edit, active: 1 }).then(response => {
134
            if (response.data) {
135
              callback(new Error('服务器编号已存在,请重新输入'))
136
            } else {
137
              callback()
138
            }
139
          })
140
        } else {
141
          checkDeviceCode({ code: value, active: 1 }).then(response => {
142
            if (response.data) {
143
              callback(new Error('服务器编号已存在,请重新输入'))
144
            } else {
145
              callback()
146
            }
147
          })
148
        }
149
      }
150
    }
151
    return {
152
      edit: '',
153
      ruleForm2: {
154
        code: '',
155
        bridge: '',
156
        seq: '',
157
        bridgeId: '',
158
        remark: '',
159
        devices: ''
160
      },
161
      rules2: {
162
        code: [
163
          { required: true, validator: code, trigger: 'blur' }
164
        ],
165
        bridge: [
166
          { required: true, validator: bridge, trigger: 'blur' }
167
        ],
168
        devices: [
169
          { required: true, message: '请输入采集盒数量', trigger: 'blur' }
170
        ],
171
        seq: [
172
          { required: true, validator: seq, trigger: 'blur' }
173
        ]
174
      },
175
      timeout: null,
176
      dialogTableVisible: false,
177
      tableKey: 0,
178
      list: null,
179
      total: null,
180
      listLoading: true,
181
      listQuery: {
182
        key: '',
183
        code: '',
184
        active: 1,
185
        pageSize: 10,
186
        pageNo: 1
187
      }
188
    }
189
  },
190
  filters: {
191
    typeFilter(type) {
192
193
    }
194
  },
195
  created() {
196
    this.getList()
197
  },
198
  methods: {
199
    submitForm(formName) {
200
      const that = this
201
      this.$refs[formName].validate((valid) => {
202
        if (valid) {
203
          if (!this.edit) {
204
            addDevice(this.ruleForm2).then(response => {
205
              if (response.success) {
206
                this.getList()
207
                setTimeout(function() {
208
                  that.pop('已成功添加服务器')
209
                }, 1000)
210
                this.resetForm('ruleForm2')
211
                this.dialogTableVisible = false
212
              }
213
            }).catch(error => {
214
              console.log(error)
215
            })
216
          } else {
217
            const par = this.ruleForm2
218
            par.id = this.edit
219
            updateDevice(par).then(response => {
220
              if (response.success) {
221
                setTimeout(function() {
222
                  that.pop('已成功更新服务器')
223
                }, 1000)
224
                this.resetForm('ruleForm2')
225
                this.getList()
226
                this.dialogTableVisible = false
227
                this.edit = ''
228
                this.ruleForm2 = {
229
                  code: '',
230
                  bridge: '',
231
                  seq: '',
232
                  bridgeId: '',
233
                  devices: '',
234
                  remark: ''
235
                }
236
              }
237
            })
238
          }
239
        }
240
      })
241
    },
242
    resetForm(formName) {
243
      this.dialogTableVisible = false
244
      this.$refs[formName].resetFields()
245
      this.edit = ''
246
    },
247
    closed() {
248
      this.$refs['ruleForm2'].resetFields()
249
      this.edit = ''
250
    },
251
    getList() {
252
      var that = this
253
      this.listLoading = true
254
      pageQueryDevice(this.listQuery).then(response => {
255
        if (response.success) {
256
          const $data = response.data.data
257
          var hdata = { num: 1, data: $data }
258
          for (let i = 0; i < $data.length; i++) {
259
            hdata.num++
260
            const str = $data[i]
261
            queryBase.getBridge(str.bridgeId, function(sc, value) {
262
              if (sc) {
263
                str.bridgeName = value.shortName
264
                hdata.num--
265
                if (hdata.num === 0) {
266
                  that.list = hdata.data
267
                }
268
              }
269
            })
270
          }
271
          hdata.num--
272
          if (hdata.num === 0) {
273
            that.list = hdata.data
274
          }
275
          that.total = response.data.total
276
          setTimeout(() => {
277
            that.listLoading = false
278
          }, 1.5 * 1000)
279
        }
280
      })
281
    },
282
    handleFilter() {
283
      this.listQuery.pageNo = 1
284
      this.getList()
285
    },
286
    handleSizeChange(val) {
287
      this.listQuery.pageSize = val
288
      this.getList()
289
    },
290
    handleCurrentChange(val) {
291
      this.listQuery.pageNo = val
292
      this.getList()
293
    },
294
    handleModifyStatus(row, status) {
295
      this.$confirm('确定要删除:服务器' + row.code + '吗?', '提示', {
296
        confirmButtonText: '确定',
297
        cancelButtonText: '取消',
298
        type: 'warning',
299
        center: true
300
      }).then(() => {
301
        deleteDevice({ id: row.id }).then(response => {
302
          if (response.success) {
303
            this.getList()
304
            this.pop('已成功删除该服务器')
305
          }
306
        })
307
      }).catch(() => {
308
309
      })
310
    },
311
    pop($par) {
312
      this.$confirm($par, '提示', {
313
        confirmButtonText: '确定',
314
        cancelButtonText: '取消',
315
        type: 'success',
316
        showCancelButton: false,
317
        center: true
318
      }).then(() => {
319
320
      }).catch(() => {
321
322
      })
323
    },
324
    resetTemp(row) {
325
      this.ruleForm2 = {
326
        code: row.code,
327
        bridge: row.bridgeName,
328
        seq: row.seq,
329
        bridgeId: row.bridgeId,
330
        devices: row.devices,
331
        remark: row.remark
332
      }
333
      this.edit = row.id
334
    },
335
    handleCreate() {
336
      this.dialogTableVisible = true
337
    },
338
    handleUpdate(row) {
339
      const that = this
340
      setTimeout(function() {
341
        that.resetTemp(row)
342
      }, 500)
343
      this.dialogTableVisible = true
344
    },
345
    querySearchAsync(queryString, cb) {
346
      this.ruleForm2.bridgeId = ''
347
      clearTimeout(this.timeout)
348
      this.timeout = setTimeout(() => {
349
        DeviceOfservice({ key: this.ruleForm2.bridge, active: 1 }).then(response => {
350
          const $info = response.data
351
          if ($info.length) {
352
            const $data = $info.map(item => {
353
              return { 'value': item.shortName, 'id': item.id }
354
            })
355
            cb($data)
356
            if ($info.length === 1 && this.ruleForm2.bridge === $info[0].shortName) {
357
              this.ruleForm2.bridgeId = $info[0].id
358
            } else {
359
              this.ruleForm2.bridgeId = ''
360
            }
361
          } else {
362
            cb([])
363
          }
364
        })
365
      }, 3000 * Math.random())
366
    },
367
    handleSelect(item) {
368
      this.ruleForm2.bridgeId = item.id
369
    }
370
  }
371
}
372
</script>
373
374
<style rel="stylesheet/scss" lang="scss" scoped>
375
  .el-autocomplete{
376
    display: block
377
  }
378
  .el-btn-col{
379
    margin-top: 45px
380
  }
381
  .el-form-item{
382
    margin: 0px 10px
383
  }
384
  .el-select{
385
    width: 100%
386
  }
387
  .el-col{
388
    margin-bottom: 15px
389
  }
390
  .el-form-item__label{
391
    padding: 0px
392
  }
393
</style>

+ 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>

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

@ -0,0 +1,250 @@
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 v-waves 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 v-waves 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 v-waves 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 v-waves 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
  import waves from '@/directive/waves'
57
58
  export default {
59
    directives: {
60
      waves
61
    },
62
    data() {
63
      var validPhone = (rule, value, callback) => {
64
        const reg = /^1[3|4|5|7|8][0-9]\d{8}$/
65
        if (!value) {
66
          callback(new Error('请输入您的手机号码'))
67
        } else if (!reg.test(value)) {
68
          callback(new Error('请输入正确的手机号码'))
69
        } else {
70
          callback()
71
        }
72
      }
73
      var validatePass = (rule, value, callback) => {
74
        if (value === '') {
75
          callback(new Error('请设置您的新密码'))
76
        } else if (value.length < 6 || value.length > 24) {
77
          callback(new Error('密码由6-24个字符组成,区分大小写'))
78
        } else {
79
          if (this.ruleForm2.checkPass !== '') {
80
            this.$refs.ruleForm2.validateField('checkPass')
81
          }
82
          callback()
83
        }
84
      }
85
      var validatePass2 = (rule, value, callback) => {
86
        if (value === '') {
87
          callback(new Error('请再次输入密码确认'))
88
        } else if (value !== this.ruleForm2.pass) {
89
          callback(new Error('两次输入密码不一致,请重新输入!'))
90
        } else {
91
          callback()
92
        }
93
      }
94
      return {
95
        phoneCodeBol: false,
96
        sendMsgDisabled: false,
97
        seconds: 60,
98
        platId: '',
99
        resetStepNum: '',
100
        resetCode: '',
101
        stepVal: 0,
102
        stepFisrt: true,
103
        stepSecond: false,
104
        isDisabl: false,
105
        ruleForm: {
106
          phoneNum: '',
107
          msgVC: ''
108
        },
109
        rules: {
110
          phoneNum: [
111
            { required: true, validator: validPhone, trigger: 'blur' }
112
          ],
113
          msgVC: [
114
            { required: true, message: '请输入短信验证码', trigger: 'blur' }
115
          ]
116
        },
117
        ruleForm2: {
118
          pass: '',
119
          checkPass: ''
120
        },
121
        rules2: {
122
          pass: [
123
            { validator: validatePass, trigger: 'blur' }
124
          ],
125
          checkPass: [
126
            { validator: validatePass2, trigger: 'blur' }
127
          ]
128
        }
129
      }
130
    },
131
    methods: {
132
      nextStep(formName) {
133
        this.$refs[formName].validate((valid) => {
134
          if (valid) {
135
            this.stepFisrt = false
136
            this.stepSecond = true
137
            this.stepVal = 1
138
          } else {
139
            return false
140
          }
141
        })
142
      },
143
      userRegisterOk() {
144
        const me = this
145
        const account = this.ruleForm.phoneNum
146
        isReg({ account }).then(res => {
147
          if (res.success) {
148
            if (res.data === true) {
149
              me.sendMsgDisabled = false
150
              me.phoneCodeBol = false
151
              me.$message({
152
                message: '该账号不存在,请检查后重试',
153
                type: 'warning'
154
              })
155
            } else {
156
              me.getResetMsgPhone()
157
              me.sendMsgDisabled = true
158
              me.phoneCodeBol = true
159
              const interval = window.setInterval(function() {
160
                if ((me.seconds--) <= 0) {
161
                  me.seconds = 60
162
                  me.sendMsgDisabled = false
163
                  me.phoneCodeBol = false
164
                  window.clearInterval(interval)
165
                }
166
              }, 1000)
167
            }
168
          }
169
        })
170
      },
171
      getResetMsgPhone() {
172
        const me = this
173
        const account = this.ruleForm.phoneNum
174
        const checkExists = true
175
        getResetMsgPhone({ account, checkExists }).then((res) => {
176
          if (!res.success) {
177
            if (res.code === -60000) {
178
              me.sendMsgDisabled = false
179
              me.phoneCodeBol = false
180
              me.$message({
181
                message: '该账号不存在,请检查后重试',
182
                type: 'warning'
183
              })
184
            } else {
185
              me.$message({
186
                message: res.detailMsg,
187
                type: 'warning'
188
              })
189
            }
190
          }
191
        })
192
      },
193
      clickMsgVcLogin() {
194
        const reg = /^1[3|4|5|7|8][0-9]\d{8}$/
195
        if (!this.ruleForm.phoneNum) {
196
          this.$message({
197
            message: '请输入你的手机号码',
198
            type: 'warning'
199
          })
200
        } else if (!reg.test(this.ruleForm.phoneNum)) {
201
          this.$message({
202
            message: '请输入正确的手机号码',
203
            type: 'warning'
204
          })
205
        } else {
206
          this.userRegisterOk()
207
        }
208
      },
209
      resetPwd(formName) {
210
        this.$refs[formName].validate((valid) => {
211
          if (valid) {
212
            resetPwdByTel(this.ruleForm2.pass, this.ruleForm.msgVC).then((res) => {
213
              if (res.success) {
214
                this.$alert('密码已重置,快去登录吧!', '提示', {
215
                  confirmButtonText: '确定',
216
                  type: 'success',
217
                  center: true,
218
                  callback: action => {
219
                    if (action === 'confirm') {
220
                      this.$router.push({ path: '/login' })
221
                    }
222
                  }
223
                })
224
              } else {
225
                this.$alert('密码重置失败!', '提示', {
226
                  confirmButtonText: '重新找回密码',
227
                  type: 'warning',
228
                  center: true,
229
                  callback: action => {
230
                    if (action === 'confirm') {
231
                      this.stepFisrt = true
232
                      this.stepSecond = false
233
                      this.stepVal = 0
234
                    }
235
                  }
236
                })
237
                return
238
              }
239
            })
240
          } else {
241
            return false
242
          }
243
        })
244
      },
245
      goLogin() {
246
        this.$router.push({ path: '/login' })
247
      }
248
    }
249
  }
250
</script>

+ 3 - 0
src/views/home/index.vue

@ -0,0 +1,3 @@
1
<template>
2
	<div>home</div>
3
</template>	

+ 3 - 0
src/views/hospital/index.vue

@ -0,0 +1,3 @@
1
<template>
2
  <div>医院</div>
3
</template>	

+ 3 - 0
src/views/intelligentJudgment/index.vue

@ -0,0 +1,3 @@
1
<template>
2
	<div>AI智能判断</div>
3
</template>	

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

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

+ 78 - 0
src/views/layout/common.vue

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

+ 45 - 0
src/views/layout/components/Abb.vue

@ -0,0 +1,45 @@
1
<template>
2
  <div>
3
    <el-menu class="navbar" mode="horizontal">
4
      <breadcrumb></breadcrumb>
5
    </el-menu>
6
  </div>
7
</template>
8
9
<script>
10
import Breadcrumb from '@/components/Breadcrumb'
11
12
export default {
13
  components: {
14
    Breadcrumb
15
  }
16
}
17
</script>
18
19
<style rel="stylesheet/scss" lang="scss" scoped>
20
.navbar {
21
  height: 50px;
22
  line-height: 50px;
23
  padding: 0 12px;
24
  border-radius: 0px !important;
25
  .hamburger-container {
26
    line-height: 58px;
27
    height: 50px;
28
    float: left;
29
    padding: 0 10px;
30
  }
31
  .screenfull {
32
    position: absolute;
33
    right: 90px;
34
    top: 16px;
35
    color: red;
36
  }
37
}
38
.message-box{
39
  color: #303133;
40
  background: #c7e3ff;
41
  padding: 0 20px;
42
  font-size: 14px;
43
}
44
</style>
45

+ 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>

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

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

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

@ -0,0 +1,189 @@
1
<template>
2
  <div class="topnavbar">
3
    <div class='topnavbarBox'>
4
      <div class="logo-container">
5
        <div class="logo-wrapper" @click="toHome"><div class="logo-img"></div></div>
6
        <el-dropdown v-if="roles.indexOf('1')<0" trigger="click" class="drop-menu">
7
          <span class="el-dropdown-link">
8
            {{showName ? showName : '选择桥梁'}}<i class="el-icon-arrow-down el-icon--right"></i>
9
          </span>
10
          <el-dropdown-menu class="drop-menu-list" style="min-width:120px;" slot="dropdown">
11
            <el-dropdown-item v-for="item in dataList" :key="item.index" :disabled="item.disab" @click.native="goToDashboardC(item.id, item.shortName)">{{item.shortName}}
12
              <i v-if="item.disab" class="el-icon-check"></i>
13
            </el-dropdown-item>
14
          </el-dropdown-menu>
15
        </el-dropdown>
16
      </div>
17
      <div class="name-box">
18
        <span>您好,{{ name }}</span>
19
        <span class="exit-btn" @click="logout">退出登录</span>
20
      </div>
21
    </div>
22
  </div>
23
</template>
24
25
<script>
26
import { mapGetters } from 'vuex'
27
import { MessageBox } from 'element-ui'
28
import { getBridgeList } from '@/api/bridgeInfo'
29
import Cookies from 'js-cookie'
30
31
export default {
32
  data() {
33
    return {
34
      bridgeId: '',
35
      showName: '',
36
      dataList: ''
37
    }
38
  },
39
  computed: {
40
    ...mapGetters([
41
      'name',
42
      'roles'
43
    ])
44
  },
45
  watch: {
46
    '$route'(to, from) {
47
      if (to.path === '/dashboard') {
48
        var dataList = this.dataList
49
        for (let i = 0; i < dataList.length; i++) {
50
          dataList[i].disab = false
51
        }
52
        Cookies.remove('bridgeId')
53
        Cookies.remove('bridgeName')
54
        this.showName = ''
55
      } else {
56
        this.bridgeId = Cookies.get('bridgeId')
57
        this.showName = Cookies.get('bridgeName')
58
        this.getBridgeLists()
59
      }
60
    }
61
  },
62
  created() {
63
    this.bridgeId = Cookies.get('bridgeId')
64
    this.showName = Cookies.get('bridgeName')
65
    this.getBridgeLists()
66
  },
67
  methods: {
68
    toHome() {
69
      this.$router.replace({ path: '/' })
70
    },
71
    toggleSideBar() {
72
      this.$store.dispatch('ToggleSideBar')
73
    },
74
    logout() {
75
      MessageBox.confirm('您确认要退出登录吗?', '提示', {
76
        confirmButtonText: '确定',
77
        cancelButtonText: '取消',
78
        type: 'warning',
79
        center: true
80
      }).then(() => {
81
        this.$store.dispatch('LogOut').then(() => {
82
          Cookies.remove('bridgeId')
83
          Cookies.remove('bridgeName')
84
          location.reload() // 为了重新实例化vue-router对象 避免bug
85
        })
86
      }).catch(() => {
87
        console.log('已取消退出')
88
      })
89
    },
90
    getBridgeLists() {
91
      const param = {
92
        active: 1,
93
        pageSize: 10,
94
        pageNo: 1
95
      }
96
      getBridgeList(param).then(res => {
97
        if (res.success) {
98
          for (let i = 0; i < res.data.data.length; i++) {
99
            if (res.data.data[i].id === this.bridgeId) {
100
              res.data.data[i].disab = true
101
            } else {
102
              res.data.data[i].disab = false
103
            }
104
          }
105
          this.dataList = res.data.data
106
        }
107
      })
108
    },
109
    goToDashboardC(id, name) {
110
      this.showName = name
111
      Cookies.set('bridgeId', id)
112
      Cookies.set('bridgeName', name)
113
      this.$router.replace({
114
        name: 'bridgeDetail',
115
        query: { id: id, name: name }
116
      })
117
    }
118
  }
119
}
120
</script>
121
122
<style rel="stylesheet/scss" lang="scss" scoped>
123
.topnavbar {
124
  position: fixed;
125
  font-size: 0px;
126
  top: 0;
127
  left: 0;
128
  right: 0;
129
  height: 50px;
130
  line-height: 50px;
131
  z-index:1002;
132
  border-radius: 0px !important;
133
  background-color: #2d3a4b;
134
  border-bottom: 1px solid #e6e6e6;
135
  .topnavbarBox {
136
    position: relative;
137
    margin: auto;
138
    width: 1100px;
139
    box-sizing: border-box;
140
    padding: 0 10px;
141
    .logo-container {
142
      display: inline-block;
143
      position: absolute;
144
      left:10px;
145
      overflow: hidden;
146
      .logo-wrapper {
147
        float:left;
148
        width:300px;
149
        padding: 0;
150
        margin:10px 12px;
151
        cursor: pointer;
152
      }
153
      .drop-menu{
154
        float:left;
155
        cursor: pointer;
156
        margin:0;
157
        margin-left:20px;
158
        color: #fff;
159
      }
160
    }
161
    .name-box{
162
      display: inline-block;
163
      position: absolute;
164
      right: 20px;
165
      font-size:14px;
166
      overflow: hidden;
167
      color:#fff;
168
      .exit-btn {
169
        margin-left:30px;
170
        cursor: pointer;
171
      }
172
    }
173
  }
174
}
175
.drop-menu-list{
176
  .el-dropdown-menu__item{
177
    display: flex;
178
    align-items: center;
179
    justify-content: space-between;
180
    &.is-disabled{
181
      background: #f3f5f7;
182
    }
183
    .el-icon-check{
184
      font-weight: bold;
185
    }
186
  }
187
}
188
</style>
189

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

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

+ 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
}

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

@ -0,0 +1,148 @@
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 v-waves 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 v-waves 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 waves from '@/directive/waves'
43
import '@/styles/loginform.scss'
44
45
export default {
46
  name: 'login',
47
  directives: {
48
    waves
49
  },
50
  data() {
51
    var validPhone = (rule, value, callback) => {
52
      const reg = /^1[3|4|5|7|8][0-9]\d{8}$/
53
      if (!value) {
54
        callback(new Error('请输入您的手机号码'))
55
      } else if (!reg.test(value)) {
56
        callback(new Error('请输入正确的手机号码'))
57
      } else {
58
        callback()
59
      }
60
    }
61
    return {
62
      falg: false,
63
      imgVcUrl: '',
64
      loginForm: {
65
        username: '',
66
        password: '',
67
        imgVerifyCode: ''
68
      },
69
      loginRules: {
70
        username: [{ required: true, trigger: 'blur', validator: validPhone }],
71
        password: [
72
          { required: true, message: '请输入您的登录密码', trigger: 'blur' },
73
          { min: 6, max: 24, message: '密码由6-24个字符组成,区分大小写', trigger: 'blur' }
74
        ],
75
        imgVerifyCode: [{ required: true, message: '请输入图形验证码', trigger: 'blur' }]
76
      },
77
      loading: false,
78
      pwdType: 'password'
79
    }
80
  },
81
  created() {
82
    this.changeImgVc()
83
  },
84
  methods: {
85
    showPwd() {
86
      this.falg = !this.falg
87
      if (this.pwdType === 'password') {
88
        this.pwdType = ''
89
      } else {
90
        this.pwdType = 'password'
91
      }
92
    },
93
    handleLogin() {
94
      this.$refs.loginForm.validate(valid => {
95
        if (valid) {
96
          this.loading = true
97
          this.$store.dispatch('LoginByUsername', this.loginForm).then((response) => {
98
            this.loading = false
99
            if (response.success) {
100
              if (response.data) {
101
                this.$store.dispatch('GetUserInfo').then(res => {
102
                })
103
                this.$router.push({ path: '/dashboard' })
104
              } else {
105
                Message.error('登录账号与密码不匹配,请检查后重试')
106
                this.changeImgVc()
107
                return
108
              }
109
            } else {
110
              const errorCode = [{
111
                code: -60001,
112
                msg: '图形验证码不存在'
113
              }, {
114
                code: -60002,
115
                msg: '图形验证码超时'
116
              }, {
117
                code: -60003,
118
                msg: '图形验证码不正确'
119
              }, {
120
                code: -60005,
121
                msg: '该账号已停用,请联系管理员'
122
              }]
123
              for (let i = 0; i < errorCode.length; i++) {
124
                if (response.code === errorCode[i].code) {
125
                  Message.error(errorCode[i].msg)
126
                  this.changeImgVc()
127
                  return
128
                }
129
              }
130
            }
131
          }).catch(() => {
132
            this.loading = false
133
          })
134
        } else {
135
          console.log('error submit!!')
136
          return false
137
        }
138
      })
139
    },
140
    goBackPwd() {
141
      this.$router.push({ path: '/findPwd' })
142
    },
143
    changeImgVc() {
144
      this.imgVcUrl = getPictureVC('PIC_LOGIN')
145
    }
146
  }
147
}
148
</script>

+ 3 - 0
src/views/medicalTreatment/index.vue

@ -0,0 +1,3 @@
1
<template>
2
	<div>协同诊疗</div>
3
</template>	

+ 51 - 0
src/views/nav/index.vue

@ -0,0 +1,51 @@
1
<template>
2
<el-menu style='display:flex'
3
  :default-active="activeIndex2"
4
  class="el-menu-demo"
5
  mode="horizontal"
6
  @select="handleSelect"
7
  background-color="green"
8
  text-color="#fff"
9
  active-text-color="#ffd04b">
10
   <router-link to='/show/home'>
11
    <el-menu-item index="1">首页</el-menu-item>
12
   </router-link>
13
   <router-link to='/show/medicalTreatment'>
14
    <el-menu-item index="2">协同诊疗</el-menu-item>
15
   </router-link>
16
   <router-link to='/show/intelligentJudgment'>
17
    <el-menu-item index="3">AI智能判断</el-menu-item>
18
   </router-link>
19
   <router-link to='/show/sharedDevice'>
20
    <el-menu-item index="4">共享器械</el-menu-item>
21
   </router-link>
22
   <router-link to='/show/hospital'> 
23
    <el-menu-item index="5">医院</el-menu-item>
24
   </router-link>
25
</el-menu>
26
</template>
27
<script>
28
  export default {
29
    data() {
30
      return {
31
        activeIndex: '1',
32
        activeIndex2: '1'
33
      }
34
    },
35
    methods: {
36
      handleSelect(key, keyPath) {
37
        console.log(key, keyPath)
38
      }
39
    }
40
  }
41
</script>
42
43
<style rel="stylesheet/scss" lang="scss" scoped>
44
  @import "src/styles/mixin.scss";
45
  .el-menu-demo {
46
    margin: auto;
47
    width: 1100px;
48
    box-sizing: border-box;
49
    padding: 0 10px;
50
  }
51
</style>

+ 3 - 0
src/views/peoplesManage/accountSettings/index.vue

@ -0,0 +1,3 @@
1
<template>
2
	<div>账户设置</div>
3
</template>

+ 15 - 0
src/views/peoplesManage/infoManage/editSystemMessage.vue

@ -0,0 +1,15 @@
1
<template>
2
   <el-form class="form-main" label-width="120px">
3
      <el-row>
4
         <el-col :span="24" >
5
            <el-input type="textarea" rows=8 maxlength=100></el-input>
6
        </el-col>
7
        <el-col :span="24" class="el-btn-col">
8
          <div class="el-btn-col-box">
9
            <el-button type="primary" @click="submitForm('ruleForm')">确认</el-button>
10
            <el-button type="info">返回</el-button>
11
          </div>
12
        </el-col>
13
      </el-row>
14
    </el-form>
15
</template>

+ 285 - 0
src/views/peoplesManage/infoManage/editUser.vue

@ -0,0 +1,285 @@
1
<template>
2
  <el-dialog title="编辑用户" ref="ruleForm" :visible.sync="dialogTableVisible" width="860px" @close='closed'>
3
     <el-form class="form-main" :model="ruleForm2" :rules="rules2" ref="ruleForm2"  label-position='top' status-icon>
4
        <el-row>
5
          <el-col :span="12">
6
            <el-form-item label="账号" prop='account'>
7
              <el-input placeholder="请输入账号" v-model="ruleForm2.account" maxlength=11></el-input>
8
            </el-form-item>
9
          </el-col>
10
          <el-col :span="12">
11
            <el-form-item label="用户姓名" prop='name'>
12
              <el-input placeholder="请输入用户姓名" v-model="ruleForm2.name" maxlength=20></el-input>
13
            </el-form-item>
14
          </el-col>
15
          <el-col :span="12">
16
            <el-form-item label="职位" prop='job'>
17
              <el-input placeholder="请输入用户职位" v-model="ruleForm2.job" maxlength=100></el-input>
18
            </el-form-item>
19
          </el-col>
20
          <el-col :span="12">
21
            <el-form-item label="用户所在机构" prop='comp'>
22
              <el-input placeholder="请输入用户所在机构" v-model="ruleForm2.comp" maxlength=200></el-input>
23
            </el-form-item>
24
          </el-col>
25
          <el-col :span="12">
26
            <el-form-item label="用户类型" prop='type'>
27
              <el-select v-model="ruleForm2.type" placeholder="请选择用户类型">
28
                <el-option
29
                  v-for="item in options"
30
                  :key="item.value"
31
                  :label="item.label"
32
                  :value="item.value">
33
                </el-option>
34
              </el-select>
35
            </el-form-item>
36
          </el-col>
37
          <el-col :span="12">
38
            <el-form-item label="联系电话" prop='phone'>
39
              <el-input placeholder="请输入手机号码" v-model="ruleForm2.phone" maxlength=11></el-input>
40
            </el-form-item>
41
          </el-col>
42
          <el-col :span="12">
43
            <el-form-item label="联系邮箱" prop='email'>
44
              <el-input placeholder="请输入邮箱地址" v-model="ruleForm2.email" maxlength=100></el-input>
45
            </el-form-item>
46
          </el-col>
47
          <el-col :span="24" >
48
            <el-form-item label="备注" prop='remark'>
49
              <el-input type="textarea" rows=4 v-model="ruleForm2.remark" maxlength=500></el-input>
50
             </el-form-item>
51
          </el-col>
52
          <el-col :span="24" class="el-btn-col">
53
            <div class="el-btn-col-box">
54
              <el-button type="primary" @click="submitForm('ruleForm2')">确认</el-button>
55
              <el-button type="info"  @click="resetForm('ruleForm2')">返回</el-button>
56
            </div>
57
          </el-col>
58
        </el-row>
59
      </el-form>
60
    </el-dialog>
61
</template>
62
63
<script>
64
import { checkRegister, addRegister, updateRegister, queryRegister } from '@/api/userManagemen'
65
export default {
66
  props: ['dialog', 'id'],
67
  data() {
68
    var account = (rule, value, callback) => {
69
      const regTel = /^1[3|4|5|7|8][0-9]\d{8}$/
70
      if (value === '') {
71
        callback(new Error('请输入账号'))
72
      } else {
73
        if (!regTel.test(value)) {
74
          callback(new Error('账号为手机号格式'))
75
        } else {
76
          if (this.edit) {
77
            checkRegister({ account: value, id: this.edit }).then(response => {
78
              if (!response.data) {
79
                callback(new Error('账户已存在,请重新输入'))
80
              } else {
81
                callback()
82
              }
83
            })
84
          } else {
85
            checkRegister({ account: value }).then(response => {
86
              if (!response.data) {
87
                callback(new Error('账户已存在,请重新输入'))
88
              } else {
89
                callback()
90
              }
91
            })
92
          }
93
        }
94
      }
95
    }
96
    var phone = (rule, value, callback) => {
97
      const regTel = /^1[3|4|5|7|8][0-9]\d{8}$/
98
      if (value === '') {
99
        callback()
100
      } else {
101
        if (!regTel.test(value)) {
102
          callback(new Error('手机号码格式不正确'))
103
        } else {
104
          callback()
105
        }
106
      }
107
    }
108
    var email = (rule, value, callback) => {
109
      const regTel = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
110
      if (value === '') {
111
        callback()
112
      } else {
113
        if (!regTel.test(value)) {
114
          callback(new Error('邮箱格式不正确'))
115
        } else {
116
          callback()
117
        }
118
      }
119
    }
120
    return {
121
      options: [{
122
        value: 0,
123
        label: '普通用户'
124
      }, {
125
        value: 1,
126
        label: '管理员'
127
      }],
128
      dialogTableVisible: false,
129
      ruleForm2: {
130
        edit: '',
131
        account: '',
132
        name: '',
133
        comp: '',
134
        job: '',
135
        phone: '',
136
        email: '',
137
        remark: '',
138
        type: 0
139
      },
140
      rules2: {
141
        account: [
142
          { required: true, validator: account, trigger: 'blur' }
143
        ],
144
        name: [
145
          { required: true, message: '请输入用户姓名', trigger: 'blur' }
146
        ],
147
        comp: [
148
          { required: true, message: '请输入用户所在机构', trigger: 'blur' }
149
        ],
150
        job: [
151
          { required: true, message: '请输入用户职位', trigger: 'blur' }
152
        ],
153
        phone: [
154
          { validator: phone, trigger: 'blur' }
155
        ],
156
        email: [
157
          { validator: email, trigger: 'blur' }
158
        ]
159
      }
160
    }
161
  },
162
  watch: {
163
    dialog() {
164
      this.dialogTableVisible = true
165
      this.edit = this.id
166
      if (this.edit) {
167
        queryRegister({ id: this.edit }).then(response => {
168
          if (response.success) {
169
            const $data = response.data
170
            this.ruleForm2 = {
171
              account: $data.account,
172
              name: $data.name,
173
              comp: $data.comp,
174
              job: $data.job,
175
              phone: $data.phone || '',
176
              email: $data.email || '',
177
              remark: $data.remark || '',
178
              type: $data.type
179
            }
180
          }
181
        })
182
      }
183
    }
184
  },
185
  methods: {
186
    submitForm(formName) {
187
      const that = this
188
      this.$refs[formName].validate((valid) => {
189
        if (valid) {
190
          if (!this.edit) {
191
            addRegister(this.ruleForm2).then(response => {
192
              if (response.success) {
193
                this.$emit('chilF')
194
                setTimeout(function() {
195
                  that.pop('已成功添加')
196
                }, 1000)
197
                this.resetForm(this.ruleForm2)
198
                this.dialogTableVisible = false
199
              }
200
            }).catch(error => {
201
              console.log(error)
202
            })
203
          } else {
204
            const par = this.ruleForm2
205
            par.id = this.edit
206
            updateRegister(par).then(response => {
207
              if (response.success) {
208
                setTimeout(function() {
209
                  that.pop('已成功更新用户信息')
210
                }, 1000)
211
                this.resetForm('ruleForm2')
212
                this.$emit('chilF')
213
                this.dialogTableVisible = false
214
                this.edit = ''
215
                this.ruleForm2 = {
216
                  account: '',
217
                  name: '',
218
                  comp: '',
219
                  job: '',
220
                  phone: '',
221
                  email: '',
222
                  remark: '',
223
                  type: 0
224
                }
225
              }
226
            })
227
          }
228
        }
229
      })
230
    },
231
    resetForm(formName) {
232
      this.dialogTableVisible = false
233
      this.$refs[formName].resetFields()
234
      this.edit = ''
235
      this.$emit('chilF', true)
236
    },
237
    closed() {
238
      this.$refs['ruleForm2'].resetFields()
239
      this.edit = ''
240
      this.$emit('chilF', true)
241
    },
242
    pop($par) {
243
      this.$confirm($par, '提示', {
244
        confirmButtonText: '确定',
245
        cancelButtonText: '取消',
246
        type: 'success',
247
        showCancelButton: false,
248
        center: true
249
      }).then(() => {
250
251
      }).catch(() => {
252
253
      })
254
    },
255
    resetTemp(row) {
256
      this.ruleForm2 = {
257
        account: row.account,
258
        name: row.name,
259
        comp: row.comp,
260
        job: row.job,
261
        phone: row.phone,
262
        email: row.email,
263
        remark: row.remark,
264
        type: row.type
265
      }
266
      this.edit = row.id
267
    }
268
  }
269
}
270
</script>
271
272
<style rel="stylesheet/scss" lang="scss" scoped>
273
  .el-form-item{
274
    margin: 0px 10px
275
  }
276
  .el-select{
277
    width: 100%
278
  }
279
  .el-col{
280
    margin-bottom: 15px
281
  }
282
  .el-form--label-top .el-form-item__label {
283
    padding: 0
284
  }
285
</style>

+ 216 - 0
src/views/peoplesManage/infoManage/editUserPermissions.vue

@ -0,0 +1,216 @@
1
<template>
2
  <el-dialog title="用户数据权限修改" :visible.sync="dialogTableVisible" width="860px" @close='closed'>
3
    <el-form class="form-main" :model="ruleForm2"  ref="ruleForm2">
4
      <el-row :gutter="16">
5
        <el-col :xs="24" :sm="24" :lg="24">
6
          <div class="list-item">
7
            <el-row>
8
              <el-col :span="8">
9
                <el-form-item label="账号">{{ruleForm2.account}}</el-form-item>
10
              </el-col>
11
              <el-col :span="8">
12
                <el-form-item label="用户姓名">{{ruleForm2.name}}</el-form-item>
13
              </el-col>
14
              <el-col :span="8">
15
                <el-form-item label="用户类型">{{(ruleForm2.type) ? '管理员' : '普通用户'}}</el-form-item>
16
              </el-col>
17
              <el-col :span="8">
18
                <el-form-item label="职位">{{ruleForm2.job}}</el-form-item>
19
              </el-col>
20
              <el-col :span="16">
21
                <el-form-item label="所属机构">{{ruleForm2.comp}}</el-form-item>
22
              </el-col>
23
            </el-row>
24
          </div>
25
        </el-col>
26
<!--         <el-col :xs="12" :sm="12" :lg="12">
27
          <div class="list-item">
28
            <el-row>
29
              <el-col :span="24">
30
                <el-form-item label="添加负责桥梁">
31
                  <el-autocomplete
32
                    v-model="state4"
33
                    :fetch-suggestions="querySearchAsync"
34
                    placeholder="请选择一个桥梁"
35
                    @select="handleSelect">
36
                  </el-autocomplete>
37
                </el-form-item>
38
              </el-col>
39
              <el-col :span="24" style="margin-top:30px"> 
40
                 <el-table
41
                  :show-header="shouHead"
42
                  :data="tableData3"
43
                  height="250"
44
                  border
45
                  style="width: 100%">
46
                  <el-table-column
47
                    prop="name"
48
                    label=""
49
                    min-width="180">
50
                  </el-table-column>
51
                  <el-table-column
52
                    prop="address"
53
                    label="">
54
                    <template slot-scope="scope">  
55
                      <el-button size="mini" type="danger" @click="handleModifyStatus(scope.row,'deleted')">删除
56
                      </el-button>
57
                    </template>
58
                  </el-table-column>
59
                </el-table>
60
              </el-col>
61
            </el-row>
62
          </div>
63
        </el-col> -->
64
        <el-col :xs="24" :sm="24" :lg="24">
65
          <el-transfer class="check-transfer"
66
            filterable
67
            v-model="valueBridge"
68
            :titles="['所有桥梁', '负责桥梁']"
69
            :button-texts="['删除', '添加']"
70
            :props="{
71
              key: 'id',
72
              label: 'value'
73
            }"
74
            :data="bridgeLists">
75
          </el-transfer>
76
        </el-col>
77
        <el-col :span="24" class="el-btn-col">
78
          <div class="el-btn-col-box">
79
            <el-button type="primary" @click="submit">确认</el-button>
80
            <el-button type="info"  @click="closed">返回</el-button>
81
          </div>
82
        </el-col>
83
      </el-row>
84
    </el-form>
85
  </el-dialog>
86
</template>
87
88
<script>
89
import { queryRegister, queryResponsibleBridge, DeviceOfservice, updatePermission } from '@/api/userManagemen'
90
export default {
91
  props: ['dialog', 'id'],
92
  data() {
93
    return {
94
      bridgeLists: [],
95
      bridgeListsChecked: [],
96
      valueBridge: [],
97
      shouHead: false,
98
      state4: '',
99
      ruleForm2: {
100
        account: '',
101
        name: '',
102
        comp: '',
103
        job: '',
104
        type: 0
105
      },
106
      dialogTableVisible: false
107
    }
108
  },
109
  created() {
110
    this.getAllBridges()
111
  },
112
  watch: {
113
    dialog() {
114
      queryRegister({ id: this.id }).then(response => {
115
        if (response.success) {
116
          const $data = response.data
117
          this.ruleForm2 = {
118
            account: $data.account,
119
            name: $data.name,
120
            comp: $data.comp,
121
            job: $data.job,
122
            type: $data.type
123
          }
124
        }
125
      })
126
      queryResponsibleBridge({ uid: this.id, active: 1 }).then(response => {
127
        if (response.success) {
128
          const $info = response.data
129
          for (let j = 0; j < $info.length; j++) {
130
            this.valueBridge.push($info[j].id)
131
          }
132
        }
133
      })
134
      this.dialogTableVisible = true
135
    }
136
  },
137
  methods: {
138
    getAllBridges() {
139
      DeviceOfservice({ key: this.state4, active: 1 }).then(response => {
140
        if (response.success) {
141
          const $info = response.data
142
          if ($info.length) {
143
            this.bridgeListsChecked.push($info[0].id)
144
            const $data = $info.map(item => {
145
              return { 'value': item.shortName, 'id': item.id }
146
            })
147
            this.bridgeLists = $data
148
          }
149
        }
150
      })
151
    },
152
    pop($par) {
153
      this.$confirm($par, '提示', {
154
        confirmButtonText: '确定',
155
        cancelButtonText: '取消',
156
        type: 'success',
157
        showCancelButton: false,
158
        center: true
159
      }).then(() => {
160
161
      }).catch(() => {
162
163
      })
164
    },
165
    closed() {
166
      this.valueBridge = []
167
      this.dialogTableVisible = false
168
    },
169
    submit() {
170
      if (!this.valueBridge.length) {
171
        this.$message.error('请至少选择一个桥梁')
172
        return
173
      }
174
      updatePermission({ id: this.id, bridges: this.valueBridge }).then(response => {
175
        if (response.success) {
176
          this.valueBridge = []
177
          this.$emit('chilF')
178
          const that = this
179
          setTimeout(function() {
180
            that.pop('权限修改成功')
181
          }, 1000)
182
          this.dialogTableVisible = false
183
        }
184
      })
185
    }
186
  }
187
}
188
</script>
189
190
<style rel="stylesheet/scss" lang="scss" scoped>
191
  .el-form-item{
192
    margin-bottom: 10px;
193
  }
194
  .textarea-div{
195
    line-height: 26px;
196
    margin-bottom: 10px;
197
  }
198
  .list-item{
199
    padding: 10px 15px;
200
  }
201
  .el-autocomplete {
202
    width: 100%
203
  }
204
  .check-transfer.el-transfer{
205
    padding-left: 15px;
206
    margin-bottom: 15px;
207
    display: -webkit-flex;
208
    display: -moz-flex;
209
    display: -ms-flexbox;
210
    display: flex;
211
    justify-content: center
212
  }
213
  .check-transfer .el-transfer-panel{
214
    width: 240px;
215
  }
216
</style>

+ 214 - 0
src/views/peoplesManage/infoManage/index.vue

@ -0,0 +1,214 @@
1
<template>
2
  <div class="app-container">
3
    <div class="filter-container" style="margin-bottom:20px">
4
      <el-input style="width: 200px;" class="filter-item" placeholder="账号" v-model="listQuery.account">
5
      </el-input>
6
       <el-input style="width: 200px;" class="filter-item" placeholder="用户姓名" v-model="listQuery.name">
7
      </el-input>
8
       <el-input style="width: 250px;" class="filter-item" placeholder="所在机构" v-model="listQuery.comp">
9
      </el-input>
10
      <el-button v-waves class="filter-item" style="margin-left: 10px;" @click="handleFilter" type="primary" icon="el-icon-search">查找</el-button>
11
      <el-button v-waves class="filter-item" style="margin-left: 10px;" @click="handleCreate" type="primary" icon="el-icon-edit">添加用户</el-button>
12
    </div>
13
    <el-table :key='tableKey' :data="list" v-loading="listLoading" border fit highlight-current-row
14
      style="width: 100%;min-height:550px;">
15
      <el-table-column width="110px" align="center" label="账号">
16
        <template slot-scope="scope">
17
          <span>{{scope.row.account}}</span>
18
        </template>
19
      </el-table-column>
20
      <el-table-column width="80px" align="center" label="用户姓名">
21
        <template slot-scope="scope">
22
          <span>{{scope.row.name}}</span>
23
        </template>
24
      </el-table-column>
25
      <el-table-column width="200px" align="center" label="职位">
26
        <template slot-scope="scope">
27
          <span>{{scope.row.job}}</span>
28
        </template>
29
      </el-table-column>
30
      <el-table-column width="110px" align="center" label="联系电话">
31
        <template slot-scope="scope">
32
          <span>{{scope.row.phone}}</span>
33
        </template>
34
      </el-table-column>
35
      <el-table-column width="100px" align="center" label="用户类型">
36
        <template slot-scope="scope">
37
          <span>{{(scope.row.type) ? '管理员' : '普通用户'}}</span>
38
        </template>
39
      </el-table-column>
40
      <el-table-column width="100px" align="center" label="账户状态">
41
        <template slot-scope="scope">
42
          <span :class="{ active: !scope.row.active}">{{(scope.row.active) ? '未停用' : '已停用'}}</span>
43
        </template>
44
      </el-table-column>
45
      <el-table-column min-width="200px" align="center" label="所在机构">
46
        <template slot-scope="scope">
47
          <span>{{scope.row.comp}}</span>
48
        </template>
49
      </el-table-column>
50
      <el-table-column min-width="200px" align="center" label="负责桥梁">
51
        <template slot-scope="scope">
52
          <span>{{scope.row.bridgeName}}</span>
53
        </template>
54
      </el-table-column>
55
      <el-table-column align="center" label="操作" width="260px" class-name="small-padding fixed-width">
56
        <template slot-scope="scope"> 
57
          <el-button v-waves :type="((!scope.row.active) ? 'info' : 'primary')" size="mini" @click="handleUpdate(scope.row)" :disabled='!scope.row.active'>编辑</el-button> 
58
          <el-button v-waves size="mini" :type="((!scope.row.active) ? 'info' : 'danger')" @click="handleModifyStatus(scope.row,'deleted')" :disabled='!scope.row.active'>停用
59
          </el-button>
60
           <el-button v-waves size="mini" :type="((!scope.row.active) ? 'info' : 'primary')" @click="distribution(scope.row)" :disabled='!scope.row.active'>分配权限
61
          </el-button>
62
        </template>
63
        
64
      </el-table-column>
65
    </el-table>
66
    <editUser :dialog="dialogTableVisible" @chilF='chilF' :id='edit'></editUser>
67
    <editUserPermissions :dialog='dialogPerssion' @chilF='chilF' :id='edit'></editUserPermissions>
68
    <div class="pagination-container" style="text-align:center;">
69
      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.page" :page-size="listQuery.limit" layout="prev, pager, next, jumper" :total="total">
70
      </el-pagination>
71
    </div>
72
  </div>
73
</template>
74
75
<script>
76
import { deleteUser, queryResponsibleBridge, pageQueryUser } from '@/api/userManagemen'
77
import waves from '@/directive/waves'
78
import editUser from './editUser'
79
import editUserPermissions from './editUserPermissions'
80
81
export default {
82
  name: 'complexTable',
83
  directives: {
84
    waves
85
  },
86
  data() {
87
    return {
88
      edit: '',
89
      tableKey: 0,
90
      list: null,
91
      total: null,
92
      listLoading: true,
93
      dialogPerssion: false,
94
      dialogTableVisible: false,
95
      listQuery: {
96
        account: '',
97
        name: '',
98
        comp: '',
99
        pageSize: 10,
100
        pageNo: 1
101
      }
102
    }
103
  },
104
  filters: {
105
    typeFilter(type) {
106
107
    }
108
  },
109
  created() {
110
    this.getList()
111
  },
112
  components: {
113
    editUser,
114
    editUserPermissions
115
  },
116
  methods: {
117
    getList() {
118
      this.listLoading = true
119
      pageQueryUser(this.listQuery).then(response => {
120
        if (response.success) {
121
          if (response.data === null) {
122
            this.list = []
123
            this.total = 0
124
            setTimeout(() => {
125
              this.listLoading = false
126
            }, 1.5 * 1000)
127
            return
128
          }
129
          const $data = response.data.data
130
          for (let i = 0; i < $data.length; i++) {
131
            $data[i].bridgeName = ''
132
            queryResponsibleBridge({ uid: $data[i].id, active: 1 }).then(response => {
133
              if (response.success) {
134
                const arr = []
135
                const $info = response.data
136
                for (let j = 0; j < $info.length; j++) {
137
                  arr.push($info[j].shortName)
138
                }
139
                $data[i].bridgeName = arr.join(',')
140
              }
141
            })
142
          }
143
          this.list = $data
144
          this.total = response.data.total
145
          setTimeout(() => {
146
            this.listLoading = false
147
          }, 1.5 * 1000)
148
        }
149
      })
150
    },
151
    handleFilter() {
152
      this.listQuery.pageNo = 1
153
      this.getList()
154
    },
155
    handleSizeChange(val) {
156
      this.listQuery.pageNo = val
157
      this.getList()
158
    },
159
    chilF(val) {
160
      if (!val) {
161
        this.getList()
162
      }
163
      this.edit = ''
164
    },
165
    handleCurrentChange(val) {
166
      this.listQuery.pageNo = val
167
      this.getList()
168
    },
169
    handleModifyStatus(row, status) {
170
      this.$confirm('确定要停用:用户' + row.name + '吗?', '提示', {
171
        confirmButtonText: '确定',
172
        cancelButtonText: '取消',
173
        type: 'warning',
174
        center: true
175
      }).then(() => {
176
        deleteUser({ id: row.id }).then(response => {
177
          if (response.success) {
178
            this.getList()
179
            this.pop('已成功停用该用户')
180
          }
181
        })
182
      }).catch(() => {
183
184
      })
185
    },
186
    handleCreate() {
187
      this.dialogTableVisible = !this.dialogTableVisible
188
    },
189
    handleUpdate(row) {
190
      this.edit = row.id
191
      this.dialogTableVisible = !this.dialogTableVisible
192
    },
193
    distribution(row) {
194
      this.edit = row.id
195
      this.dialogPerssion = !this.dialogPerssion
196
    }
197
  }
198
}
199
</script>
200
201
<style rel="stylesheet/scss" lang="scss" scoped>
202
  .el-autocomplete{
203
    display: block
204
  }
205
  .el-btn-col{
206
    margin-top: 45px
207
  }
208
  .editTe{
209
    margin: 10px 0 0 22px
210
  }
211
  .active{
212
    color: red
213
  }
214
</style>

+ 3 - 0
src/views/sharedDevice/index.vue

@ -0,0 +1,3 @@
1
<template>
2
	<div>共享器械</div>
3
</template>	

+ 0 - 0
static/.gitkeep


BIN
static/login_bg.jpg


BIN
static/touchwave.png