@ -0,0 +1,14 @@ | 
			
		|||||
 | 
				# http://editorconfig.org | 
			
		||||
 | 
				root = true | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				[*] | 
			
		||||
 | 
				charset = utf-8 | 
			
		||||
 | 
				indent_style = space | 
			
		||||
 | 
				indent_size = 2 | 
			
		||||
 | 
				end_of_line = lf | 
			
		||||
 | 
				insert_final_newline = true | 
			
		||||
 | 
				trim_trailing_whitespace = true | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				[*.md] | 
			
		||||
 | 
				insert_final_newline = false | 
			
		||||
 | 
				trim_trailing_whitespace = false | 
			
		||||
@ -0,0 +1,2 @@ | 
			
		|||||
 | 
				VITE_APP_COMPANY=asdzxcasdzxc | 
			
		||||
 | 
				
 | 
			
		||||
@ -0,0 +1,6 @@ | 
			
		|||||
 | 
				# base api | 
			
		||||
 | 
				VITE_APP_BASE_API=/api | 
			
		||||
 | 
				VITE_APP_WVP_API=/wvp | 
			
		||||
 | 
				VITE_APP_PLAY_PORT=8090 | 
			
		||||
 | 
				VITE_APP_BASE_URL=http://192.168.0.129:8890/cc-admin | 
			
		||||
 | 
				VITE_APP_WVP_URL=http://127.0.0.1:18899 | 
			
		||||
@ -0,0 +1,4 @@ | 
			
		|||||
 | 
				# base api | 
			
		||||
 | 
				VITE_APP_BASE_API=/cc-admin | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				VITE_APP_BASE_URL=http://222.128.25.216:4050 | 
			
		||||
@ -0,0 +1,271 @@ | 
			
		|||||
 | 
				module.exports = { | 
			
		||||
 | 
				  root: true, | 
			
		||||
 | 
				  parser: "vue-eslint-parser", | 
			
		||||
 | 
				  parserOptions: { | 
			
		||||
 | 
				      parser: "@typescript-eslint/parser", | 
			
		||||
 | 
				      sourceType: "module", | 
			
		||||
 | 
				        ecmaFeatures: { | 
			
		||||
 | 
				          'jsx': true | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  env: { | 
			
		||||
 | 
				    browser: true, | 
			
		||||
 | 
				    node: true, | 
			
		||||
 | 
				    es6: true | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  extends: ['plugin:vue/recommended', 'eslint:recommended','prettier'], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  // add your custom rules here
 | 
			
		||||
 | 
				  // it is base on https://github.com/vuejs/eslint-config-vue
 | 
			
		||||
 | 
				  rules: { | 
			
		||||
 | 
				    'vue/singleline-html-element-content-newline': 'off', | 
			
		||||
 | 
				    'vue/multiline-html-element-content-newline': 'off', | 
			
		||||
 | 
				    'vue/name-property-casing': 'off', | 
			
		||||
 | 
				    'vue/no-v-html': 'off', | 
			
		||||
 | 
				    'vue/multi-word-component-names': 'off', | 
			
		||||
 | 
				    'vue/max-attributes-per-line': 'off', | 
			
		||||
 | 
				    // 'accessor-pairs': 2,
 | 
			
		||||
 | 
				    // 'arrow-spacing': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     before: true,
 | 
			
		||||
 | 
				    //     after: true
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'block-spacing': [2, 'always'],
 | 
			
		||||
 | 
				    // 'brace-style': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   '1tbs',
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     allowSingleLine: true
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // camelcase: [
 | 
			
		||||
 | 
				    //   0,
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     properties: 'always'
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'comma-dangle': [2, 'never'],
 | 
			
		||||
 | 
				    // 'comma-spacing': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     before: false,
 | 
			
		||||
 | 
				    //     after: true
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'comma-style': [2, 'last'],
 | 
			
		||||
 | 
				    // 'constructor-super': 2,
 | 
			
		||||
 | 
				    // curly: [2, 'multi-line'],
 | 
			
		||||
 | 
				    // 'dot-location': [2, 'property'],
 | 
			
		||||
 | 
				    // 'eol-last': 2,
 | 
			
		||||
 | 
				    // eqeqeq: ['error', 'always', { null: 'ignore' }],
 | 
			
		||||
 | 
				    // 'generator-star-spacing': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     before: true,
 | 
			
		||||
 | 
				    //     after: true
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'handle-callback-err': [2, '^(err|error)$'],
 | 
			
		||||
 | 
				    // indent: [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     SwitchCase: 1
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'jsx-quotes': [2, 'prefer-single'],
 | 
			
		||||
 | 
				    // 'key-spacing': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     beforeColon: false,
 | 
			
		||||
 | 
				    //     afterColon: true
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'keyword-spacing': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     before: true,
 | 
			
		||||
 | 
				    //     after: true
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'new-cap': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     newIsCap: true,
 | 
			
		||||
 | 
				    //     capIsNew: false
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'new-parens': 2,
 | 
			
		||||
 | 
				    // 'no-array-constructor': 2,
 | 
			
		||||
 | 
				    // 'no-caller': 2,
 | 
			
		||||
 | 
				    // 'no-console': 'off',
 | 
			
		||||
 | 
				    // 'no-class-assign': 2,
 | 
			
		||||
 | 
				    // 'no-cond-assign': 2,
 | 
			
		||||
 | 
				    // 'no-const-assign': 2,
 | 
			
		||||
 | 
				    // 'no-control-regex': 0,
 | 
			
		||||
 | 
				    // 'no-delete-var': 2,
 | 
			
		||||
 | 
				    // 'no-dupe-args': 2,
 | 
			
		||||
 | 
				    // 'no-dupe-class-members': 2,
 | 
			
		||||
 | 
				    // 'no-dupe-keys': 2,
 | 
			
		||||
 | 
				    // 'no-duplicate-case': 2,
 | 
			
		||||
 | 
				    // 'no-empty-character-class': 2,
 | 
			
		||||
 | 
				    // 'no-empty-pattern': 2,
 | 
			
		||||
 | 
				    // 'no-eval': 2,
 | 
			
		||||
 | 
				    // 'no-ex-assign': 2,
 | 
			
		||||
 | 
				    // 'no-extend-native': 2,
 | 
			
		||||
 | 
				    // 'no-extra-bind': 2,
 | 
			
		||||
 | 
				    // 'no-extra-boolean-cast': 2,
 | 
			
		||||
 | 
				    // 'no-extra-parens': [2, 'functions'],
 | 
			
		||||
 | 
				    // 'no-fallthrough': 2,
 | 
			
		||||
 | 
				    // 'no-floating-decimal': 2,
 | 
			
		||||
 | 
				    // 'no-func-assign': 2,
 | 
			
		||||
 | 
				    // 'no-implied-eval': 2,
 | 
			
		||||
 | 
				    // 'no-inner-declarations': [2, 'functions'],
 | 
			
		||||
 | 
				    // 'no-invalid-regexp': 2,
 | 
			
		||||
 | 
				    // 'no-irregular-whitespace': 2,
 | 
			
		||||
 | 
				    // 'no-iterator': 2,
 | 
			
		||||
 | 
				    // 'no-label-var': 2,
 | 
			
		||||
 | 
				    // 'no-labels': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     allowLoop: false,
 | 
			
		||||
 | 
				    //     allowSwitch: false
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'no-lone-blocks': 2,
 | 
			
		||||
 | 
				    // 'no-mixed-spaces-and-tabs': 2,
 | 
			
		||||
 | 
				    // 'no-multi-spaces': 2,
 | 
			
		||||
 | 
				    // 'no-multi-str': 2,
 | 
			
		||||
 | 
				    // 'no-multiple-empty-lines': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     max: 1
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'no-native-reassign': 2,
 | 
			
		||||
 | 
				    // 'no-negated-in-lhs': 2,
 | 
			
		||||
 | 
				    // 'no-new-object': 2,
 | 
			
		||||
 | 
				    // 'no-new-require': 2,
 | 
			
		||||
 | 
				    // 'no-new-symbol': 2,
 | 
			
		||||
 | 
				    // 'no-new-wrappers': 2,
 | 
			
		||||
 | 
				    // 'no-obj-calls': 2,
 | 
			
		||||
 | 
				    // 'no-octal': 2,
 | 
			
		||||
 | 
				    // 'no-octal-escape': 2,
 | 
			
		||||
 | 
				    // 'no-path-concat': 2,
 | 
			
		||||
 | 
				    // 'no-proto': 2,
 | 
			
		||||
 | 
				    // 'no-redeclare': 2,
 | 
			
		||||
 | 
				    // 'no-regex-spaces': 2,
 | 
			
		||||
 | 
				    // 'no-return-assign': [2, 'except-parens'],
 | 
			
		||||
 | 
				    // 'no-self-assign': 2,
 | 
			
		||||
 | 
				    // 'no-self-compare': 2,
 | 
			
		||||
 | 
				    // 'no-sequences': 2,
 | 
			
		||||
 | 
				    // 'no-shadow-restricted-names': 2,
 | 
			
		||||
 | 
				    // 'no-spaced-func': 2,
 | 
			
		||||
 | 
				    // 'no-sparse-arrays': 2,
 | 
			
		||||
 | 
				    // 'no-this-before-super': 2,
 | 
			
		||||
 | 
				    // 'no-throw-literal': 2,
 | 
			
		||||
 | 
				    // 'no-trailing-spaces': 2,
 | 
			
		||||
 | 
				    // 'no-undef': 2,
 | 
			
		||||
 | 
				    // 'no-undef-init': 2,
 | 
			
		||||
 | 
				    // 'no-unexpected-multiline': 2,
 | 
			
		||||
 | 
				    // 'no-unmodified-loop-condition': 2,
 | 
			
		||||
 | 
				    // 'no-unneeded-ternary': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     defaultAssignment: false
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'no-unreachable': 2,
 | 
			
		||||
 | 
				    // 'no-unsafe-finally': 2,
 | 
			
		||||
 | 
				    // 'no-unused-vars': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     vars: 'all',
 | 
			
		||||
 | 
				    //     args: 'none'
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'no-useless-call': 2,
 | 
			
		||||
 | 
				    // 'no-useless-computed-key': 2,
 | 
			
		||||
 | 
				    // 'no-useless-constructor': 2,
 | 
			
		||||
 | 
				    // 'no-useless-escape': 0,
 | 
			
		||||
 | 
				    // 'no-whitespace-before-property': 2,
 | 
			
		||||
 | 
				    // 'no-with': 2,
 | 
			
		||||
 | 
				    // 'one-var': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     initialized: 'never'
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'operator-linebreak': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   'after',
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     overrides: {
 | 
			
		||||
 | 
				    //       '?': 'before',
 | 
			
		||||
 | 
				    //       ':': 'before'
 | 
			
		||||
 | 
				    //     }
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'padded-blocks': [2, 'never'],
 | 
			
		||||
 | 
				    // quotes: [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   'single',
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     avoidEscape: true,
 | 
			
		||||
 | 
				    //     allowTemplateLiterals: true
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // semi: [2, 'never'],
 | 
			
		||||
 | 
				    // 'semi-spacing': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     before: false,
 | 
			
		||||
 | 
				    //     after: true
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'space-before-blocks': [2, 'always'],
 | 
			
		||||
 | 
				    // 'space-before-function-paren': [2, 'never'],
 | 
			
		||||
 | 
				    // 'space-in-parens': [2, 'never'],
 | 
			
		||||
 | 
				    // 'space-infix-ops': 2,
 | 
			
		||||
 | 
				    // 'space-unary-ops': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     words: true,
 | 
			
		||||
 | 
				    //     nonwords: false
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'spaced-comment': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   'always',
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     markers: [
 | 
			
		||||
 | 
				    //       'global',
 | 
			
		||||
 | 
				    //       'globals',
 | 
			
		||||
 | 
				    //       'eslint',
 | 
			
		||||
 | 
				    //       'eslint-disable',
 | 
			
		||||
 | 
				    //       '*package',
 | 
			
		||||
 | 
				    //       '!',
 | 
			
		||||
 | 
				    //       ','
 | 
			
		||||
 | 
				    //     ]
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'template-curly-spacing': [2, 'never'],
 | 
			
		||||
 | 
				    // 'use-isnan': 2,
 | 
			
		||||
 | 
				    // 'valid-typeof': 2,
 | 
			
		||||
 | 
				    // 'wrap-iife': [2, 'any'],
 | 
			
		||||
 | 
				    // 'yield-star-spacing': [2, 'both'],
 | 
			
		||||
 | 
				    // yoda: [2, 'never'],
 | 
			
		||||
 | 
				    // 'prefer-const': 2,
 | 
			
		||||
 | 
				    // 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
 | 
			
		||||
 | 
				    // 'object-curly-spacing': [
 | 
			
		||||
 | 
				    //   2,
 | 
			
		||||
 | 
				    //   'always',
 | 
			
		||||
 | 
				    //   {
 | 
			
		||||
 | 
				    //     objectsInObjects: false
 | 
			
		||||
 | 
				    //   }
 | 
			
		||||
 | 
				    // ],
 | 
			
		||||
 | 
				    // 'array-bracket-spacing': [2, 'never']
 | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,18 @@ | 
			
		|||||
 | 
				.DS_Store | 
			
		||||
 | 
				node_modules/ | 
			
		||||
 | 
				dist/ | 
			
		||||
 | 
				npm-debug.log* | 
			
		||||
 | 
				yarn-debug.log* | 
			
		||||
 | 
				yarn-error.log* | 
			
		||||
 | 
				package-lock.json | 
			
		||||
 | 
				tests/**/coverage/ | 
			
		||||
 | 
				pnpm-lock.yaml | 
			
		||||
 | 
				# Editor directories and files | 
			
		||||
 | 
				.idea | 
			
		||||
 | 
				.vscode | 
			
		||||
 | 
				*.suo | 
			
		||||
 | 
				*.ntvs* | 
			
		||||
 | 
				*.njsproj | 
			
		||||
 | 
				*.sln | 
			
		||||
 | 
				release | 
			
		||||
 | 
				dist-electron | 
			
		||||
@ -0,0 +1,5 @@ | 
			
		|||||
 | 
				language: node_js | 
			
		||||
 | 
				node_js: 10 | 
			
		||||
 | 
				script: npm run test | 
			
		||||
 | 
				notifications: | 
			
		||||
 | 
				  email: false | 
			
		||||
@ -0,0 +1,21 @@ | 
			
		|||||
 | 
				MIT License | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				Copyright (c) 2022 misaka10032 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				Permission is hereby granted, free of charge, to any person obtaining a copy | 
			
		||||
 | 
				of this software and associated documentation files (the "Software"), to deal | 
			
		||||
 | 
				in the Software without restriction, including without limitation the rights | 
			
		||||
 | 
				to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
			
		||||
 | 
				copies of the Software, and to permit persons to whom the Software is | 
			
		||||
 | 
				furnished to do so, subject to the following conditions: | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				The above copyright notice and this permission notice shall be included in all | 
			
		||||
 | 
				copies or substantial portions of the Software. | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
			
		||||
 | 
				IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
			
		||||
 | 
				FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
			
		||||
 | 
				AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
			
		||||
 | 
				LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
			
		||||
 | 
				OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 
			
		||||
 | 
				SOFTWARE. | 
			
		||||
@ -0,0 +1,84 @@ | 
			
		|||||
 | 
				# 依赖 | 
			
		||||
 | 
				vue2 + elementui2 +vue-router+ axios + pinia | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				# 开发说明 | 
			
		||||
 | 
				- `views/` 目录仅存放页面(路由)组件,(因为菜单管理会读取views文件列表) | 
			
		||||
 | 
				- `components/` 页面的组件存放在components目录,目录要和views中页面路径一致 | 
			
		||||
 | 
				- `components/common/` 公共组件存放 | 
			
		||||
 | 
				- `directive/` 挂载全局指令 | 
			
		||||
 | 
				- `methods/` 挂载全局函数 | 
			
		||||
 | 
				- `store/` 状态管理(https://pinia.vuejs.org/zh/) | 
			
		||||
 | 
				# vite-admin-template | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				[原作者,可以参考代码示例](https://panjiachen.gitee.io/vue-admin-template) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				[原作者预览地址](https://panjiachen.github.io/vue-element-admin/#) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				[原作者文档](https://panjiachen.github.io/vue-element-admin-site/zh/) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				[二次改编](https://gitee.com/mi-sa-ka10032/vite-element-template.git) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				[本仓库](http://182.92.163.198:3000/18610965287/cc-admin-element-ui.git) | 
			
		||||
 | 
				## Build Setup | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				```bash | 
			
		||||
 | 
				# 安装依赖、npm建议替换为pnpm | 
			
		||||
 | 
				npm install | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				# 建议不要直接使用 cnpm 安装,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题 | 
			
		||||
 | 
				npm install --registry=https://registry.npm.taobao.org | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				# 启动服务 | 
			
		||||
 | 
				npm run dev | 
			
		||||
 | 
				npm run dev:test | 
			
		||||
 | 
				npm run dev:staging | 
			
		||||
 | 
				``` | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				浏览器访问 [http://localhost:9528](http://localhost:9528) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				## 发布 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				```bash | 
			
		||||
 | 
				# 构建生产环境 | 
			
		||||
 | 
				npm run build | 
			
		||||
 | 
				``` | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				## 其它 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				```bash | 
			
		||||
 | 
				# 预览发布环境效果 | 
			
		||||
 | 
				npm run preview | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				# 预览发布环境效果 + 静态资源分析 | 
			
		||||
 | 
				# npm run preview -- --report | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				# 代码格式检查 | 
			
		||||
 | 
				npm run lint | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				# 代码格式检查并自动修复 | 
			
		||||
 | 
				npm run lint -- --fix | 
			
		||||
 | 
				``` | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				# 图标使用 | 
			
		||||
 | 
				1. svg图标,放在`src/icons/svg` 目录下 | 
			
		||||
 | 
				```html | 
			
		||||
 | 
				<svg-icon :icon-class="文件名" class-name="disabled" /> | 
			
		||||
 | 
				``` | 
			
		||||
 | 
				2. element自带图标 | 
			
		||||
 | 
				```html | 
			
		||||
 | 
				<i :class="'el-icon-图标名'" /> | 
			
		||||
 | 
				``` | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				3. 合并svg图标、element自带图标 | 
			
		||||
 | 
				```html | 
			
		||||
 | 
				<AnyIcon :icon="svg文件名或者el图标名" :class-name="icon" ></AnyIcon> | 
			
		||||
 | 
				<style scoped> | 
			
		||||
 | 
				.icon{ | 
			
		||||
 | 
				  font-size: 40px; | 
			
		||||
 | 
				  color: red; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
 | 
				``` | 
			
		||||
 | 
				4. 自定义字体图标(无、不建议使用) | 
			
		||||
@ -0,0 +1,11 @@ | 
			
		|||||
 | 
				module.exports = { | 
			
		||||
 | 
				  presets: [['@babel/preset-env', { targets: { node: 'current' }}]], | 
			
		||||
 | 
				  'env': { | 
			
		||||
 | 
				    'development': { | 
			
		||||
 | 
				      // babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
 | 
			
		||||
 | 
				      // This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
 | 
			
		||||
 | 
				      // https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html
 | 
			
		||||
 | 
				      'plugins': ['dynamic-import-node'] | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,18 @@ | 
			
		|||||
 | 
				<!DOCTYPE html> | 
			
		||||
 | 
				<html> | 
			
		||||
 | 
				  <head> | 
			
		||||
 | 
				    <meta charset="utf-8"> | 
			
		||||
 | 
				    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | 
			
		||||
 | 
				    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> | 
			
		||||
 | 
				    <link rel="icon" href="/favicon.ico"> | 
			
		||||
 | 
				    <title>Vue Admin Template</title> | 
			
		||||
 | 
				  </head> | 
			
		||||
 | 
				  <body> | 
			
		||||
 | 
				    <div id="app"></div> | 
			
		||||
 | 
				    <script type="text/javascript" src="/js/jessibuca/jessibuca.js"></script> | 
			
		||||
 | 
				    <script type="text/javascript" src="/js/EasyWasmPlayer.js"></script> | 
			
		||||
 | 
				    <script type="text/javascript" src="/js/ZLMRTCClient.js"></script> | 
			
		||||
 | 
				    <script type="text/javascript" src="/js/mapConfig.js"></script> | 
			
		||||
 | 
				    <script type="module" src="/src/main.js"></script> | 
			
		||||
 | 
				  </body> | 
			
		||||
 | 
				</html> | 
			
		||||
@ -0,0 +1,25 @@ | 
			
		|||||
 | 
				module.exports = { | 
			
		||||
 | 
				  moduleFileExtensions: ['js', 'jsx', 'json', 'vue'], | 
			
		||||
 | 
				  transform: { | 
			
		||||
 | 
				    '^.+\\.vue$': '@vue/vue2-jest', | 
			
		||||
 | 
				    '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': | 
			
		||||
 | 
				      'jest-transform-stub', | 
			
		||||
 | 
				    '^.+\\.jsx?$': 'babel-jest' | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  moduleNameMapper: { | 
			
		||||
 | 
				    '^@/(.*)$': '<rootDir>/src/$1' | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  snapshotSerializers: ['jest-serializer-vue'], | 
			
		||||
 | 
				  testMatch: [ | 
			
		||||
 | 
				    '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)' | 
			
		||||
 | 
				  ], | 
			
		||||
 | 
				  collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'], | 
			
		||||
 | 
				  coverageDirectory: '<rootDir>/tests/unit/coverage', | 
			
		||||
 | 
				  // 'collectCoverage': true,
 | 
			
		||||
 | 
				  'coverageReporters': [ | 
			
		||||
 | 
				    'lcov', | 
			
		||||
 | 
				    'text-summary' | 
			
		||||
 | 
				  ], | 
			
		||||
 | 
				  testURL: 'http://localhost/', | 
			
		||||
 | 
				  testEnvironment: 'jsdom' | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,16 @@ | 
			
		|||||
 | 
				{ | 
			
		||||
 | 
				  "vueCompilerOptions": { | 
			
		||||
 | 
				    "target": 2.7 | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  "compilerOptions": { | 
			
		||||
 | 
				    "target": "esnext", | 
			
		||||
 | 
				    "module": "esnext", | 
			
		||||
 | 
				    "moduleResolution": "node", | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    "baseUrl": "./", | 
			
		||||
 | 
				    "paths": { | 
			
		||||
 | 
				        "@/*": ["src/*"] | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  "exclude": ["node_modules", "dist"] | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,66 @@ | 
			
		|||||
 | 
				{ | 
			
		||||
 | 
				  "name": "vite-admin-template", | 
			
		||||
 | 
				  "version": "1.0.0", | 
			
		||||
 | 
				  "description": "A vite vue admin template with Element UI & axios & iconfont & permission control & lint", | 
			
		||||
 | 
				  "author": "misaka10032@aliyun.com", | 
			
		||||
 | 
				  "scripts": { | 
			
		||||
 | 
				    "dev": "vite", | 
			
		||||
 | 
				    "build": "vite build", | 
			
		||||
 | 
				    "preview": "vite preview", | 
			
		||||
 | 
				    "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml", | 
			
		||||
 | 
				    "lint": "eslint --ext .js,.vue src" | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  "dependencies": { | 
			
		||||
 | 
				    "@logicflow/core": "^1.2.17", | 
			
		||||
 | 
				    "@logicflow/extension": "^1.2.18", | 
			
		||||
 | 
				    "@vueuse/core": "^10.6.1", | 
			
		||||
 | 
				    "axios": "^1.4.0", | 
			
		||||
 | 
				    "core-js": "3.31.0", | 
			
		||||
 | 
				    "dayjs": "^1.11.10", | 
			
		||||
 | 
				    "echarts": "^5.6.0", | 
			
		||||
 | 
				    "element-ui": "2.15.13", | 
			
		||||
 | 
				    "js-base64": "^3.7.5", | 
			
		||||
 | 
				    "lodash-es": "^4.17.21", | 
			
		||||
 | 
				    "normalize.css": "8.0.1", | 
			
		||||
 | 
				    "nprogress": "0.2.0", | 
			
		||||
 | 
				    "path-browserify": "^1.0.1", | 
			
		||||
 | 
				    "path-to-regexp": "6.2.1", | 
			
		||||
 | 
				    "pinia": "^2.1.4", | 
			
		||||
 | 
				    "qs": "^6.11.2", | 
			
		||||
 | 
				    "uuid": "^9.0.0", | 
			
		||||
 | 
				    "vue": "^2.7.14", | 
			
		||||
 | 
				    "vue-color": "^2.8.1", | 
			
		||||
 | 
				    "vue-router": "3.0.6" | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  "devDependencies": { | 
			
		||||
 | 
				    "@babel/core": "^7.22.5", | 
			
		||||
 | 
				    "@babel/eslint-parser": "^7.22.5", | 
			
		||||
 | 
				    "@babel/preset-env": "^7.22.5", | 
			
		||||
 | 
				    "@typescript-eslint/parser": "^5.61.0", | 
			
		||||
 | 
				    "@vitejs/plugin-vue2": "^2.2.0", | 
			
		||||
 | 
				    "@vitejs/plugin-vue2-jsx": "^1.1.0", | 
			
		||||
 | 
				    "autoprefixer": "9.5.1", | 
			
		||||
 | 
				    "babel-plugin-dynamic-import-node": "2.3.3", | 
			
		||||
 | 
				    "eslint": "^8.44.0", | 
			
		||||
 | 
				    "eslint-config-prettier": "^8.8.0", | 
			
		||||
 | 
				    "eslint-plugin-vue": "^9.15.1", | 
			
		||||
 | 
				    "mockjs": "^1.1.0", | 
			
		||||
 | 
				    "sass": "1.63.6", | 
			
		||||
 | 
				    "svgo": "1.2.2", | 
			
		||||
 | 
				    "typescript": "^5.1.6", | 
			
		||||
 | 
				    "vite": "^4.3.9", | 
			
		||||
 | 
				    "vite-plugin-compression": "^0.5.1", | 
			
		||||
 | 
				    "vite-plugin-mock": "^2.9.6", | 
			
		||||
 | 
				    "vite-plugin-svg-icons": "^2.0.1", | 
			
		||||
 | 
				    "vue-template-compiler": "^2.7.14" | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  "browserslist": [ | 
			
		||||
 | 
				    "> 1%", | 
			
		||||
 | 
				    "last 2 versions" | 
			
		||||
 | 
				  ], | 
			
		||||
 | 
				  "engines": { | 
			
		||||
 | 
				    "node": ">=8.9", | 
			
		||||
 | 
				    "npm": ">= 6.0.0" | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  "license": "MIT" | 
			
		||||
 | 
				} | 
			
		||||
| 
		 After Width: | Height: | Size: 78 KiB  | 
| 
		 Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 66 KiB  | 
| 
		 After Width: | Height: | Size: 4.9 KiB  | 
| 
		 After Width: | Height: | Size: 5.4 KiB  | 
| 
		 After Width: | Height: | Size: 5.2 KiB  | 
| 
		 After Width: | Height: | Size: 1.3 KiB  | 
| 
		 After Width: | Height: | Size: 5.4 KiB  | 
| 
		 After Width: | Height: | Size: 5.3 KiB  | 
| 
		 After Width: | Height: | Size: 8.0 KiB  | 
| 
		 After Width: | Height: | Size: 4.8 KiB  | 
| 
		 After Width: | Height: | Size: 7.5 KiB  | 
| 
		 After Width: | Height: | Size: 5.3 KiB  | 
| 
		 After Width: | Height: | Size: 4.3 KiB  | 
| 
		 After Width: | Height: | Size: 4.7 KiB  | 
| 
		 After Width: | Height: | Size: 2.0 KiB  | 
| 
		 After Width: | Height: | Size: 2.0 KiB  | 
| 
		 After Width: | Height: | Size: 142 KiB  | 
@ -0,0 +1,190 @@ | 
			
		|||||
 | 
				<!DOCTYPE html> | 
			
		||||
 | 
				<html lang="en"> | 
			
		||||
 | 
				<head> | 
			
		||||
 | 
				    <meta charset="UTF-8"> | 
			
		||||
 | 
				    <title>Title</title> | 
			
		||||
 | 
				    <script src="./jessibuca.js"></script> | 
			
		||||
 | 
				    <style> | 
			
		||||
 | 
				        .root { | 
			
		||||
 | 
				            display: flex; | 
			
		||||
 | 
				            place-content: center; | 
			
		||||
 | 
				            margin-top: 3rem; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .container-shell { | 
			
		||||
 | 
				            backdrop-filter: blur(5px); | 
			
		||||
 | 
				            background: hsla(0, 0%, 50%, 0.5); | 
			
		||||
 | 
				            padding: 30px 4px 10px 4px; | 
			
		||||
 | 
				            /* border: 2px solid black; */ | 
			
		||||
 | 
				            width: auto; | 
			
		||||
 | 
				            position: relative; | 
			
		||||
 | 
				            border-radius: 5px; | 
			
		||||
 | 
				            box-shadow: 0 10px 20px; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .container-shell:before { | 
			
		||||
 | 
				            content: "jessibuca demo player"; | 
			
		||||
 | 
				            position: absolute; | 
			
		||||
 | 
				            color: darkgray; | 
			
		||||
 | 
				            top: 4px; | 
			
		||||
 | 
				            left: 10px; | 
			
		||||
 | 
				            text-shadow: 1px 1px black; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        #container { | 
			
		||||
 | 
				            background: rgba(13, 14, 27, 0.7); | 
			
		||||
 | 
				            width: 640px; | 
			
		||||
 | 
				            height: 398px; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .input { | 
			
		||||
 | 
				            display: flex; | 
			
		||||
 | 
				            margin-top: 10px; | 
			
		||||
 | 
				            color: white; | 
			
		||||
 | 
				            place-content: stretch; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .input2 { | 
			
		||||
 | 
				            bottom: 0px; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .input input { | 
			
		||||
 | 
				            flex: auto; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .err { | 
			
		||||
 | 
				            position: absolute; | 
			
		||||
 | 
				            top: 40px; | 
			
		||||
 | 
				            left: 10px; | 
			
		||||
 | 
				            color: red; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .option { | 
			
		||||
 | 
				            position: absolute; | 
			
		||||
 | 
				            top: 4px; | 
			
		||||
 | 
				            right: 10px; | 
			
		||||
 | 
				            display: flex; | 
			
		||||
 | 
				            place-content: center; | 
			
		||||
 | 
				            font-size: 12px; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .option span { | 
			
		||||
 | 
				            color: white; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .page { | 
			
		||||
 | 
				            background: url('./bg.jpg'); | 
			
		||||
 | 
				            background-repeat: no-repeat; | 
			
		||||
 | 
				            background-position: top; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        @media (max-width: 720px) { | 
			
		||||
 | 
				            #container { | 
			
		||||
 | 
				                width: 90vw; | 
			
		||||
 | 
				                height: 52.7vw; | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				    </style> | 
			
		||||
 | 
				</head> | 
			
		||||
 | 
				<body class="page"> | 
			
		||||
 | 
				<div class="root"> | 
			
		||||
 | 
				    <div class="container-shell"> | 
			
		||||
 | 
				        <div id="container"></div> | 
			
		||||
 | 
				        <div class="input"> | 
			
		||||
 | 
				            <div>输入URL:</div> | 
			
		||||
 | 
				            <input | 
			
		||||
 | 
				                autocomplete="on" | 
			
		||||
 | 
				                id="playUrl" | 
			
		||||
 | 
				                value="" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				            <button id="play">播放</button> | 
			
		||||
 | 
				            <button id="pause" style="display: none">停止</button> | 
			
		||||
 | 
				        </div> | 
			
		||||
 | 
				        <div class="input" style="line-height: 30px"> | 
			
		||||
 | 
				            <button id="destroy">销毁</button> | 
			
		||||
 | 
				        </div> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				</div> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				    var $player = document.getElementById('play'); | 
			
		||||
 | 
				    var $pause = document.getElementById('pause'); | 
			
		||||
 | 
				    var $playHref = document.getElementById('playUrl'); | 
			
		||||
 | 
				    var $container = document.getElementById('container'); | 
			
		||||
 | 
				    var $destroy = document.getElementById('destroy'); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    var showOperateBtns = false; // 是否显示按钮 | 
			
		||||
 | 
				    var forceNoOffscreen = true; // | 
			
		||||
 | 
				    var jessibuca = null; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    function create() { | 
			
		||||
 | 
				        jessibuca = null; | 
			
		||||
 | 
				        jessibuca = new Jessibuca({ | 
			
		||||
 | 
				            container: $container, | 
			
		||||
 | 
				            videoBuffer: 0.2, // 缓存时长 | 
			
		||||
 | 
				            isResize: false, | 
			
		||||
 | 
				            text: "", | 
			
		||||
 | 
				            loadingText: "", | 
			
		||||
 | 
				            useMSE: false, | 
			
		||||
 | 
				            debug: true, | 
			
		||||
 | 
				            showBandwidth: showOperateBtns, // 显示网速 | 
			
		||||
 | 
				            operateBtns: { | 
			
		||||
 | 
				                fullscreen: showOperateBtns, | 
			
		||||
 | 
				                screenshot: showOperateBtns, | 
			
		||||
 | 
				                play: showOperateBtns, | 
			
		||||
 | 
				                audio: false, | 
			
		||||
 | 
				                recorder: false | 
			
		||||
 | 
				            }, | 
			
		||||
 | 
				            forceNoOffscreen: forceNoOffscreen, | 
			
		||||
 | 
				            isNotMute: false, | 
			
		||||
 | 
				        },); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        jessibuca.on('audioInfo', function (audioInfo) { | 
			
		||||
 | 
				            console.log('audioInfo',audioInfo); | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        jessibuca.on('videoInfo', function (videoInfo) { | 
			
		||||
 | 
				            console.log('videoInfo',videoInfo); | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        $player.style.display = 'inline-block'; | 
			
		||||
 | 
				        $pause.style.display = 'none'; | 
			
		||||
 | 
				        $destroy.style.display = 'none'; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    create(); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    $player.addEventListener('click', function () { | 
			
		||||
 | 
				        var href = $playHref.value; | 
			
		||||
 | 
				        if (href) { | 
			
		||||
 | 
				            jessibuca.play(href); | 
			
		||||
 | 
				            $player.style.display = 'none'; | 
			
		||||
 | 
				            $pause.style.display = 'inline-block'; | 
			
		||||
 | 
				            $destroy.style.display = 'inline-block'; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				    }, false) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    $pause.addEventListener('click', function () { | 
			
		||||
 | 
				        $player.style.display = 'inline-block'; | 
			
		||||
 | 
				        $pause.style.display = 'none'; | 
			
		||||
 | 
				        jessibuca.pause(); | 
			
		||||
 | 
				    }) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    $destroy.addEventListener('click', function () { | 
			
		||||
 | 
				        if (jessibuca) { | 
			
		||||
 | 
				            jessibuca.destroy().then(()=>{ | 
			
		||||
 | 
				                create(); | 
			
		||||
 | 
				            }); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        else { | 
			
		||||
 | 
				            create(); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				    }) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				</body> | 
			
		||||
 | 
				</html> | 
			
		||||
 | 
				
 | 
			
		||||
@ -0,0 +1,637 @@ | 
			
		|||||
 | 
				declare namespace Jessibuca { | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** 超时信息 */ | 
			
		||||
 | 
				    enum TIMEOUT { | 
			
		||||
 | 
				        /** 当play()的时候,如果没有数据返回 */ | 
			
		||||
 | 
				        loadingTimeout = 'loadingTimeout', | 
			
		||||
 | 
				        /** 当播放过程中,如果超过timeout之后没有数据渲染 */ | 
			
		||||
 | 
				        delayTimeout = 'delayTimeout', | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** 错误信息 */ | 
			
		||||
 | 
				    enum ERROR { | 
			
		||||
 | 
				        /** 播放错误,url 为空的时候,调用 play 方法 */ | 
			
		||||
 | 
				        playError = 'playError', | 
			
		||||
 | 
				        /** http 请求失败 */ | 
			
		||||
 | 
				        fetchError = 'fetchError', | 
			
		||||
 | 
				        /** websocket 请求失败 */ | 
			
		||||
 | 
				        websocketError = 'websocketError', | 
			
		||||
 | 
				        /** webcodecs 解码 h265 失败 */ | 
			
		||||
 | 
				        webcodecsH265NotSupport = 'webcodecsH265NotSupport', | 
			
		||||
 | 
				        /** mediaSource 解码 h265 失败 */ | 
			
		||||
 | 
				        mediaSourceH265NotSupport = 'mediaSourceH265NotSupport', | 
			
		||||
 | 
				        /** wasm 解码失败 */ | 
			
		||||
 | 
				        wasmDecodeError = 'wasmDecodeError', | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    interface Config { | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 播放器容器 | 
			
		||||
 | 
				         * *  若为 string ,则底层调用的是 document.getElementById('id') | 
			
		||||
 | 
				         * */ | 
			
		||||
 | 
				        container: HTMLElement | string; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 设置最大缓冲时长,单位秒,播放器会自动消除延迟 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        videoBuffer?: number; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * worker地址 | 
			
		||||
 | 
				         * *  默认引用的是根目录下面的decoder.js文件 ,decoder.js 与 decoder.wasm文件必须是放在同一个目录下面。 */ | 
			
		||||
 | 
				        decoder?: string; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 是否不使用离屏模式(提升渲染能力) | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        forceNoOffscreen?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 是否开启当页面的'visibilityState'变为'hidden'的时候,自动暂停播放。 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        hiddenAutoPause?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 是否有音频,如果设置`false`,则不对音频数据解码,提升性能。 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        hasAudio?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 设置旋转角度,只支持,0(默认),180,270 三个值 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        rotate?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 1. 当为`true`的时候:视频画面做等比缩放后,高或宽对齐canvas区域,画面不被拉伸,但有黑边。 等同于 `setScaleMode(1)` | 
			
		||||
 | 
				         * 2. 当为`false`的时候:视频画面完全填充canvas区域,画面会被拉伸。等同于 `setScaleMode(0)` | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        isResize?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 1. 当为`true`的时候:视频画面做等比缩放后,完全填充canvas区域,画面不被拉伸,没有黑边,但画面显示不全。等同于 `setScaleMode(2)` | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        isFullResize?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 1. 当为`true`的时候:ws协议不检验是否以.flv为依据,进行协议解析。 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        isFlv?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 是否开启控制台调试打 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        debug?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 1. 设置超时时长, 单位秒 | 
			
		||||
 | 
				         * 2. 在连接成功之前(loading)和播放中途(heart),如果超过设定时长无数据返回,则回调timeout事件 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        timeout?: number; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 1. 设置超时时长, 单位秒 | 
			
		||||
 | 
				         * 2. 在连接成功之前,如果超过设定时长无数据返回,则回调timeout事件 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        heartTimeout?: number; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 1. 设置超时时长, 单位秒 | 
			
		||||
 | 
				         * 2. 在连接成功之前,如果超过设定时长无数据返回,则回调timeout事件 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        loadingTimeout?: number; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 是否支持屏幕的双击事件,触发全屏,取消全屏事件 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        supportDblclickFullscreen?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 是否显示网 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        showBandwidth?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 配置操作按钮 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        operateBtns?: { | 
			
		||||
 | 
				            /** 是否显示全屏按钮 */ | 
			
		||||
 | 
				            fullscreen?: boolean; | 
			
		||||
 | 
				            /** 是否显示截图按钮 */ | 
			
		||||
 | 
				            screenshot?: boolean; | 
			
		||||
 | 
				            /** 是否显示播放暂停按钮 */ | 
			
		||||
 | 
				            play?: boolean; | 
			
		||||
 | 
				            /** 是否显示声音按钮 */ | 
			
		||||
 | 
				            audio?: boolean; | 
			
		||||
 | 
				            /** 是否显示录制按 */ | 
			
		||||
 | 
				            record?: boolean; | 
			
		||||
 | 
				        }; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 开启屏幕常亮,在手机浏览器上, canvas标签渲染视频并不会像video标签那样保持屏幕常亮 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        keepScreenOn?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 是否开启声音,默认是关闭声音播放的 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        isNotMute?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 加载过程中文案 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        loadingText?: string; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 背景图片 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        background?: string; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 是否开启MediaSource硬解码 | 
			
		||||
 | 
				         * * 视频编码只支持H.264视频(Safari on iOS不支持) | 
			
		||||
 | 
				         * * 不支持 forceNoOffscreen 为 false (开启离屏渲染) | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        useMSE?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 是否开启Webcodecs硬解码 | 
			
		||||
 | 
				         * *  视频编码只支持H.264视频 (需在chrome 94版本以上,需要https或者localhost环境) | 
			
		||||
 | 
				         * *  支持 forceNoOffscreen 为 false (开启离屏渲染) | 
			
		||||
 | 
				         * */ | 
			
		||||
 | 
				        useWCS?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * 是否开启键盘快捷键 | 
			
		||||
 | 
				         * 目前支持的键盘快捷键有:esc -> 退出全屏;arrowUp -> 声音增加;arrowDown -> 声音减少; | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        hotKey?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         *  在使用MSE或者Webcodecs 播放H265的时候,是否自动降级到wasm模式。 | 
			
		||||
 | 
				         *  设置为false 则直接关闭播放,抛出Error 异常,设置为true 则会自动切换成wasm模式播放。 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        autoWasm?: boolean; | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * heartTimeout 心跳超时之后自动再播放,不再抛出异常,而直接重新播放视频地址。 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        heartTimeoutReplay?: boolean, | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * heartTimeoutReplay 从试次数,超过之后,不再自动播放 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        heartTimeoutReplayTimes?: number, | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * loadingTimeout loading之后自动再播放,不再抛出异常,而直接重新播放视频地址。 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        loadingTimeoutReplay?: boolean, | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * heartTimeoutReplay 从试次数,超过之后,不再自动播放 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        loadingTimeoutReplayTimes?: number | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * wasm解码报错之后,不再抛出异常,而是直接重新播放视频地址。 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        wasmDecodeErrorReplay?: boolean, | 
			
		||||
 | 
				        /** | 
			
		||||
 | 
				         * https://github.com/langhuihui/jessibuca/issues/152 解决方案
 | 
			
		||||
 | 
				         * 例如:WebGL图像预处理默认每次取4字节的数据,但是540x960分辨率下的U、V分量宽度是540/2=270不能被4整除,导致绿屏。 | 
			
		||||
 | 
				         */ | 
			
		||||
 | 
				        openWebglAlignment?: boolean | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				declare class Jessibuca { | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    constructor(config?: Jessibuca.Config); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 是否开启控制台调试打印 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     // 开启
 | 
			
		||||
 | 
				     jessibuca.setDebug(true) | 
			
		||||
 | 
				     // 关闭
 | 
			
		||||
 | 
				     jessibuca.setDebug(false) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    setDebug(flag: boolean): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 静音 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     jessibuca.mute() | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    mute(): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 取消静音 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     jessibuca.cancelMute() | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    cancelMute(): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 留给上层用户操作来触发音频恢复的方法。 | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * iPhone,chrome等要求自动播放时,音频必须静音,需要由一个真实的用户交互操作来恢复,不能使用代码。 | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
 | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    audioResume(): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * 设置超时时长, 单位秒 | 
			
		||||
 | 
				     * 在连接成功之前和播放中途,如果超过设定时长无数据返回,则回调timeout事件 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     jessibuca.setTimeout(10) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     jessibuca.on('timeout',function(){ | 
			
		||||
 | 
				        //
 | 
			
		||||
 | 
				    }); | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    setTimeout(): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * @param mode | 
			
		||||
 | 
				     *      0 视频画面完全填充canvas区域,画面会被拉伸  等同于参数 `isResize` 为false | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     *      1 视频画面做等比缩放后,高或宽对齐canvas区域,画面不被拉伸,但有黑边 等同于参数 `isResize` 为true | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     *      2 视频画面做等比缩放后,完全填充canvas区域,画面不被拉伸,没有黑边,但画面显示不全 等同于参数 `isFullResize` 为true | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     jessibuca.setScaleMode(0) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     jessibuca.setScaleMode(1) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     jessibuca.setScaleMode(2) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    setScaleMode(mode: number): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 暂停播放 | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * 可以在pause 之后,再调用 `play()`方法就继续播放之前的流。 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     jessibuca.pause().then(()=>{ | 
			
		||||
 | 
				        console.log('pause success') | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        jessibuca.play().then(()=>{ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        }).catch((e)=>{ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    }).catch((e)=>{ | 
			
		||||
 | 
				        console.log('pause error',e); | 
			
		||||
 | 
				    }) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    pause(): Promise<void>; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 关闭视频,不释放底层资源 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     jessibuca.close(); | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    close(): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 关闭视频,释放底层资源 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     jessibuca.destroy() | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    destroy(): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 清理画布为黑色背景 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     jessibuca.clearView() | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    clearView(): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 播放视频 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     jessibuca.play('url').then(()=>{ | 
			
		||||
 | 
				        console.log('play success') | 
			
		||||
 | 
				    }).catch((e)=>{ | 
			
		||||
 | 
				        console.log('play error',e) | 
			
		||||
 | 
				    }) | 
			
		||||
 | 
				     //
 | 
			
		||||
 | 
				     jessibuca.play() | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    play(url?: string): Promise<void>; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 重新调整视图大小 | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    resize(): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 设置最大缓冲时长,单位秒,播放器会自动消除延迟。 | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * 等同于 `videoBuffer` 参数。 | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     // 设置 200ms 缓冲
 | 
			
		||||
 | 
				     jessibuca.setBufferTime(0.2) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    setBufferTime(time: number): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 设置旋转角度,只支持,0(默认) ,180,270 三个值。 | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * > 可用于实现监控画面小窗和全屏效果,由于iOS没有全屏API,此方法可以模拟页面内全屏效果而且多端效果一致。   * | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     jessibuca.setRotate(0) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     jessibuca.setRotate(90) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     jessibuca.setRotate(270) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    setRotate(deg: number): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * 设置音量大小,取值0 — 1 | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * > 区别于 mute 和 cancelMute 方法,虽然设置setVolume(0) 也能达到 mute方法,但是mute 方法是不调用底层播放音频的,能提高性能。而setVolume(0)只是把声音设置为0 ,以达到效果。 | 
			
		||||
 | 
				     * @param volume 当为0时,完全无声;当为1时,最大音量,默认值 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     jessibuca.setVolume(0.2) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     jessibuca.setVolume(0) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     jessibuca.setVolume(1) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    setVolume(volume: number): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 返回是否加载完毕 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     var result = jessibuca.hasLoaded() | 
			
		||||
 | 
				     console.log(result) // true
 | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    hasLoaded(): boolean; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 开启屏幕常亮,在手机浏览器上, canvas标签渲染视频并不会像video标签那样保持屏幕常亮。 | 
			
		||||
 | 
				     * H5目前在chrome\edge 84, android chrome 84及以上有原生亮屏API, 需要是https页面 | 
			
		||||
 | 
				     * 其余平台为模拟实现,此时为兼容实现,并不保证所有浏览器都支持 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     jessibuca.setKeepScreenOn() | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    setKeepScreenOn(): boolean; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 全屏(取消全屏)播放视频 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     jessibuca.setFullscreen(true) | 
			
		||||
 | 
				     //
 | 
			
		||||
 | 
				     jessibuca.setFullscreen(false) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    setFullscreen(flag: boolean): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * 截图,调用后弹出下载框保存截图 | 
			
		||||
 | 
				     * @param filename 可选参数, 保存的文件名, 默认 `时间戳` | 
			
		||||
 | 
				     * @param format   可选参数, 截图的格式,可选png或jpeg或者webp ,默认 `png` | 
			
		||||
 | 
				     * @param quality  可选参数, 当格式是jpeg或者webp时,压缩质量,取值0 ~ 1 ,默认 `0.92` | 
			
		||||
 | 
				     * @param type 可选参数, 可选download或者base64或者blob,默认`download` | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     jessibuca.screenshot("test","png",0.5) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     const base64 = jessibuca.screenshot("test","png",0.5,'base64') | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     const fileBlob = jessibuca.screenshot("test",'blob') | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    screenshot(filename?: string, format?: string, quality?: number, type?: string): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 开始录制。 | 
			
		||||
 | 
				     * @param fileName 可选,默认时间戳 | 
			
		||||
 | 
				     * @param fileType 可选,默认webm,支持webm 和mp4 格式 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     jessibuca.startRecord('xxx','webm') | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    startRecord(fileName: string, fileType: string): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 暂停录制并下载。 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     jessibuca.stopRecordAndSave() | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    stopRecordAndSave(): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 返回是否正在播放中状态。 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     var result = jessibuca.isPlaying() | 
			
		||||
 | 
				     console.log(result) // true
 | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    isPlaying(): boolean; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     *   返回是否静音。 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     var result = jessibuca.isMute() | 
			
		||||
 | 
				     console.log(result) // true
 | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    isMute(): boolean; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 返回是否正在录制。 | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				     var result = jessibuca.isRecording() | 
			
		||||
 | 
				     console.log(result) // true
 | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    isRecording(): boolean; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 监听 jessibuca 初始化事件 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("load",function(){console.log('load')}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'load', callback: () => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 视频播放持续时间,单位ms | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on('timeUpdate',function (ts) {console.log('timeUpdate',ts);}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'timeUpdate', callback: () => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 当解析出视频信息时回调,2个回调参数 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("videoInfo",function(data){console.log('width:',data.width,'height:',data.width)}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'videoInfo', callback: (data: { | 
			
		||||
 | 
				        /** 视频宽 */ | 
			
		||||
 | 
				        width: number; | 
			
		||||
 | 
				        /** 视频高 */ | 
			
		||||
 | 
				        height: number; | 
			
		||||
 | 
				    }) => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 当解析出音频信息时回调,2个回调参数 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("audioInfo",function(data){console.log('numOfChannels:',data.numOfChannels,'sampleRate',data.sampleRate)}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'audioInfo', callback: (data: { | 
			
		||||
 | 
				        /** 声频通道 */ | 
			
		||||
 | 
				        numOfChannels: number; | 
			
		||||
 | 
				        /** 采样率 */ | 
			
		||||
 | 
				        sampleRate: number; | 
			
		||||
 | 
				    }) => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 信息,包含错误信息 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("log",function(data){console.log('data:',data)}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'log', callback: () => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 错误信息 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("error",function(error){ | 
			
		||||
 | 
				        if(error === Jessibuca.ERROR.fetchError){ | 
			
		||||
 | 
				            //
 | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        else if(error === Jessibuca.ERROR.webcodecsH265NotSupport){ | 
			
		||||
 | 
				            //
 | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        console.log('error:',error) | 
			
		||||
 | 
				    }) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'error', callback: (err: Jessibuca.ERROR) => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 当前网速, 单位KB 每秒1次, | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("kBps",function(data){console.log('kBps:',data)}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'kBps', callback: (value: number) => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 渲染开始 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("start",function(){console.log('start render')}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'start', callback: () => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 当设定的超时时间内无数据返回,则回调 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("timeout",function(error){console.log('timeout:',error)}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'timeout', callback: (error: Jessibuca.TIMEOUT) => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 当play()的时候,如果没有数据返回,则回调 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("loadingTimeout",function(){console.log('timeout')}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'loadingTimeout', callback: () => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 当播放过程中,如果超过timeout之后没有数据渲染,则抛出异常。 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("delayTimeout",function(){console.log('timeout')}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'delayTimeout', callback: () => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 当前是否全屏 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("fullscreen",function(flag){console.log('is fullscreen',flag)}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'fullscreen', callback: () => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 触发播放事件 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("play",function(flag){console.log('play')}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'play', callback: () => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 触发暂停事件 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("pause",function(flag){console.log('pause')}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'pause', callback: () => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 触发声音事件,返回boolean值 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("mute",function(flag){console.log('is mute',flag)}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'mute', callback: () => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 流状态统计,流开始播放后回调,每秒1次。 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("stats",function(s){console.log("stats is",s)}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'stats', callback: (stats: { | 
			
		||||
 | 
				        /** 当前缓冲区时长,单位毫秒 */ | 
			
		||||
 | 
				        buf: number; | 
			
		||||
 | 
				        /** 当前视频帧率 */ | 
			
		||||
 | 
				        fps: number; | 
			
		||||
 | 
				        /** 当前音频码率,单位byte */ | 
			
		||||
 | 
				        abps: number; | 
			
		||||
 | 
				        /** 当前视频码率,单位byte */ | 
			
		||||
 | 
				        vbps: number; | 
			
		||||
 | 
				        /** 当前视频帧pts,单位毫秒 */ | 
			
		||||
 | 
				        ts: number; | 
			
		||||
 | 
				    }) => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 渲染性能统计,流开始播放后回调,每秒1次。 | 
			
		||||
 | 
				     * @param performance 0: 表示卡顿,1: 表示流畅,2: 表示非常流程 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("performance",function(performance){console.log("performance is",performance)}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'performance', callback: (performance: 0 | 1 | 2) => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 录制开始的事件 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("recordStart",function(){console.log("record start")}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'recordStart', callback: () => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 录制结束的事件 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("recordEnd",function(){console.log("record end")}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'recordEnd', callback: () => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 录制的时候,返回的录制时长,1s一次 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     * @example | 
			
		||||
 | 
				     * jessibuca.on("recordingTimestamp",function(timestamp){console.log("recordingTimestamp is",timestamp)}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'recordingTimestamp', callback: (timestamp: number) => void): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 监听调用play方法 经过 初始化-> 网络请求-> 解封装 -> 解码 -> 渲染 一系列过程的时间消耗 | 
			
		||||
 | 
				     * @param event | 
			
		||||
 | 
				     * @param callback | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: 'playToRenderTimes', callback: (times: { | 
			
		||||
 | 
				        playInitStart: number, // 1 初始化
 | 
			
		||||
 | 
				        playStart: number, // 2 初始化
 | 
			
		||||
 | 
				        streamStart: number, // 3 网络请求
 | 
			
		||||
 | 
				        streamResponse: number, // 4 网络请求
 | 
			
		||||
 | 
				        demuxStart: number, // 5 解封装
 | 
			
		||||
 | 
				        decodeStart: number, // 6 解码
 | 
			
		||||
 | 
				        videoStart: number, // 7 渲染
 | 
			
		||||
 | 
				        playTimestamp: number,// playStart- playInitStart
 | 
			
		||||
 | 
				        streamTimestamp: number,// streamStart - playStart
 | 
			
		||||
 | 
				        streamResponseTimestamp: number,// streamResponse - streamStart
 | 
			
		||||
 | 
				        demuxTimestamp: number, // demuxStart - streamResponse
 | 
			
		||||
 | 
				        decodeTimestamp: number, // decodeStart - demuxStart
 | 
			
		||||
 | 
				        videoTimestamp: number,// videoStart - decodeStart
 | 
			
		||||
 | 
				        allTimestamp: number // videoStart - playInitStart
 | 
			
		||||
 | 
				    }) => void): void | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 监听方法 | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     @example | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				     jessibuca.on("load",function(){console.log('load')}) | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    on(event: string, callback: Function): void; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export default Jessibuca; | 
			
		||||
@ -0,0 +1,19 @@ | 
			
		|||||
 | 
				// map组件全局参数, 注释此内容可以关闭地图功能
 | 
			
		||||
 | 
				window.mapParam = { | 
			
		||||
 | 
				  // 开启/关闭地图功能
 | 
			
		||||
 | 
				  enable: true, | 
			
		||||
 | 
				  // 坐标系 GCJ-02 WGS-84,
 | 
			
		||||
 | 
				  coordinateSystem: "GCJ-02", | 
			
		||||
 | 
				  // 地图瓦片地址
 | 
			
		||||
 | 
				  tilesUrl: "http://webrd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8", | 
			
		||||
 | 
				  // 瓦片大小
 | 
			
		||||
 | 
				  tileSize: 256, | 
			
		||||
 | 
				  // 默认层级
 | 
			
		||||
 | 
				  zoom:10, | 
			
		||||
 | 
				  // 默认地图中心点
 | 
			
		||||
 | 
				  center:[116.41020, 39.915119], | 
			
		||||
 | 
				  // 地图最大层级
 | 
			
		||||
 | 
				  maxZoom:18, | 
			
		||||
 | 
				  // 地图最小层级
 | 
			
		||||
 | 
				  minZoom: 3 | 
			
		||||
 | 
				} | 
			
		||||
| 
		 After Width: | Height: | Size: 6.2 KiB  | 
@ -0,0 +1,11 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <div id="app"> | 
			
		||||
 | 
				    <router-view /> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  name: 'App' | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,64 @@ | 
			
		|||||
 | 
				import request from '@/utils/request' | 
			
		||||
 | 
				export function getDictList(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/dict/list', | 
			
		||||
 | 
				    method: 'get', | 
			
		||||
 | 
				    params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				export function getDictInfoList(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/dictItem/list', | 
			
		||||
 | 
				    method: 'get', | 
			
		||||
 | 
				    params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				export function addDict(data) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/dict/add', | 
			
		||||
 | 
				    method: 'post', | 
			
		||||
 | 
				    data | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				export function deleteDict(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/dict/delete', | 
			
		||||
 | 
				    method: 'delete', | 
			
		||||
 | 
				    params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				export function deleteDictItem(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/dictItem/delete', | 
			
		||||
 | 
				    method: 'delete', | 
			
		||||
 | 
				    params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				export function editDict(data) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/dict/edit', | 
			
		||||
 | 
				    method: 'put', | 
			
		||||
 | 
				    data | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				export function changeStatus(data) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/dictItem/status', | 
			
		||||
 | 
				    method: 'put', | 
			
		||||
 | 
				    data | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				export function addDictItem(data) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/dictItem/add', | 
			
		||||
 | 
				    method: 'post', | 
			
		||||
 | 
				    data | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				export function editDictItem(data) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/dictItem/edit', | 
			
		||||
 | 
				    method: 'put', | 
			
		||||
 | 
				    data | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,122 @@ | 
			
		|||||
 | 
				import request from '@/utils/request' | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export function fetchRoleList(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/role/list', | 
			
		||||
 | 
				    method: 'get', | 
			
		||||
 | 
				    params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export function addRole(data) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/role/add', | 
			
		||||
 | 
				    method: 'post', | 
			
		||||
 | 
				    data | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export function editRole(data) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/role/edit', | 
			
		||||
 | 
				    method: 'put', | 
			
		||||
 | 
				    data | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				export function batchDeleteRoles(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/role/deleteBatch', | 
			
		||||
 | 
				    method: 'delete', | 
			
		||||
 | 
				    params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				export function deleteRole(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/role/delete', | 
			
		||||
 | 
				    method: 'delete', | 
			
		||||
 | 
				    params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				export function getRolePermission(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/permission/queryRolePermission', | 
			
		||||
 | 
				    method: 'get', | 
			
		||||
 | 
				    params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				/** | 
			
		||||
 | 
				 * @description 修改用户权限 | 
			
		||||
 | 
				 * @param {Object} data | 
			
		||||
 | 
				 * @param {String} data.lastpermissionIds 上次permission | 
			
		||||
 | 
				 * @param {String} data.permissionIds 本次permission | 
			
		||||
 | 
				 * @param {String} data.roleId | 
			
		||||
 | 
				 * @returns | 
			
		||||
 | 
				 */ | 
			
		||||
 | 
				export function editRolePermission(data) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/permission/saveRolePermission', | 
			
		||||
 | 
				    method: 'post', | 
			
		||||
 | 
				    data | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				export function getMenuList() { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/permission/list', | 
			
		||||
 | 
				    method: 'get', | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				/** | 
			
		||||
 | 
				 * @description 获取是否拥有该权限的用户 | 
			
		||||
 | 
				 * @param {Object} params | 
			
		||||
 | 
				 * @param {String} params.roleId 角色id | 
			
		||||
 | 
				 * @param {boolean} params.selected 是否拥有该角色 | 
			
		||||
 | 
				 * @param {String} params.key 查询关键字 | 
			
		||||
 | 
				 * @param {String} params.pageNo | 
			
		||||
 | 
				 * @param {String} params.pageSize | 
			
		||||
 | 
				 * @returns | 
			
		||||
 | 
				 */ | 
			
		||||
 | 
				export function getPermissionUsers(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/userRole/list', | 
			
		||||
 | 
				    method: 'get', | 
			
		||||
 | 
				    params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				/** | 
			
		||||
 | 
				 * @description 添加拥有该权限的用户 | 
			
		||||
 | 
				 * @param {Array<{userId:String,roleId:String}>} data [{userId,userId}] | 
			
		||||
 | 
				 * @returns | 
			
		||||
 | 
				 */ | 
			
		||||
 | 
				export function addPermissionUsers(data) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/userRole/add', | 
			
		||||
 | 
				    method: 'post', | 
			
		||||
 | 
				    data | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				/** | 
			
		||||
 | 
				 * @description 批量删除拥有该权限的用户 | 
			
		||||
 | 
				 * @param {Array<{userId:String,roleId:String}>} data [{userId,userId}] | 
			
		||||
 | 
				 * @returns | 
			
		||||
 | 
				 */ | 
			
		||||
 | 
				export function BatchDeletePermissionUsers(data) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/userRole/deleteBatch', | 
			
		||||
 | 
				    method: 'post', | 
			
		||||
 | 
				    data | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				/** | 
			
		||||
 | 
				 * @description 删除拥有该权限的用户 | 
			
		||||
 | 
				 * @param {Object}  params | 
			
		||||
 | 
				 * @param {String}  params.userId | 
			
		||||
 | 
				 * @param {String}  params.roleId | 
			
		||||
 | 
				 * @returns | 
			
		||||
 | 
				 */ | 
			
		||||
 | 
				export function deletePermissionUsers(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: 'sys/userRole/delete', | 
			
		||||
 | 
				    method: 'delete', | 
			
		||||
 | 
				    params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,62 @@ | 
			
		|||||
 | 
				import request from '@/utils/request' | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export function fetchUserList(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/user/list', | 
			
		||||
 | 
				    method: 'get', | 
			
		||||
 | 
				    params: params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export function addUser(data) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/user/add', | 
			
		||||
 | 
				    method: 'post', | 
			
		||||
 | 
				    data: data | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export function editUser(data) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/user/edit', | 
			
		||||
 | 
				    method: 'put', | 
			
		||||
 | 
				    data: data | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				export function deleteBatchUsers(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/user/deleteBatch', | 
			
		||||
 | 
				    method: 'delete', | 
			
		||||
 | 
				    params: params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				export function deleteUser(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/user/delete', | 
			
		||||
 | 
				    method: 'delete', | 
			
		||||
 | 
				    params: params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				/** | 
			
		||||
 | 
				 * @description 修改角色权限 | 
			
		||||
 | 
				 * @param {Object} params {userId:String,selectedRoles:String} | 
			
		||||
 | 
				 * @param {String} params.userId | 
			
		||||
 | 
				 * @param {String} params.selectedRoles | 
			
		||||
 | 
				 * @returns | 
			
		||||
 | 
				 */ | 
			
		||||
 | 
				export function editUserRoles(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/sys/user/setUserRoles', | 
			
		||||
 | 
				    method: 'put', | 
			
		||||
 | 
				    params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export function changePassword(data) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: 'sys/user/changePassword', | 
			
		||||
 | 
				    method: 'put', | 
			
		||||
 | 
				    data: data | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
@ -0,0 +1,112 @@ | 
			
		|||||
 | 
				import request from "@/utils/request"; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				//获取所有通道列表
 | 
			
		||||
 | 
				export function getAllChannel() { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/nvr/channel/list', | 
			
		||||
 | 
				    method: 'get', | 
			
		||||
 | 
				    params: { | 
			
		||||
 | 
				      pageSize: 99999, | 
			
		||||
 | 
				      pageNo: 1 | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				//根据取通道列表
 | 
			
		||||
 | 
				/** | 
			
		||||
 | 
				 * | 
			
		||||
 | 
				 * @param {*} params | 
			
		||||
 | 
				 * @param {String} params.siteId 区域 | 
			
		||||
 | 
				 * @param {String} params.equipmentId  主机 | 
			
		||||
 | 
				 * @param {String} params.name 名称 | 
			
		||||
 | 
				 * @param {String} params.pageNo 页码 | 
			
		||||
 | 
				 * @param {String} params.pageSize 页大小 | 
			
		||||
 | 
				 * @returns | 
			
		||||
 | 
				 */ | 
			
		||||
 | 
				export function getChannel(params) { | 
			
		||||
 | 
				  // 区域 主机 名称
 | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/nvr/channel/list', | 
			
		||||
 | 
				    method: 'get', | 
			
		||||
 | 
				    params: params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				/** | 
			
		||||
 | 
				 * | 
			
		||||
 | 
				 * @param {*} params | 
			
		||||
 | 
				 * @param {String} params.siteId 区域 | 
			
		||||
 | 
				 */ | 
			
		||||
 | 
				// 根据区域获取巡航列表
 | 
			
		||||
 | 
				export function getCruiseList(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/nvr/cruise/list', | 
			
		||||
 | 
				    method: 'get', | 
			
		||||
 | 
				    params: params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				// 获取巡航映射
 | 
			
		||||
 | 
				export function getCruiseMap(params) { | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/nvr/cruise/presetList', | 
			
		||||
 | 
				    method: 'get', | 
			
		||||
 | 
				    params: params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				// 通道云台控制
 | 
			
		||||
 | 
				/** | 
			
		||||
 | 
				 * @param {String} params.cameraIp ip | 
			
		||||
 | 
				 * @param {String} params.speed 速度 | 
			
		||||
 | 
				 * @param {String} params.direction 方向 | 
			
		||||
 | 
				*/ | 
			
		||||
 | 
				export function setChannelPTZ(params) { | 
			
		||||
 | 
				  // 原有系统的云台控制
 | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/nvr/cruise/movePTZ', | 
			
		||||
 | 
				    method: 'get', | 
			
		||||
 | 
				    params: params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				// 通道预置位控制
 | 
			
		||||
 | 
				/** | 
			
		||||
 | 
				 * @param {String} params.cameraIp ip | 
			
		||||
 | 
				 * @param {String} params.preset 预置位 | 
			
		||||
 | 
				*/ | 
			
		||||
 | 
				export function setChannelPreset(params) { | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  // 原有系统的预置位控制
 | 
			
		||||
 | 
				  return request({ | 
			
		||||
 | 
				    url: '/nvr/cruise/movePreset', | 
			
		||||
 | 
				    method: 'get', | 
			
		||||
 | 
				    params: params | 
			
		||||
 | 
				  }) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export function setZoom({ | 
			
		||||
 | 
				  ip, command, deviceType, deviceSerial, accessToken, channelNo | 
			
		||||
 | 
				}) { | 
			
		||||
 | 
				  let cmd; | 
			
		||||
 | 
				  // 原有系统的缩放控制
 | 
			
		||||
 | 
				  if (command > 0) { | 
			
		||||
 | 
				    cmd = 'zoomin'; | 
			
		||||
 | 
				  } else if (command < 0) { | 
			
		||||
 | 
				    cmd = 'zoomout'; | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				  command = Math.abs(command); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  // 发送command秒命令
 | 
			
		||||
 | 
				  return new Promise((res, rej) => { | 
			
		||||
 | 
				    return setChannelPTZ({ cameraIp: ip, command: cmd }).then(() => { | 
			
		||||
 | 
				      setTimeout(() => { | 
			
		||||
 | 
				        setChannelPTZ({ | 
			
		||||
 | 
				          cameraIp: ip, | 
			
		||||
 | 
				          command: 'stop' | 
			
		||||
 | 
				        }).then(() => { | 
			
		||||
 | 
				          res(); | 
			
		||||
 | 
				        }).catch((err) => { | 
			
		||||
 | 
				          rej(err); | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      }, command * 1000); | 
			
		||||
 | 
				    }); | 
			
		||||
 | 
				  }); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,87 @@ | 
			
		|||||
 | 
				class WvpService { | 
			
		||||
 | 
				  constructor() { | 
			
		||||
 | 
				    this.baseURL = import.meta.env.VITE_APP_WVP_API; | 
			
		||||
 | 
				    this.token = ''; | 
			
		||||
 | 
				    this.login() | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  login() { | 
			
		||||
 | 
				    return fetch(`${this.baseURL}/api/user/login?username=admin&password=21232f297a57a5a743894a0e4a801fc3`) | 
			
		||||
 | 
				      .then(response => response.json()) | 
			
		||||
 | 
				      .then(({ data }) => { | 
			
		||||
 | 
				        this.token = data.accessToken; | 
			
		||||
 | 
				      }) | 
			
		||||
 | 
				      .catch(error => { | 
			
		||||
 | 
				        console.error('Error:', error); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  async deviceList() { | 
			
		||||
 | 
				    if (!this.token) { | 
			
		||||
 | 
				      await this.login(); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				    return fetch(`${this.baseURL}/api/device/query/devices?page=1&count=100`, { | 
			
		||||
 | 
				      headers: { | 
			
		||||
 | 
				        'Access-Token': `${this.token}` | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }) | 
			
		||||
 | 
				      .then(response => response.json()) | 
			
		||||
 | 
				      .then(data => { | 
			
		||||
 | 
				        if (data.code === 401) { | 
			
		||||
 | 
				          // this.login();
 | 
			
		||||
 | 
				        } else { | 
			
		||||
 | 
				          return data.data.list; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      }) | 
			
		||||
 | 
				      .catch(error => { | 
			
		||||
 | 
				        console.error('Error:', error); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				  getTree(deviceId, parentId, onlyCatalog, callback, endCallback, errorCallback) { | 
			
		||||
 | 
				    let currentPage = 1; | 
			
		||||
 | 
				    let count = 100; | 
			
		||||
 | 
				    let catalogList = [] | 
			
		||||
 | 
				    this.getTreeIteration(deviceId, parentId, onlyCatalog, catalogList, currentPage, count, callback, endCallback, errorCallback) | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  getTreeIteration(deviceId, parentId, onlyCatalog, catalogList, currentPage, count, callback, endCallback, errorCallback) { | 
			
		||||
 | 
				    this.getTreeInfo(deviceId, parentId, onlyCatalog, currentPage, count, (data) => { | 
			
		||||
 | 
				      console.log(data) | 
			
		||||
 | 
				      if (data.code === 0 && data.data.list) { | 
			
		||||
 | 
				        if (typeof (callback) == "function") callback(data.data.list) | 
			
		||||
 | 
				        catalogList = catalogList.concat(data.data.list); | 
			
		||||
 | 
				        if (catalogList.length < data.data.total) { | 
			
		||||
 | 
				          currentPage++ | 
			
		||||
 | 
				          this.getTreeIteration(deviceId, parentId, onlyCatalog, catalogList, currentPage, count, callback, endCallback, errorCallback) | 
			
		||||
 | 
				        } else { | 
			
		||||
 | 
				          if (typeof (endCallback) == "function") endCallback(catalogList) | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, errorCallback) | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				  getTreeInfo(deviceId, parentId, onlyCatalog, currentPage, count, callback, errorCallback) { | 
			
		||||
 | 
				    if (onlyCatalog == null || typeof onlyCatalog === "undefined") { | 
			
		||||
 | 
				      onlyCatalog = false; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				    return fetch(`${this.baseURL}/api/device/query/tree/${deviceId}?page=${currentPage}&count=${count}&parentId=${parentId}&onlyCatalog=${onlyCatalog}`, { | 
			
		||||
 | 
				      headers: { | 
			
		||||
 | 
				        'Access-Token': `${this.token}` | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }) | 
			
		||||
 | 
				      .then(response => response.json()) | 
			
		||||
 | 
				      .then((res) => { | 
			
		||||
 | 
				        if (typeof (callback) == "function") callback(res) | 
			
		||||
 | 
				      }).catch(errorCallback); | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  startPlay(deviceId, channelId) { | 
			
		||||
 | 
				    return fetch(`${this.baseURL}/api/play/start/${deviceId}/${channelId}`, { | 
			
		||||
 | 
				      headers: { | 
			
		||||
 | 
				        'Access-Token': `${this.token}` | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }) | 
			
		||||
 | 
				      .then(response => response.json()) | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export default new WvpService(); | 
			
		||||
| 
		 After Width: | Height: | Size: 4.7 KiB  | 
| 
		 Before Width: | Height: | Size: 139 KiB  | 
| 
		 Before Width: | Height: | Size: 1.0 KiB  | 
| 
		 Before Width: | Height: | Size: 1.1 KiB  | 
@ -0,0 +1,388 @@ | 
			
		|||||
 | 
				<!-- 审批 --> | 
			
		||||
 | 
				<template> | 
			
		||||
 | 
				  <el-dialog | 
			
		||||
 | 
				    v-if="dialogVisible" | 
			
		||||
 | 
				    v-el-drag-dialog | 
			
		||||
 | 
				    :title="showTitle" | 
			
		||||
 | 
				    :visible.sync="dialogVisible" | 
			
		||||
 | 
				    :destroy-on-close="true" | 
			
		||||
 | 
				  > | 
			
		||||
 | 
				    <el-form | 
			
		||||
 | 
				      ref="editForm" | 
			
		||||
 | 
				      size="mini" | 
			
		||||
 | 
				      :model="form" | 
			
		||||
 | 
				      label-position="right" | 
			
		||||
 | 
				      label-width="100px" | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				      <el-form-item label="审批意见" prop="comment" :rules="[requiredTest]"> | 
			
		||||
 | 
				        <el-input | 
			
		||||
 | 
				          v-model="form.comment" | 
			
		||||
 | 
				          type="textarea" | 
			
		||||
 | 
				          placeholder="请输入审批意见" | 
			
		||||
 | 
				          style="width: 100%" | 
			
		||||
 | 
				          clearable | 
			
		||||
 | 
				        ></el-input> | 
			
		||||
 | 
				      </el-form-item> | 
			
		||||
 | 
				      <el-form-item | 
			
		||||
 | 
				        v-if="showAssign" | 
			
		||||
 | 
				        label="下一审批人" | 
			
		||||
 | 
				        prop="assignees" | 
			
		||||
 | 
				        :rules="[requiredTest]" | 
			
		||||
 | 
				      > | 
			
		||||
 | 
				        <el-select | 
			
		||||
 | 
				          v-model="form.assignees" | 
			
		||||
 | 
				          filterable | 
			
		||||
 | 
				          multiple | 
			
		||||
 | 
				          placeholder="请选择" | 
			
		||||
 | 
				          style="width: 100%" | 
			
		||||
 | 
				          clearable | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <el-option | 
			
		||||
 | 
				            v-for="item in assigneeList" | 
			
		||||
 | 
				            :key="item.username" | 
			
		||||
 | 
				            :label="item.realname" | 
			
		||||
 | 
				            :value="item.username" | 
			
		||||
 | 
				          ></el-option> | 
			
		||||
 | 
				        </el-select> | 
			
		||||
 | 
				      </el-form-item> | 
			
		||||
 | 
				      <el-form-item v-if="isGateway" label="下一审批人" :rules="[requiredTest]"> | 
			
		||||
 | 
				        分支网关处不支持自定义选择下一审批人,将自动下发给所有可审批人。 | 
			
		||||
 | 
				      </el-form-item> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <div v-show="form.type == 1"> | 
			
		||||
 | 
				        <el-form-item label="驳回至" :rules="[requiredTest]"> | 
			
		||||
 | 
				          <el-select | 
			
		||||
 | 
				            v-model="form.backTaskKey" | 
			
		||||
 | 
				            filterable | 
			
		||||
 | 
				            placeholder="请选择" | 
			
		||||
 | 
				            style="width: 100%" | 
			
		||||
 | 
				            clearable | 
			
		||||
 | 
				            @change="changeBackTask" | 
			
		||||
 | 
				          > | 
			
		||||
 | 
				            <el-option | 
			
		||||
 | 
				              v-for="item in backList" | 
			
		||||
 | 
				              :key="item.key" | 
			
		||||
 | 
				              :value="item.key" | 
			
		||||
 | 
				              :label="item.name" | 
			
		||||
 | 
				            ></el-option> | 
			
		||||
 | 
				          </el-select> | 
			
		||||
 | 
				        </el-form-item> | 
			
		||||
 | 
				        <el-form-item | 
			
		||||
 | 
				          v-show="form.backTaskKey != -1" | 
			
		||||
 | 
				          label="指定原节点审批人" | 
			
		||||
 | 
				          :rules="[requiredTest]" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <el-select | 
			
		||||
 | 
				            v-model="form.assignees" | 
			
		||||
 | 
				            filterable | 
			
		||||
 | 
				            multiple | 
			
		||||
 | 
				            placeholder="请选择" | 
			
		||||
 | 
				            style="width: 100%" | 
			
		||||
 | 
				            clearable | 
			
		||||
 | 
				          > | 
			
		||||
 | 
				            <el-option | 
			
		||||
 | 
				              v-for="item in assigneeList" | 
			
		||||
 | 
				              :key="item.username" | 
			
		||||
 | 
				              :value="item.username" | 
			
		||||
 | 
				              :label="item.realname" | 
			
		||||
 | 
				            ></el-option> | 
			
		||||
 | 
				          </el-select> | 
			
		||||
 | 
				        </el-form-item> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				    </el-form> | 
			
		||||
 | 
				    <div slot="footer" class="dialog-footer"> | 
			
		||||
 | 
				      <el-button @click="dialogVisible = false"> 取消 </el-button> | 
			
		||||
 | 
				      <el-button type="primary" :loading="loading" @click="onSubmit"> | 
			
		||||
 | 
				        确定 | 
			
		||||
 | 
				      </el-button> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				  </el-dialog> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				import { requiredTest } from "@/utils/inputTest.js"; | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  name: "ExamineAndApprove", | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    title: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: "", | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    url: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return {}; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      requiredTest, | 
			
		||||
 | 
				      dialogVisible: false, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      loading: false, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      isGateway: false, // | 
			
		||||
 | 
				      showAssign: false, //显示审批人 | 
			
		||||
 | 
				      assigneeList: [], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      backList: [], // 返回节点列表 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      form: { | 
			
		||||
 | 
				        id: "", | 
			
		||||
 | 
				        procDefId: "", | 
			
		||||
 | 
				        title: "", | 
			
		||||
 | 
				        priority: 0, //优先级 | 
			
		||||
 | 
				        firstGateway: false, | 
			
		||||
 | 
				        assignees: [], | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  computed: { | 
			
		||||
 | 
				    showTitle() { | 
			
		||||
 | 
				      return this.form.type==1?"驳回":"审批通过"; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    reset() { | 
			
		||||
 | 
				      this.loading = false; | 
			
		||||
 | 
				      this.isGateway = false; | 
			
		||||
 | 
				      this.showAssign = false; | 
			
		||||
 | 
				      this.assigneeList = []; | 
			
		||||
 | 
				      this.backList = []; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      this.form = this.$options.data().form; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    changeBackTask(v) { | 
			
		||||
 | 
				      if (v == "-1") { | 
			
		||||
 | 
				        return; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      this.$axios | 
			
		||||
 | 
				        .get("act/zNodePreset/getCurrentNodeUser", { | 
			
		||||
 | 
				          params: { | 
			
		||||
 | 
				            businessId: this.form.businessKey, | 
			
		||||
 | 
				            procDefId: this.form.procDefId, | 
			
		||||
 | 
				            nodeId: v, | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				        .then((res) => { | 
			
		||||
 | 
				          if (!res.success) { | 
			
		||||
 | 
				            return this.$message.error("请求错误"); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				          this.assigneeList = res.result.users; | 
			
		||||
 | 
				          const ids = []; | 
			
		||||
 | 
				          res.result.users.forEach((e) => { | 
			
		||||
 | 
				            ids.push(e.username); | 
			
		||||
 | 
				          }); | 
			
		||||
 | 
				          this.form.assignees = ids; | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    backTask(v) { | 
			
		||||
 | 
				      this.reset(); | 
			
		||||
 | 
				      const form = { | 
			
		||||
 | 
				        id: v.id, | 
			
		||||
 | 
				        procInstId: v.procInstId, | 
			
		||||
 | 
				        procDefId: v.procDefId, | 
			
		||||
 | 
				        title: "", | 
			
		||||
 | 
				        priority: v.priority, // 这里和申请不一样 | 
			
		||||
 | 
				        type: 1, //0通过1驳回 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        businessKey: v.businessKey, | 
			
		||||
 | 
				        tableName: v.tableName, | 
			
		||||
 | 
				        tableId: v.tableId, | 
			
		||||
 | 
				        backTaskKey: "-1", | 
			
		||||
 | 
				      }; | 
			
		||||
 | 
				      this.showAssign = false; | 
			
		||||
 | 
				      // 获取可驳回节点 | 
			
		||||
 | 
				      this.backList = [ | 
			
		||||
 | 
				        { | 
			
		||||
 | 
				          key: "-1", | 
			
		||||
 | 
				          name: "发起人", | 
			
		||||
 | 
				        }, | 
			
		||||
 | 
				      ]; | 
			
		||||
 | 
				      this.$axios | 
			
		||||
 | 
				        .get(this.url.getBackList + v.procInstId) | 
			
		||||
 | 
				        .then((res) => { | 
			
		||||
 | 
				          if (!res.success) { | 
			
		||||
 | 
				            return this.$message.error("请求错误"); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				          res.result.forEach((e) => { | 
			
		||||
 | 
				            this.backList.push(e); | 
			
		||||
 | 
				          }); | 
			
		||||
 | 
				          if (res.result.length) { | 
			
		||||
 | 
				            form.backTaskKey = res.result[0].key; | 
			
		||||
 | 
				            this.changeBackTask(form.backTaskKey); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				          this.form = form; | 
			
		||||
 | 
				          this.dialogVisible = true; | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				        .catch(() => { | 
			
		||||
 | 
				          this.$message.error("请求驳回节点错误"); | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    passTask(v) { | 
			
		||||
 | 
				      this.reset(); | 
			
		||||
 | 
				      if (!v.procDefId || v.procDefId == "null") { | 
			
		||||
 | 
				        this.$message.error("流程定义为空"); | 
			
		||||
 | 
				        return; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      const form = { | 
			
		||||
 | 
				        id: v.id, | 
			
		||||
 | 
				        procInstId: v.procInstId, | 
			
		||||
 | 
				        procDefId: v.procDefId, | 
			
		||||
 | 
				        title: "", | 
			
		||||
 | 
				        priority: v.priority, // 这里和申请不一样 | 
			
		||||
 | 
				        type: 0, //0通过1驳回 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        // firstGateway: false, | 
			
		||||
 | 
				        // assignees: [], //审批人id | 
			
		||||
 | 
				      }; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      this.$axios | 
			
		||||
 | 
				        .get("act/zNodePreset/getNodeUser", { | 
			
		||||
 | 
				          params: { | 
			
		||||
 | 
				            businessId: v.businessKey, | 
			
		||||
 | 
				            procDefId: v.procDefId, | 
			
		||||
 | 
				            nodeId: v.key, | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				        .then((res) => { | 
			
		||||
 | 
				          if (!res.success) { | 
			
		||||
 | 
				            return this.$message.error("请求错误"); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				          // if (res.result.type == 3 || res.result.type == 4) { | 
			
		||||
 | 
				          if (res.result.type == 4) { | 
			
		||||
 | 
				            this.isGateway = true; // | 
			
		||||
 | 
				            this.showAssign = false; //不显示选择审批人 | 
			
		||||
 | 
				            this.form = form; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            this.dialogVisible = true; | 
			
		||||
 | 
				            return; | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				          if (res.result.type == 2) { | 
			
		||||
 | 
				            this.isGateway = false; | 
			
		||||
 | 
				            this.showAssign = false; | 
			
		||||
 | 
				            this.form = form; | 
			
		||||
 | 
				            this.dialogVisible = true; | 
			
		||||
 | 
				            return; | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				          this.isGateway = false; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				          if (res.result.users && res.result.users.length > 0) { | 
			
		||||
 | 
				            this.assigneeList = res.result.users; | 
			
		||||
 | 
				            // 默认勾选 | 
			
		||||
 | 
				            let ids = []; | 
			
		||||
 | 
				            res.result.users.forEach((e) => { | 
			
		||||
 | 
				              ids.push(e.username); | 
			
		||||
 | 
				            }); | 
			
		||||
 | 
				            form.assignees = ids; | 
			
		||||
 | 
				            this.showAssign = true; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            this.dialogVisible = true; | 
			
		||||
 | 
				          } else { | 
			
		||||
 | 
				            form.assignees = []; | 
			
		||||
 | 
				            this.showAssign = true; | 
			
		||||
 | 
				            this.$message.error( | 
			
		||||
 | 
				              `审批节点“${res.result.title}”未分配候选审批人员,请联系管理员!` | 
			
		||||
 | 
				            ); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				          this.form = form; | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				        .catch(() => { | 
			
		||||
 | 
				          this.$message.error("请求错误"); | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      return; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /*审批提交的方法*/ | 
			
		||||
 | 
				    onSubmit() { | 
			
		||||
 | 
				      // this.submitLoading = true; | 
			
		||||
 | 
				      var formData = Object.assign({}, this.form); | 
			
		||||
 | 
				      formData.assignees = formData.assignees.join(","); | 
			
		||||
 | 
				      if (formData.type == 0) { | 
			
		||||
 | 
				        // 通过 | 
			
		||||
 | 
				        if (this.showAssign && formData.assignees.length < 1) { | 
			
		||||
 | 
				          this.$message.error("请至少选择一个审批人"); | 
			
		||||
 | 
				          // this.submitLoading = false; | 
			
		||||
 | 
				          return; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        this.$axios | 
			
		||||
 | 
				          .post(this.url.pass, null, { | 
			
		||||
 | 
				            params: formData, | 
			
		||||
 | 
				          }) | 
			
		||||
 | 
				          .then((res) => { | 
			
		||||
 | 
				            // this.submitLoading = false; | 
			
		||||
 | 
				            if (res.success) { | 
			
		||||
 | 
				              this.$message.success("操作成功"); | 
			
		||||
 | 
				              this.close(); | 
			
		||||
 | 
				              this.$emit("refresh"); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				          }); | 
			
		||||
 | 
				      } else if (formData.type == 1) { | 
			
		||||
 | 
				        // 驳回 | 
			
		||||
 | 
				        if (formData.backTaskKey == "-1") { | 
			
		||||
 | 
				          // 驳回至发起人 | 
			
		||||
 | 
				          this.$axios | 
			
		||||
 | 
				          .post(this.url.back, null, { | 
			
		||||
 | 
				            params: formData, | 
			
		||||
 | 
				          }).then((res) => { | 
			
		||||
 | 
				            // this.submitLoading = false; | 
			
		||||
 | 
				            if (res.success) { | 
			
		||||
 | 
				              this.$message.success("操作成功"); | 
			
		||||
 | 
				              this.close(); | 
			
		||||
 | 
				              this.$emit("refresh"); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				          }); | 
			
		||||
 | 
				        } else { | 
			
		||||
 | 
				          // 自定义驳回 | 
			
		||||
 | 
				          if (formData.backTaskKey != "-1" && formData.assignees.length < 1) { | 
			
		||||
 | 
				            this.$message.error("请至少选择一个审批人"); | 
			
		||||
 | 
				            // this.submitLoading = false; | 
			
		||||
 | 
				            return; | 
			
		||||
 | 
				          } else { | 
			
		||||
 | 
				            this.error = ""; | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				          this.$axios | 
			
		||||
 | 
				          .post(this.url.backToTask, null, { | 
			
		||||
 | 
				            params: formData, | 
			
		||||
 | 
				          }).then((res) => { | 
			
		||||
 | 
				            // this.submitLoading = false; | 
			
		||||
 | 
				            if (res.success) { | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				              this.$message.success("操作成功"); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				              this.close(); | 
			
		||||
 | 
				              this.$emit("refresh"); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				          }); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      } else if (formData.type == 2) { | 
			
		||||
 | 
				        // 委托 | 
			
		||||
 | 
				        if (!formData.userId) { | 
			
		||||
 | 
				          this.$message.error("请选择一委托人"); | 
			
		||||
 | 
				          // this.submitLoading = false; | 
			
		||||
 | 
				          return; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        this.$axios | 
			
		||||
 | 
				          .post(this.url.delegate, null, { | 
			
		||||
 | 
				            params: formData, | 
			
		||||
 | 
				          }).then((res) => { | 
			
		||||
 | 
				          // this.submitLoading = false; | 
			
		||||
 | 
				          if (res.success) { | 
			
		||||
 | 
				            this.$message.success("操作成功"); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            this.close(); | 
			
		||||
 | 
				            this.$emit("refresh"); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    close() { | 
			
		||||
 | 
				      this.dialogVisible = false; | 
			
		||||
 | 
				      this.$emit("close"); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,162 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <div class="ProcessProgress"> | 
			
		||||
 | 
				    <div @click="show"> | 
			
		||||
 | 
				      <slot> | 
			
		||||
 | 
				        <el-link type="primary">审批历史</el-link> | 
			
		||||
 | 
				      </slot> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    <el-drawer | 
			
		||||
 | 
				      title="流程审批进度历史" | 
			
		||||
 | 
				      append-to-body | 
			
		||||
 | 
				      :visible.sync="drawerShow" | 
			
		||||
 | 
				      position="right" | 
			
		||||
 | 
				      size="700px" | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				      <el-table :data="data" border fit size="mini" highlight-current-row> | 
			
		||||
 | 
				        <el-table-column | 
			
		||||
 | 
				          align="center" | 
			
		||||
 | 
				          label="任务名称" | 
			
		||||
 | 
				          prop="name" | 
			
		||||
 | 
				        ></el-table-column> | 
			
		||||
 | 
				        <el-table-column align="center" label="处理人" prop="assignees"> | 
			
		||||
 | 
				          <template slot-scope="scope"> | 
			
		||||
 | 
				            <span v-for="(item, index) in scope.row.assignees" :key="index"> | 
			
		||||
 | 
				              <span v-if="item.isExecutor" style="color: #00db00"> | 
			
		||||
 | 
				                {{ item.username }} | 
			
		||||
 | 
				              </span> | 
			
		||||
 | 
				              <span v-else style="color: #999">{{ item.username }}</span> | 
			
		||||
 | 
				            </span> | 
			
		||||
 | 
				          </template> | 
			
		||||
 | 
				        </el-table-column> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        <el-table-column | 
			
		||||
 | 
				          align="center" | 
			
		||||
 | 
				          label="审批操作" | 
			
		||||
 | 
				          prop="deleteReason" | 
			
		||||
 | 
				        ></el-table-column> | 
			
		||||
 | 
				        <el-table-column | 
			
		||||
 | 
				          align="center" | 
			
		||||
 | 
				          label="审批意见" | 
			
		||||
 | 
				          prop="comment" | 
			
		||||
 | 
				        ></el-table-column> | 
			
		||||
 | 
				        <el-table-column | 
			
		||||
 | 
				          align="center" | 
			
		||||
 | 
				          label="耗时" | 
			
		||||
 | 
				          prop="duration" | 
			
		||||
 | 
				        ></el-table-column> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        <el-table-column | 
			
		||||
 | 
				          align="center" | 
			
		||||
 | 
				          label="创建时间" | 
			
		||||
 | 
				          prop="createTime" | 
			
		||||
 | 
				        ></el-table-column> | 
			
		||||
 | 
				        <el-table-column | 
			
		||||
 | 
				          align="center" | 
			
		||||
 | 
				          label="完成时间" | 
			
		||||
 | 
				          prop="endTime" | 
			
		||||
 | 
				        ></el-table-column> | 
			
		||||
 | 
				        <el-table-column | 
			
		||||
 | 
				          align="center" | 
			
		||||
 | 
				          label="状态" | 
			
		||||
 | 
				          prop="status" | 
			
		||||
 | 
				        ></el-table-column> | 
			
		||||
 | 
				      </el-table> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <div class="progress"> | 
			
		||||
 | 
				        <img :src="imgUrl" alt /> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				    </el-drawer> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    rid: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: "", | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      drawerShow: false, | 
			
		||||
 | 
				      data: [], | 
			
		||||
 | 
				      url: { | 
			
		||||
 | 
				        historicFlow: "/actTask/historicFlow/", | 
			
		||||
 | 
				        getHighlightImg: `${import.meta.env.VITE_APP_BASE_URL}${ | 
			
		||||
 | 
				          import.meta.env.VITE_APP_BASE_API | 
			
		||||
 | 
				        }/activiti/models/getHighlightImg/`, | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      imgUrl: "", | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    millsToTime(mills) { | 
			
		||||
 | 
				      if (!mills) { | 
			
		||||
 | 
				        return ""; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      const s = mills / 1000; | 
			
		||||
 | 
				      if (s < 60) { | 
			
		||||
 | 
				        return `${s.toFixed(0)} 秒`; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      const m = s / 60; | 
			
		||||
 | 
				      if (m < 60) { | 
			
		||||
 | 
				        return `${m.toFixed(0)} 分钟`; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      const h = m / 60; | 
			
		||||
 | 
				      if (h < 24) { | 
			
		||||
 | 
				        return `${h.toFixed(0)} 小时`; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      const d = h / 24; | 
			
		||||
 | 
				      if (d < 30) { | 
			
		||||
 | 
				        return `${d.toFixed(0)} 天`; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      const month = d / 30; | 
			
		||||
 | 
				      if (month < 12) { | 
			
		||||
 | 
				        return `${month.toFixed(0)} 个月`; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      const year = month / 12; | 
			
		||||
 | 
				      return `${year.toFixed(0)} 年`; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    show() { | 
			
		||||
 | 
				      if (!this.rid) { | 
			
		||||
 | 
				        this.$message.error("未指定数据"); | 
			
		||||
 | 
				      } else { | 
			
		||||
 | 
				        this.drawerShow = true; | 
			
		||||
 | 
				        this.imgUrl = `${ | 
			
		||||
 | 
				          this.url.getHighlightImg + this.rid | 
			
		||||
 | 
				        }?time=${new Date()}`; | 
			
		||||
 | 
				        this.getDataList(); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    getDataList() { | 
			
		||||
 | 
				      this.$axios.get(this.url.historicFlow + this.rid).then((res) => { | 
			
		||||
 | 
				        this.loading = false; | 
			
		||||
 | 
				        if (res.success) { | 
			
		||||
 | 
				          this.data = res.result; | 
			
		||||
 | 
				          if (!res.result || res.result.length === 0) { | 
			
		||||
 | 
				            this.$message.error( | 
			
		||||
 | 
				              "未找到该记录审批历史数据,历史数据可能已被删除" | 
			
		||||
 | 
				            ); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				        } else { | 
			
		||||
 | 
				          this.$message.error(res.message); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    submit() {}, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style lang="scss" scoped> | 
			
		||||
 | 
				.ProcessProgress { | 
			
		||||
 | 
				  display: inline-block; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.progress { | 
			
		||||
 | 
				  img { | 
			
		||||
 | 
				    width: 100%; | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,146 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <el-drawer | 
			
		||||
 | 
				    title="选择流程" | 
			
		||||
 | 
				    :visible.sync="drawerShow" | 
			
		||||
 | 
				    position="right" | 
			
		||||
 | 
				    size="600px" | 
			
		||||
 | 
				  > | 
			
		||||
 | 
				    <el-table | 
			
		||||
 | 
				      v-for="value of activeKeyAll" | 
			
		||||
 | 
				      :key="value" | 
			
		||||
 | 
				      :data="processDataMap[value]" | 
			
		||||
 | 
				      border | 
			
		||||
 | 
				      fit | 
			
		||||
 | 
				      size="mini" | 
			
		||||
 | 
				      highlight-current-row | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				      <el-table-column | 
			
		||||
 | 
				        align="center" | 
			
		||||
 | 
				        :label="filterDictText(dictOptions, value) || '未分类'" | 
			
		||||
 | 
				      > | 
			
		||||
 | 
				        <el-table-column | 
			
		||||
 | 
				          align="center" | 
			
		||||
 | 
				          label="任务名称" | 
			
		||||
 | 
				          prop="name" | 
			
		||||
 | 
				        ></el-table-column> | 
			
		||||
 | 
				        <el-table-column | 
			
		||||
 | 
				          align="center" | 
			
		||||
 | 
				          label="版本" | 
			
		||||
 | 
				          prop="version" | 
			
		||||
 | 
				        ></el-table-column> | 
			
		||||
 | 
				        <el-table-column | 
			
		||||
 | 
				          align="center" | 
			
		||||
 | 
				          label="说明" | 
			
		||||
 | 
				          prop="description" | 
			
		||||
 | 
				        ></el-table-column> | 
			
		||||
 | 
				        <el-table-column align="center" label="说明" prop="description"> | 
			
		||||
 | 
				          <template #default="scope"> | 
			
		||||
 | 
				            <a href="javascript:void (0)" @click="chooseProcess(scope.row)" | 
			
		||||
 | 
				              >发起申请</a | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				          </template> | 
			
		||||
 | 
				        </el-table-column> | 
			
		||||
 | 
				      </el-table-column> | 
			
		||||
 | 
				    </el-table> | 
			
		||||
 | 
				    <ViewForm ref="viewForm"  @refresh="refresh"></ViewForm> | 
			
		||||
 | 
				  </el-drawer> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				import { groupBy } from "lodash-es"; | 
			
		||||
 | 
				import ViewForm from "@/components/activiticonfig/ProcessModelList/ViewForm.vue"; | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  components: { | 
			
		||||
 | 
				    ViewForm, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      drawerShow: false, | 
			
		||||
 | 
				      activeKeyAll: [], | 
			
		||||
 | 
				      processDataMap: {}, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      dictOptions: [], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      data: [], | 
			
		||||
 | 
				      url: { | 
			
		||||
 | 
				        list: "/actBusiness/listData", | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        delete: "/actBusiness/delByIds", | 
			
		||||
 | 
				        deleteBatch: "/actBusiness/delByIds", | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        getProcessDataList: "/activiti_process/listData", | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        getFirstNode: "/actProcessIns/getFirstNode", | 
			
		||||
 | 
				        applyBusiness: "/actBusiness/apply", | 
			
		||||
 | 
				        cancelApply: "/actBusiness/cancel", | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    show() { | 
			
		||||
 | 
				      this.drawerShow = true; | 
			
		||||
 | 
				      this.getProcessList(); | 
			
		||||
 | 
				      this.initDictConfig(); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    initDictConfig() { | 
			
		||||
 | 
				      //初始化字典 - 流程分类 | 
			
		||||
 | 
				      this.$axios.get("/sys/dict/getDictItems/bpm_process_type").then((res) => { | 
			
		||||
 | 
				        if (res.success) { | 
			
		||||
 | 
				          this.dictOptions = res.result; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    filterDictText(dictOptions, text) { | 
			
		||||
 | 
				      if (dictOptions instanceof Array) { | 
			
		||||
 | 
				        for (let dictItem of dictOptions) { | 
			
		||||
 | 
				          if (text === dictItem.value) { | 
			
		||||
 | 
				            return dictItem.text; | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      return text || text == "null" ? "" : text; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    getProcessList() { | 
			
		||||
 | 
				      this.$axios | 
			
		||||
 | 
				        .get("/activiti_process/listData", { | 
			
		||||
 | 
				          params: { status: 1, roles: true }, | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				        .then((res) => { | 
			
		||||
 | 
				          this.activeKeyAll = []; | 
			
		||||
 | 
				          if (res.success) { | 
			
		||||
 | 
				            var result = res.result || []; | 
			
		||||
 | 
				            if (result.length > 0) { | 
			
		||||
 | 
				              this.processDataMap = groupBy(result, "categoryId"); | 
			
		||||
 | 
				              for (const categoryId in this.processDataMap) { | 
			
		||||
 | 
				                this.activeKeyAll.push(categoryId); | 
			
		||||
 | 
				              } | 
			
		||||
 | 
				              this.activeKey = this.activeKeyAll; | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            this.processModalVisible = true; | 
			
		||||
 | 
				          } else { | 
			
		||||
 | 
				            this.$message.error(res.message); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				        .finally(() => (this.addApplyLoading = false)); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    chooseProcess(v) { | 
			
		||||
 | 
				      if (!v.routeName) { | 
			
		||||
 | 
				        this.$message.error("该流程信息未配置表单,请联系开发人员!"); | 
			
		||||
 | 
				        return; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      this.$refs.viewForm.show({ | 
			
		||||
 | 
				        routeName:v.routeName, | 
			
		||||
 | 
				        title:"发起流程:" + v.name, | 
			
		||||
 | 
				        isNew:true, | 
			
		||||
 | 
				        processData:v, | 
			
		||||
 | 
				        disabled:false, | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				      console.log("发起", v); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    refresh() { | 
			
		||||
 | 
				      this.drawerShow = false; | 
			
		||||
 | 
				      this.$emit("refresh"); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    submit() {}, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,216 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <el-dialog | 
			
		||||
 | 
				    v-if="dialogVisible" | 
			
		||||
 | 
				    v-el-drag-dialog | 
			
		||||
 | 
				    :title="showTitle" | 
			
		||||
 | 
				    :visible.sync="dialogVisible" | 
			
		||||
 | 
				    :destroy-on-close="true" | 
			
		||||
 | 
				  > | 
			
		||||
 | 
				    <el-form | 
			
		||||
 | 
				      ref="editForm" | 
			
		||||
 | 
				      size="mini" | 
			
		||||
 | 
				      :model="form" | 
			
		||||
 | 
				      label-position="right" | 
			
		||||
 | 
				      label-width="100px" | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				      <el-form-item | 
			
		||||
 | 
				        v-if="showAssign" | 
			
		||||
 | 
				        label="审批人" | 
			
		||||
 | 
				        prop="assignees" | 
			
		||||
 | 
				        :rules="[requiredTest]" | 
			
		||||
 | 
				      > | 
			
		||||
 | 
				        <el-select | 
			
		||||
 | 
				          v-model="form.assignees" | 
			
		||||
 | 
				          filterable | 
			
		||||
 | 
				          multiple | 
			
		||||
 | 
				          placeholder="请选择" | 
			
		||||
 | 
				          style="width: 100%" | 
			
		||||
 | 
				          clearable | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <el-option | 
			
		||||
 | 
				            v-for="item in assigneeList" | 
			
		||||
 | 
				            :key="item.username" | 
			
		||||
 | 
				            :label="item.realname" | 
			
		||||
 | 
				            :value="item.username" | 
			
		||||
 | 
				          ></el-option> | 
			
		||||
 | 
				        </el-select> | 
			
		||||
 | 
				      </el-form-item> | 
			
		||||
 | 
				      <el-form-item v-if="isGateway" label="下一审批人" :rules="[requiredTest]"> | 
			
		||||
 | 
				        分支网关处不支持自定义选择下一审批人,将自动下发给所有可审批人。 | 
			
		||||
 | 
				      </el-form-item> | 
			
		||||
 | 
				      <el-form-item label="优先级" prop="priority"> | 
			
		||||
 | 
				        <el-select | 
			
		||||
 | 
				          v-model="form.priority" | 
			
		||||
 | 
				          filterable | 
			
		||||
 | 
				          placeholder="请选择" | 
			
		||||
 | 
				          style="width: 100%" | 
			
		||||
 | 
				          clearable | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <el-option label="普通" :value="0"></el-option> | 
			
		||||
 | 
				          <el-option label="重要" :value="1"></el-option> | 
			
		||||
 | 
				          <el-option label="紧急" :value="2"></el-option> | 
			
		||||
 | 
				        </el-select> | 
			
		||||
 | 
				      </el-form-item> | 
			
		||||
 | 
				    </el-form> | 
			
		||||
 | 
				    <div slot="footer" class="dialog-footer"> | 
			
		||||
 | 
				      <el-button @click="dialogVisible = false"> 取消 </el-button> | 
			
		||||
 | 
				      <el-button type="primary" :loading="loading" @click="onSubmit"> | 
			
		||||
 | 
				        确定 | 
			
		||||
 | 
				      </el-button> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				  </el-dialog> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				import { requiredTest } from "@/utils/inputTest.js"; | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    title: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: "", | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    url: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return {}; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    options: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return {}; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  emits: ["refresh"], | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      requiredTest, | 
			
		||||
 | 
				      dialogVisible: false, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      loading: false, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      isGateway: false, // | 
			
		||||
 | 
				      showAssign: false, //显示审批人 | 
			
		||||
 | 
				      assigneeList: [], | 
			
		||||
 | 
				      form: { | 
			
		||||
 | 
				        id: "", | 
			
		||||
 | 
				        procDefId: "", | 
			
		||||
 | 
				        title: "", | 
			
		||||
 | 
				        priority: 0, //优先级 | 
			
		||||
 | 
				        firstGateway: false, | 
			
		||||
 | 
				        assignees: [], | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  computed: { | 
			
		||||
 | 
				    showTitle() { | 
			
		||||
 | 
				      return "提交申请"; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    reset() { | 
			
		||||
 | 
				      this.loading = false; | 
			
		||||
 | 
				      this.isGateway = false; | 
			
		||||
 | 
				      this.showAssign = false; | 
			
		||||
 | 
				      this.form = this.$options.data().form; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    show(form) { | 
			
		||||
 | 
				      this.reset(); | 
			
		||||
 | 
				      if (form) { | 
			
		||||
 | 
				        // this.form = { ...this.$options.data().form, ...form }; | 
			
		||||
 | 
				        this.apply(form); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      // this.dialogVisible = true; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    apply(v) { | 
			
		||||
 | 
				      if (!v.procDefId || v.procDefId == "null") { | 
			
		||||
 | 
				        this.$message.error("流程定义为空"); | 
			
		||||
 | 
				        return; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      const form = { | 
			
		||||
 | 
				        id: v.id, | 
			
		||||
 | 
				        procDefId: v.procDefId, | 
			
		||||
 | 
				        title: v.title, | 
			
		||||
 | 
				        priority: 0, | 
			
		||||
 | 
				        firstGateway: false, | 
			
		||||
 | 
				        assignees: [], //审批人id | 
			
		||||
 | 
				      }; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      this.$axios | 
			
		||||
 | 
				        .get("act/zNodePreset/getNodeUser", { | 
			
		||||
 | 
				          params: { | 
			
		||||
 | 
				            businessId: v.id, | 
			
		||||
 | 
				            procDefId: v.procDefId, | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				        .then((res) => { | 
			
		||||
 | 
				          if (!res.success) { | 
			
		||||
 | 
				            return this.$message.error("需要先设置审核用户"); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				          if (res.result.type == 3 || res.result.type == 4) { | 
			
		||||
 | 
				            form.firstGateway = true; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            this.isGateway = true; // | 
			
		||||
 | 
				            this.showAssign = false; //不显示选择审批人 | 
			
		||||
 | 
				            this.form = form; | 
			
		||||
 | 
				            this.dialogVisible = true; | 
			
		||||
 | 
				            return; | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				          if (res.result.users && res.result.users.length > 0) { | 
			
		||||
 | 
				            this.assigneeList = res.result.users; | 
			
		||||
 | 
				            // 默认勾选 | 
			
		||||
 | 
				            let ids = []; | 
			
		||||
 | 
				            res.result.users.forEach((e) => { | 
			
		||||
 | 
				              ids.push(e.username); | 
			
		||||
 | 
				            }); | 
			
		||||
 | 
				            form.assignees = ids; | 
			
		||||
 | 
				            this.showAssign = true; | 
			
		||||
 | 
				          } else { | 
			
		||||
 | 
				            form.assignees = []; | 
			
		||||
 | 
				            this.showAssign = true; | 
			
		||||
 | 
				            this.$message.error( | 
			
		||||
 | 
				              `审批节点“${res.result.title}”未分配候选审批人员,请联系管理员!` | 
			
		||||
 | 
				            ); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				          this.form = form; | 
			
		||||
 | 
				          this.dialogVisible = true; | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      return; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    onSubmit() { | 
			
		||||
 | 
				      if (this.showAssign && this.form.assignees.length < 1) { | 
			
		||||
 | 
				        this.$error("请至少选择一个审批人"); | 
			
		||||
 | 
				        return; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      this.$refs.editForm.validate((valid) => { | 
			
		||||
 | 
				        if (!valid) { | 
			
		||||
 | 
				          return false; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        this.loading = true; | 
			
		||||
 | 
				        var form = { ...this.form }; | 
			
		||||
 | 
				        console.log("form", form); | 
			
		||||
 | 
				        form.assignees = form.assignees.join(","); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        this.$axios | 
			
		||||
 | 
				          .post(this.url.applyBusiness, null, { | 
			
		||||
 | 
				            params: form, | 
			
		||||
 | 
				          }) | 
			
		||||
 | 
				          .then(({ message }) => { | 
			
		||||
 | 
				            this.$message({ type: "info", message: message }); | 
			
		||||
 | 
				            this.dialogVisible = false; | 
			
		||||
 | 
				            this.$emit("refresh"); | 
			
		||||
 | 
				          }) | 
			
		||||
 | 
				          .finally(() => { | 
			
		||||
 | 
				            this.loading = false; | 
			
		||||
 | 
				          }); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style lang="scss" scoped></style> | 
			
		||||
@ -0,0 +1,174 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <span> | 
			
		||||
 | 
				    <el-link type="primary" @click="getNodeData">审批用户</el-link> | 
			
		||||
 | 
				    <el-dialog | 
			
		||||
 | 
				      v-el-drag-dialog | 
			
		||||
 | 
				      title="审批用户" | 
			
		||||
 | 
				      width="500px" | 
			
		||||
 | 
				      :visible.sync="showProcessNode" | 
			
		||||
 | 
				      append-to-body | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				      <el-form> | 
			
		||||
 | 
				        <el-form-item label="提示:" style="color: red" | 
			
		||||
 | 
				          >所有输入框请只保留一个审批人</el-form-item | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				        <el-form-item | 
			
		||||
 | 
				          v-for="(item, i) in nodeList" | 
			
		||||
 | 
				          :key="i" | 
			
		||||
 | 
				          :label="item.title" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <el-select v-model="item.userId" multiple style="width: 100%"> | 
			
		||||
 | 
				            <el-option | 
			
		||||
 | 
				              v-for="v in item.users" | 
			
		||||
 | 
				              :key="v.id" | 
			
		||||
 | 
				              :value="v.id" | 
			
		||||
 | 
				              :label="v.realname" | 
			
		||||
 | 
				            ></el-option> | 
			
		||||
 | 
				          </el-select> | 
			
		||||
 | 
				        </el-form-item> | 
			
		||||
 | 
				      </el-form> | 
			
		||||
 | 
				      <div slot="footer" class="dialog-footer"> | 
			
		||||
 | 
				        <el-button @click="closeNode"> 取消 </el-button> | 
			
		||||
 | 
				        <el-button type="primary" :loading="loading" @click="confirm"> | 
			
		||||
 | 
				          确定 | 
			
		||||
 | 
				        </el-button> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				    </el-dialog> | 
			
		||||
 | 
				  </span> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    row: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => ({}), | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      showProcessNode: false, | 
			
		||||
 | 
				      nodeList: [], | 
			
		||||
 | 
				      nodeId: "", | 
			
		||||
 | 
				      loading: false, | 
			
		||||
 | 
				      url: { | 
			
		||||
 | 
				        PresetList: "act/zNodePreset/listAll", | 
			
		||||
 | 
				        add: "act/zNodePreset/add", | 
			
		||||
 | 
				        edit: "act/zNodePreset/edit", | 
			
		||||
 | 
				        getNodeData: "/actBusiness/getApprovalUser", | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      PresetList: [], | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    closeNode() { | 
			
		||||
 | 
				      this.showProcessNode = false; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    confirm() { | 
			
		||||
 | 
				      this.add(); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    handleChange(v, item) { | 
			
		||||
 | 
				      console.log(v, item); | 
			
		||||
 | 
				      item.userId = v; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    add() { | 
			
		||||
 | 
				      let haveMultiple = false; // 是否有多个审批人 | 
			
		||||
 | 
				      let haveNull = false; // 是否有空的审批人 | 
			
		||||
 | 
				      const data = this.nodeList.map((v) => { | 
			
		||||
 | 
				        if (!v.userId || v.userId.length === 0) { | 
			
		||||
 | 
				          haveNull = true; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        if (v.userId && v.userId.length > 1) { | 
			
		||||
 | 
				          haveMultiple = true; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        return { | 
			
		||||
 | 
				          id: v.PresetId, | 
			
		||||
 | 
				          businessId: this.row.id, | 
			
		||||
 | 
				          procDefId: v.procDefId, | 
			
		||||
 | 
				          nodeId: v.id, | 
			
		||||
 | 
				          userId: v.userId && v.userId.length === 1 ? v.userId[0] : "", | 
			
		||||
 | 
				        }; | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				      if (haveNull) { | 
			
		||||
 | 
				        this.$message.error("所有节点都需要选择审批人"); | 
			
		||||
 | 
				        return; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      if (haveMultiple) { | 
			
		||||
 | 
				        this.$message.error("所有节点只能选择一个审批人"); | 
			
		||||
 | 
				        return; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      console.log(data); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      if (this.PresetList.length) { | 
			
		||||
 | 
				        this.$axios.put(this.url.edit, data).then((res) => { | 
			
		||||
 | 
				          if (res.code === 200) { | 
			
		||||
 | 
				            // this.nodeList = res.data; | 
			
		||||
 | 
				            this.$message.info(res.message); | 
			
		||||
 | 
				          } else { | 
			
		||||
 | 
				            this.$message.error(res.message); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				          this.closeNode(); | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      } else { | 
			
		||||
 | 
				        this.$axios.post(this.url.add, data).then((res) => { | 
			
		||||
 | 
				          if (res.code === 200) { | 
			
		||||
 | 
				            // this.nodeList = res.data; | 
			
		||||
 | 
				            this.$message.info(res.message); | 
			
		||||
 | 
				          } else { | 
			
		||||
 | 
				            this.$message.error(res.message); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				          this.closeNode(); | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    async getPresetList() { | 
			
		||||
 | 
				      const res = await this.$axios.get(this.url.PresetList, { | 
			
		||||
 | 
				        params: { | 
			
		||||
 | 
				          businessId: this.row.id, | 
			
		||||
 | 
				        }, | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				      if (res.code === 200) { | 
			
		||||
 | 
				        console.log("获取user"); | 
			
		||||
 | 
				        this.PresetList = res.result; | 
			
		||||
 | 
				        // this.$message.info(res.message); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    async getNodeData() { | 
			
		||||
 | 
				      await this.getPresetList(); | 
			
		||||
 | 
				      console.log("获取NodeData"); | 
			
		||||
 | 
				      this.$axios | 
			
		||||
 | 
				        .get(`${this.url.getNodeData}?id=${this.row.id}`, { | 
			
		||||
 | 
				          id: this.row.id, | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				        .then((res) => { | 
			
		||||
 | 
				          if (res.success) { | 
			
		||||
 | 
				            res.result.forEach((v) => { | 
			
		||||
 | 
				              this.PresetList.forEach((p) => { | 
			
		||||
 | 
				                if (v.id === p.nodeId) { | 
			
		||||
 | 
				                  v.userId = [p.userId]; | 
			
		||||
 | 
				                  v.PresetId = p.id; | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				              }); | 
			
		||||
 | 
				            }); | 
			
		||||
 | 
				            res.result.forEach((v) => { | 
			
		||||
 | 
				              let ids = []; | 
			
		||||
 | 
				              if (v.users) { | 
			
		||||
 | 
				                ids = v.users.map((user) => user.id); | 
			
		||||
 | 
				              } | 
			
		||||
 | 
				              if (!v.userId) { | 
			
		||||
 | 
				                v.userId = ids; | 
			
		||||
 | 
				              } | 
			
		||||
 | 
				            }); | 
			
		||||
 | 
				            this.nodeList = res.result || []; | 
			
		||||
 | 
				            console.log("this.nodeList", this.nodeList); | 
			
		||||
 | 
				            this.showProcessNode = true; | 
			
		||||
 | 
				          } else { | 
			
		||||
 | 
				            this.$message.error(res.message); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style></style> | 
			
		||||
@ -0,0 +1,108 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <el-dialog | 
			
		||||
 | 
				    v-if="dialogVisible" | 
			
		||||
 | 
				    v-el-drag-dialog | 
			
		||||
 | 
				    :title="showTitle" | 
			
		||||
 | 
				    :visible.sync="dialogVisible" | 
			
		||||
 | 
				    :destroy-on-close="true" | 
			
		||||
 | 
				    :close-on-click-modal="false" | 
			
		||||
 | 
				    width="500px" | 
			
		||||
 | 
				    top="5vh" | 
			
		||||
 | 
				  > | 
			
		||||
 | 
				    <el-form | 
			
		||||
 | 
				      v-if="dialogVisible" | 
			
		||||
 | 
				      ref="editForm" | 
			
		||||
 | 
				      size="mini" | 
			
		||||
 | 
				      :rules="rules" | 
			
		||||
 | 
				      :model="form" | 
			
		||||
 | 
				      label-position="right" | 
			
		||||
 | 
				      label-width="100px" | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				      <el-form-item label="模型名称" prop="name"> | 
			
		||||
 | 
				        <el-input v-model="form.name" /> | 
			
		||||
 | 
				      </el-form-item> | 
			
		||||
 | 
				      <el-form-item label="模型描述" prop="description"> | 
			
		||||
 | 
				        <el-input v-model="form.description" /> | 
			
		||||
 | 
				      </el-form-item> | 
			
		||||
 | 
				    </el-form> | 
			
		||||
 | 
				    <div slot="footer" class="dialog-footer"> | 
			
		||||
 | 
				      <el-button @click="dialogVisible = false"> 取消 </el-button> | 
			
		||||
 | 
				      <el-button type="primary" :loading="loading" @click="onSubmit"> | 
			
		||||
 | 
				        确定 | 
			
		||||
 | 
				      </el-button> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				  </el-dialog> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				import { useAppStore } from "@/store"; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    title: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: "", | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    url: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return {}; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      appStore: useAppStore(), | 
			
		||||
 | 
				      dialogVisible: false, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      loading: false, | 
			
		||||
 | 
				      form: { | 
			
		||||
 | 
				        id: "", | 
			
		||||
 | 
				        name: "", | 
			
		||||
 | 
				        description: "", | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      rules: { | 
			
		||||
 | 
				        // icon: [{ required: false, message: "图标必填", trigger: "blur" }], | 
			
		||||
 | 
				        name: [{ required: true, message: "名称必填", trigger: "blur" }], | 
			
		||||
 | 
				        description: [ | 
			
		||||
 | 
				          { required: true, message: "描述必填", trigger: "change" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      // componentOptions:[], | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  computed: { | 
			
		||||
 | 
				    showTitle() { | 
			
		||||
 | 
				      return this.form.id ? "编辑" + this.title : "新增" + this.title; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    reset() { | 
			
		||||
 | 
				      this.form = this.$options.data().form; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    show(form) { | 
			
		||||
 | 
				      this.reset(); | 
			
		||||
 | 
				      if (form) { | 
			
		||||
 | 
				        this.form = { ...this.$options.data().form, ...form }; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      this.dialogVisible = true; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    onSubmit() { | 
			
		||||
 | 
				      this.$refs.editForm.validate((valid) => { | 
			
		||||
 | 
				        if (!valid) { | 
			
		||||
 | 
				          return false; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        this.dialogVisible = false; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        this.$emit("refresh", this.form.name, this.form.description); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style lang="scss" scoped> | 
			
		||||
 | 
				.tips { | 
			
		||||
 | 
				  font-size: 12px; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,105 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <el-dialog | 
			
		||||
 | 
				    v-if="dialogVisible" | 
			
		||||
 | 
				    v-el-drag-dialog | 
			
		||||
 | 
				    :title="showTitle" | 
			
		||||
 | 
				    :visible.sync="dialogVisible" | 
			
		||||
 | 
				    :destroy-on-close="true" | 
			
		||||
 | 
				    :close-on-click-modal="false" | 
			
		||||
 | 
				    width="90%" | 
			
		||||
 | 
				    top="20px" | 
			
		||||
 | 
				  > | 
			
		||||
 | 
				    <iframe | 
			
		||||
 | 
				      :src="iframeUrl" | 
			
		||||
 | 
				      frameborder="0" | 
			
		||||
 | 
				      width="100%" | 
			
		||||
 | 
				      height="600px" | 
			
		||||
 | 
				      scrolling="auto" | 
			
		||||
 | 
				      style="background-color: #fff" | 
			
		||||
 | 
				    ></iframe> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    <!-- <div slot="footer" class="dialog-footer"> | 
			
		||||
 | 
				      <el-button @click="dialogVisible = false"> 取消 </el-button> | 
			
		||||
 | 
				      <el-button type="primary" :loading="loading" @click="onSubmit"> | 
			
		||||
 | 
				        确定 | 
			
		||||
 | 
				      </el-button> | 
			
		||||
 | 
				    </div> --> | 
			
		||||
 | 
				  </el-dialog> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				import { useAppStore } from "@/store"; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    title: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: "", | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    url: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return {}; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      appStore: useAppStore(), | 
			
		||||
 | 
				      dialogVisible: false, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      loading: false, | 
			
		||||
 | 
				      iframeUrl: "", | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      rules: { | 
			
		||||
 | 
				        // icon: [{ required: false, message: "图标必填", trigger: "blur" }], | 
			
		||||
 | 
				        name: [{ required: true, message: "名称必填", trigger: "blur" }], | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      // componentOptions:[], | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  computed: { | 
			
		||||
 | 
				    showTitle() { | 
			
		||||
 | 
				      return "编辑"; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    reset() { | 
			
		||||
 | 
				      this.form = this.$options.data().form; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    show(iframeUrl) { | 
			
		||||
 | 
				      this.reset(); | 
			
		||||
 | 
				      if (iframeUrl) { | 
			
		||||
 | 
				        this.iframeUrl = iframeUrl; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      this.dialogVisible = true; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    onSubmit() { | 
			
		||||
 | 
				      this.$refs.editForm.validate((valid) => { | 
			
		||||
 | 
				        if (!valid) { | 
			
		||||
 | 
				          return false; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        // const url = this.form.id ? this.url.edit : this.url.add; | 
			
		||||
 | 
				        // this.loading = true; | 
			
		||||
 | 
				        // this.$axios | 
			
		||||
 | 
				        //   .post(url, this.form) | 
			
		||||
 | 
				        //   .then(({ message }) => { | 
			
		||||
 | 
				        //     this.$message({ type: "info", message: message }); | 
			
		||||
 | 
				        //     this.dialogVisible = false; | 
			
		||||
 | 
				        //     this.$emit("refresh"); | 
			
		||||
 | 
				        //   }) | 
			
		||||
 | 
				        //   .finally(() => { | 
			
		||||
 | 
				        //     this.loading = false; | 
			
		||||
 | 
				        //   }); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style lang="scss" scoped> | 
			
		||||
 | 
				.tips { | 
			
		||||
 | 
				  font-size: 12px; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,241 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <el-dialog | 
			
		||||
 | 
				    v-if="dialogVisible" | 
			
		||||
 | 
				    v-el-drag-dialog | 
			
		||||
 | 
				    :title="showTitle" | 
			
		||||
 | 
				    :visible.sync="dialogVisible" | 
			
		||||
 | 
				    :destroy-on-close="true" | 
			
		||||
 | 
				    :close-on-click-modal="false" | 
			
		||||
 | 
				    width="800px" | 
			
		||||
 | 
				    top="20px" | 
			
		||||
 | 
				  > | 
			
		||||
 | 
				    <el-form | 
			
		||||
 | 
				      v-if="dialogVisible" | 
			
		||||
 | 
				      ref="editForm" | 
			
		||||
 | 
				      size="mini" | 
			
		||||
 | 
				      :rules="rules" | 
			
		||||
 | 
				      :model="form" | 
			
		||||
 | 
				      label-position="right" | 
			
		||||
 | 
				      label-width="100px" | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				      <el-form-item label="流程分类" prop="categoryId"> | 
			
		||||
 | 
				        <el-select | 
			
		||||
 | 
				          v-model="form.categoryId" | 
			
		||||
 | 
				          filterable | 
			
		||||
 | 
				          placeholder="请选择" | 
			
		||||
 | 
				          style="width: 100%" | 
			
		||||
 | 
				          clearable | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <el-option | 
			
		||||
 | 
				            v-for="item in categoryOptions" | 
			
		||||
 | 
				            :key="item.itemValue" | 
			
		||||
 | 
				            :label="item.itemText" | 
			
		||||
 | 
				            :value="item.itemValue" | 
			
		||||
 | 
				          ></el-option> | 
			
		||||
 | 
				        </el-select> | 
			
		||||
 | 
				      </el-form-item> | 
			
		||||
 | 
				      <el-form-item label="关联表单" prop="routeName"> | 
			
		||||
 | 
				        <el-select | 
			
		||||
 | 
				          v-model="form.routeName" | 
			
		||||
 | 
				          filterable | 
			
		||||
 | 
				          placeholder="请选择" | 
			
		||||
 | 
				          style="width: 100%" | 
			
		||||
 | 
				          clearable | 
			
		||||
 | 
				          @change="changeRouteName" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <el-option | 
			
		||||
 | 
				            v-for="item in activeStore.allFormComponent" | 
			
		||||
 | 
				            :key="item.routeName" | 
			
		||||
 | 
				            :label="item.text" | 
			
		||||
 | 
				            :value="item.routeName" | 
			
		||||
 | 
				          ></el-option> | 
			
		||||
 | 
				        </el-select> | 
			
		||||
 | 
				        <span style="cursor: pointer;" @click="viewForm()">预览表单</span> | 
			
		||||
 | 
				      </el-form-item> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-form-item label="角色授权" prop="roles"> | 
			
		||||
 | 
				        <el-select v-model="form.roles" multiple placeholder="请选择"> | 
			
		||||
 | 
				          <el-option | 
			
		||||
 | 
				            v-for="item in rolesOptions" | 
			
		||||
 | 
				            :key="item.value" | 
			
		||||
 | 
				            :label="item.label" | 
			
		||||
 | 
				            :value="item.value" | 
			
		||||
 | 
				          > | 
			
		||||
 | 
				          </el-option> | 
			
		||||
 | 
				        </el-select> | 
			
		||||
 | 
				      </el-form-item> | 
			
		||||
 | 
				      <el-form-item label="排序" prop="sort"> | 
			
		||||
 | 
				        <el-input-number v-model="form.sort" :step="1"></el-input-number> | 
			
		||||
 | 
				      </el-form-item> | 
			
		||||
 | 
				      <el-form-item label="备注描述" prop="description"> | 
			
		||||
 | 
				        <el-input v-model="form.description" autosize /> | 
			
		||||
 | 
				      </el-form-item> | 
			
		||||
 | 
				    </el-form> | 
			
		||||
 | 
				    <div slot="footer" class="dialog-footer"> | 
			
		||||
 | 
				      <el-button @click="dialogVisible = false"> 取消 </el-button> | 
			
		||||
 | 
				      <el-button type="primary" :loading="loading" @click="onSubmit"> | 
			
		||||
 | 
				        确定 | 
			
		||||
 | 
				      </el-button> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    <el-dialog | 
			
		||||
 | 
				      append-to-body | 
			
		||||
 | 
				      v-el-drag-dialog | 
			
		||||
 | 
				      :title="preview.showTitle" | 
			
		||||
 | 
				      :visible.sync="preview.dialogVisible" | 
			
		||||
 | 
				      :destroy-on-close="true" | 
			
		||||
 | 
				      :close-on-click-modal="true" | 
			
		||||
 | 
				      width="800px" | 
			
		||||
 | 
				      top="20px" | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				      <component :is="preview.formComponent" :disabled="true" isNew></component> | 
			
		||||
 | 
				    </el-dialog> | 
			
		||||
 | 
				  </el-dialog> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				import { useAppStore, useActiveStore } from "@/store"; | 
			
		||||
 | 
				import qs from "qs"; | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    title: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: "", | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    url: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return {}; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      preview: { | 
			
		||||
 | 
				        dialogVisible: false, | 
			
		||||
 | 
				        formComponent: null, | 
			
		||||
 | 
				        showTitle: null, | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      appStore: useAppStore(), | 
			
		||||
 | 
				      activeStore: useActiveStore(), | 
			
		||||
 | 
				      dialogVisible: false, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      loading: false, | 
			
		||||
 | 
				      categoryOptions: [], | 
			
		||||
 | 
				      allFormComponent: [], | 
			
		||||
 | 
				      rolesOptions: [], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      form: { | 
			
		||||
 | 
				        id: "", | 
			
		||||
 | 
				        categoryId: "", | 
			
		||||
 | 
				        routeName: "", | 
			
		||||
 | 
				        description: "", | 
			
		||||
 | 
				        sort: 0, | 
			
		||||
 | 
				        roles: [], | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      rules: { | 
			
		||||
 | 
				        // icon: [{ required: false, message: "图标必填", trigger: "blur" }], | 
			
		||||
 | 
				        categoryId: [ | 
			
		||||
 | 
				          { required: true, message: "分类必选", trigger: "change" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        routeName: [{ required: true, message: "表单必选", trigger: "change" }], | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  computed: { | 
			
		||||
 | 
				    showTitle() { | 
			
		||||
 | 
				      return this.form.id ? "编辑" + this.title : "新增" + this.title; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  mounted() { | 
			
		||||
 | 
				    this.getClass(); | 
			
		||||
 | 
				    this.getRoleList(); | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    reset() { | 
			
		||||
 | 
				      this.form = this.$options.data().form; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    show(form) { | 
			
		||||
 | 
				      this.reset(); | 
			
		||||
 | 
				      if (form) { | 
			
		||||
 | 
				        let row = { ...form }; | 
			
		||||
 | 
				        if (row.roles) { | 
			
		||||
 | 
				          row.roles = row.roles.split(","); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        this.form = { ...this.$options.data().form, ...row }; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      this.dialogVisible = true; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    onSubmit() { | 
			
		||||
 | 
				      this.$refs.editForm.validate((valid) => { | 
			
		||||
 | 
				        if (!valid) { | 
			
		||||
 | 
				          return false; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        let formData = Object.assign({}, this.form); | 
			
		||||
 | 
				        if (formData.roles) { | 
			
		||||
 | 
				          formData.roles = formData.roles.join(","); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        this.$axios | 
			
		||||
 | 
				          .post(this.url.updateInfo + "?" + qs.stringify(formData)) | 
			
		||||
 | 
				          .then((res) => { | 
			
		||||
 | 
				            if (res.success) { | 
			
		||||
 | 
				              this.$message.info("操作成功"); | 
			
		||||
 | 
				              this.dialogVisible = false; | 
			
		||||
 | 
				              this.$emit("refresh"); | 
			
		||||
 | 
				            } else { | 
			
		||||
 | 
				              this.$message.error(res.message); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				          }) | 
			
		||||
 | 
				          .finally(() => (this.confirmLoading = false)); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    viewForm() { | 
			
		||||
 | 
				      if (this.form.routeName) { | 
			
		||||
 | 
				        var row = this.activeStore.getFormComponent(this.form.routeName); | 
			
		||||
 | 
				        this.preview.formComponent = row.component; | 
			
		||||
 | 
				        this.preview.showTitle = row.text; | 
			
		||||
 | 
				        this.preview.dialogVisible = true; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    changeRouteName(routeName) { | 
			
		||||
 | 
				      if (!routeName) { | 
			
		||||
 | 
				        this.form.businessTable = ""; | 
			
		||||
 | 
				        return; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      console.log("changeRouteName", routeName); | 
			
		||||
 | 
				      let row = this.activeStore.getFormComponent(routeName); | 
			
		||||
 | 
				      this.form.businessTable = row.businessTable; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    // 角色列表 | 
			
		||||
 | 
				    getRoleList() { | 
			
		||||
 | 
				      return this.$axios.get("/sys/role/queryall").then((r) => { | 
			
		||||
 | 
				        this.rolesOptions = r.result.map((v) => { | 
			
		||||
 | 
				          return { | 
			
		||||
 | 
				            value: v.roleCode, | 
			
		||||
 | 
				            label: v.roleName, | 
			
		||||
 | 
				          }; | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    // 流程分类 | 
			
		||||
 | 
				    getClass() { | 
			
		||||
 | 
				      return this.$axios | 
			
		||||
 | 
				        .get("/sys/dictItem/list", { | 
			
		||||
 | 
				          params: { | 
			
		||||
 | 
				            dictId: "d6e1152968b02d69ff358c75b48a6ee1", | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				        .then((r) => { | 
			
		||||
 | 
				          this.categoryOptions = r.result.records.map((v) => v); | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				        .finally(() => {}); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style lang="scss" scoped> | 
			
		||||
 | 
				.tips { | 
			
		||||
 | 
				  font-size: 12px; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,249 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <el-dialog | 
			
		||||
 | 
				    v-if="dialogVisible" | 
			
		||||
 | 
				    v-el-drag-dialog | 
			
		||||
 | 
				    :title="showTitle" | 
			
		||||
 | 
				    :visible.sync="dialogVisible" | 
			
		||||
 | 
				    :destroy-on-close="true" | 
			
		||||
 | 
				    :close-on-click-modal="false" | 
			
		||||
 | 
				    width="800px" | 
			
		||||
 | 
				    top="20px" | 
			
		||||
 | 
				  > | 
			
		||||
 | 
				    <el-row :gutter="20"> | 
			
		||||
 | 
				      <el-col :span="6" style="height: 100%"> | 
			
		||||
 | 
				        <el-steps direction="vertical" :active="current"> | 
			
		||||
 | 
				          <el-step v-for="(item, i) in nodeList" :key="i" :title="item.title"> | 
			
		||||
 | 
				            <div | 
			
		||||
 | 
				              slot="title" | 
			
		||||
 | 
				              style="cursor: pointer" | 
			
		||||
 | 
				              @click.prevent="setStep(item, i)" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              {{ item.title }} | 
			
		||||
 | 
				            </div> | 
			
		||||
 | 
				          </el-step> | 
			
		||||
 | 
				        </el-steps> | 
			
		||||
 | 
				      </el-col> | 
			
		||||
 | 
				      <el-col :key="current" :span="18"> | 
			
		||||
 | 
				        <el-alert | 
			
		||||
 | 
				          title="温馨提示:若流程运行至未分配审批人员的审批节点时,流程将自动中断取消!" | 
			
		||||
 | 
				          type="warning" | 
			
		||||
 | 
				        /> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        <el-form | 
			
		||||
 | 
				          ref="editForm" | 
			
		||||
 | 
				          size="mini" | 
			
		||||
 | 
				          :rules="rules" | 
			
		||||
 | 
				          :model="editNode" | 
			
		||||
 | 
				          label-position="right" | 
			
		||||
 | 
				          label-width="100px" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <el-form-item label="节点名称:" prop="title"> | 
			
		||||
 | 
				            {{ editNode.title }} | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				          <el-form-item label="节点类型:" prop="type"> | 
			
		||||
 | 
				            {{ dictNodeType[editNode.type] }} | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				          <el-alert | 
			
		||||
 | 
				            title="每个节点设置,如有修改都请保存一次,跳转节点后数据不会自动保存!" | 
			
		||||
 | 
				            type="warning" | 
			
		||||
 | 
				          /> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				          <el-form-item | 
			
		||||
 | 
				            v-if="editNode.type == 1" | 
			
		||||
 | 
				            label="角色授权:" | 
			
		||||
 | 
				            prop="roleIds" | 
			
		||||
 | 
				          > | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="editNode.roleIds" | 
			
		||||
 | 
				              multiple | 
			
		||||
 | 
				              placeholder="请选择" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option | 
			
		||||
 | 
				                v-for="item in rolesOptions" | 
			
		||||
 | 
				                :key="item.value" | 
			
		||||
 | 
				                :label="item.label" | 
			
		||||
 | 
				                :value="item.value" | 
			
		||||
 | 
				              > | 
			
		||||
 | 
				              </el-option> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-form> | 
			
		||||
 | 
				      </el-col> | 
			
		||||
 | 
				    </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    <div slot="footer" class="dialog-footer"> | 
			
		||||
 | 
				      <el-button @click="dialogVisible = false"> 取消 </el-button> | 
			
		||||
 | 
				      <el-button | 
			
		||||
 | 
				        v-if="editNode.type !== 0 && editNode.type != 2" | 
			
		||||
 | 
				        type="primary" | 
			
		||||
 | 
				        :loading="loading" | 
			
		||||
 | 
				        @click="onSubmit" | 
			
		||||
 | 
				      > | 
			
		||||
 | 
				        确定 | 
			
		||||
 | 
				      </el-button> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				  </el-dialog> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				import { useAppStore, useActiveStore } from "@/store"; | 
			
		||||
 | 
				import qs from "qs"; | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    title: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: "", | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    url: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return {}; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      appStore: useAppStore(), | 
			
		||||
 | 
				      activeStore: useActiveStore(), | 
			
		||||
 | 
				      dialogVisible: false, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      loading: false, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      nodeList: [], | 
			
		||||
 | 
				      current: 0, | 
			
		||||
 | 
				      editNode: { | 
			
		||||
 | 
				        id: "", | 
			
		||||
 | 
				        procDefId: "", | 
			
		||||
 | 
				        title: "", | 
			
		||||
 | 
				        type: 0, | 
			
		||||
 | 
				        roleIds: [], | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      rolesOptions: [], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      parentRow: {}, | 
			
		||||
 | 
				      rules: { | 
			
		||||
 | 
				        // icon: [{ required: false, message: "图标必填", trigger: "blur" }], | 
			
		||||
 | 
				        roleIds: [{ required: true, message: "角色必选", trigger: "change" }], | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      dictNodeType: { | 
			
		||||
 | 
				        0: "开始节点", | 
			
		||||
 | 
				        1: "审批节点", | 
			
		||||
 | 
				        2: "结束节点", | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  computed: { | 
			
		||||
 | 
				    showTitle() { | 
			
		||||
 | 
				      return this.parentRow.id ? "编辑" + this.title : "新增" + this.title; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  mounted() { | 
			
		||||
 | 
				    this.getRoleList(); | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    reset() { | 
			
		||||
 | 
				      this.editNode= this.$options.data().editNode; | 
			
		||||
 | 
				      this.parentRow = this.$options.data().parentRow; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    show(row) { | 
			
		||||
 | 
				      this.reset(); | 
			
		||||
 | 
				      if (row) { | 
			
		||||
 | 
				        this.parentRow = { ...this.$options.data().parentRow, ...row }; | 
			
		||||
 | 
				        this.getNodeData(this.parentRow); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      this.dialogVisible = true; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    // 获取流程节点 | 
			
		||||
 | 
				    getNodeData(row) { | 
			
		||||
 | 
				      this.$axios | 
			
		||||
 | 
				        .post(this.url.getProcessNode + `?id=${row.id}`, { | 
			
		||||
 | 
				          id: row.id, | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				        .then((res) => { | 
			
		||||
 | 
				          if (res.success) { | 
			
		||||
 | 
				            // 转换null为"" | 
			
		||||
 | 
				            let nodeList = res.result || []; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            if (nodeList.length > 0) { | 
			
		||||
 | 
				              nodeList.forEach((v) => { | 
			
		||||
 | 
				                if (v.roles) { | 
			
		||||
 | 
				                  v.roleIds = v.roles.map((v) => v.roleCode); | 
			
		||||
 | 
				                } else { | 
			
		||||
 | 
				                  v.roleIds = []; | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				              }); | 
			
		||||
 | 
				              this.nodeList = nodeList; | 
			
		||||
 | 
				              this.setStep(this.nodeList[0], 0); | 
			
		||||
 | 
				            } else { | 
			
		||||
 | 
				              this.nodeList = []; | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				          } else { | 
			
		||||
 | 
				            this.nodeList = []; | 
			
		||||
 | 
				            this.$message.error(res.message); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    setStep(node, i) { | 
			
		||||
 | 
				      console.log("setStep", node, i); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      this.editNode = node; | 
			
		||||
 | 
				      this.current = i; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    // 角色列表 | 
			
		||||
 | 
				    getRoleList() { | 
			
		||||
 | 
				      return this.$axios.get("/sys/role/queryall").then((r) => { | 
			
		||||
 | 
				        this.rolesOptions = r.result.map((v) => { | 
			
		||||
 | 
				          return { | 
			
		||||
 | 
				            value: v.roleCode, | 
			
		||||
 | 
				            label: v.roleName, | 
			
		||||
 | 
				          }; | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    onSubmit() { | 
			
		||||
 | 
				      this.$refs.editForm.validate((valid) => { | 
			
		||||
 | 
				        if (!valid) { | 
			
		||||
 | 
				          return false; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        this.loading = true; | 
			
		||||
 | 
				        var send = { | 
			
		||||
 | 
				          nodeId: this.editNode.id, | 
			
		||||
 | 
				          procDefId: this.editNode.procDefId, | 
			
		||||
 | 
				          chooseDepHeader: "", | 
			
		||||
 | 
				          chooseSponsor: "", | 
			
		||||
 | 
				          userIds: "", | 
			
		||||
 | 
				          departmentIds: "", | 
			
		||||
 | 
				          departmentManageIds: "", | 
			
		||||
 | 
				          formVariables: "", | 
			
		||||
 | 
				          formVariable: "", | 
			
		||||
 | 
				          // roleIds: this.editNode.roleIds.join(","), | 
			
		||||
 | 
				        }; | 
			
		||||
 | 
				        if (this.editNode.roleIds.length) { | 
			
		||||
 | 
				          send.roleIds = this.editNode.roleIds.join(","); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        this.$axios | 
			
		||||
 | 
				          .post(this.url.editNodeUser + "?" + qs.stringify(send)) | 
			
		||||
 | 
				          .then((res) => { | 
			
		||||
 | 
				            if (res.success) { | 
			
		||||
 | 
				              this.$message.info("操作成功"); | 
			
		||||
 | 
				              /*保存成功后回显数据*/ | 
			
		||||
 | 
				              this.getNodeData(this.parentRow); | 
			
		||||
 | 
				            } else { | 
			
		||||
 | 
				              this.$message.error(res.message); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				          }) | 
			
		||||
 | 
				          .finally(() => (this.loading = false)); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style lang="scss" scoped> | 
			
		||||
 | 
				.tips { | 
			
		||||
 | 
				  font-size: 12px; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,113 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <div> | 
			
		||||
 | 
				    <el-dialog | 
			
		||||
 | 
				      v-if="dialogVisible" | 
			
		||||
 | 
				      v-el-drag-dialog | 
			
		||||
 | 
				      append-to-body | 
			
		||||
 | 
				      :title="preview.title" | 
			
		||||
 | 
				      :visible.sync="dialogVisible" | 
			
		||||
 | 
				      :destroy-on-close="true" | 
			
		||||
 | 
				      :close-on-click-modal="false" | 
			
		||||
 | 
				      width="800px" | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				      <component | 
			
		||||
 | 
				        :is="preview.formComponent" | 
			
		||||
 | 
				        v-if="preview.formComponent" | 
			
		||||
 | 
				        :disabled="preview.disabled" | 
			
		||||
 | 
				        :is-new="preview.isNew" | 
			
		||||
 | 
				        :task="preview.isTask" | 
			
		||||
 | 
				        :process-data="preview.processData" | 
			
		||||
 | 
				        @onSave="onSave" | 
			
		||||
 | 
				        @passTask="passTask" | 
			
		||||
 | 
				        @backTask="backTask" | 
			
		||||
 | 
				        @close="close" | 
			
		||||
 | 
				      ></component> | 
			
		||||
 | 
				    </el-dialog> | 
			
		||||
 | 
				    <ExamineAndApprove ref="ExamineAndApprove" :url="url" @refresh="refresh" @close="close"></ExamineAndApprove> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				import { useActiveStore } from "@/store"; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				import ExamineAndApprove from "@/components/activiti/ExamineAndApprove.vue"; | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  name: "ViewForm", | 
			
		||||
 | 
				  components: { ExamineAndApprove }, | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    title: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: "", | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    url: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return {}; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  emits:["refresh","close"], | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      activeStore: useActiveStore(), | 
			
		||||
 | 
				      dialogVisible: false, | 
			
		||||
 | 
				      preview: { | 
			
		||||
 | 
				        formComponent: null, | 
			
		||||
 | 
				        title: null, | 
			
		||||
 | 
				        isNew: false, | 
			
		||||
 | 
				        isTask: false, | 
			
		||||
 | 
				        processData: null, | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    reset() { | 
			
		||||
 | 
				      this.preview = this.$options.data().preview; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * 显示表单 | 
			
		||||
 | 
				     * @param {Object} preview | 
			
		||||
 | 
				     * @param {String} preview.routeName 表单组件名称 | 
			
		||||
 | 
				     * @param {String} preview.title 表单标题 | 
			
		||||
 | 
				     * @param {Boolean} preview.isNew 是否是新增 | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    show(preview = {}) { | 
			
		||||
 | 
				      this.reset(); | 
			
		||||
 | 
				      if (!preview.routeName) { | 
			
		||||
 | 
				        return; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      var formComponent = this.activeStore.getFormComponent(preview.routeName); | 
			
		||||
 | 
				      if (!formComponent) { | 
			
		||||
 | 
				        this.$message.error("表单组件不存在"); | 
			
		||||
 | 
				        return; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      this.preview = { | 
			
		||||
 | 
				        ...this.preview, | 
			
		||||
 | 
				        ...preview, | 
			
		||||
 | 
				        formComponent: formComponent.component, | 
			
		||||
 | 
				      }; | 
			
		||||
 | 
				      this.dialogVisible = true; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    onSave() { | 
			
		||||
 | 
				      this.close(); | 
			
		||||
 | 
				      this.$emit("refresh"); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    passTask() { | 
			
		||||
 | 
				      // this.close(); | 
			
		||||
 | 
				      console.log("pass"); | 
			
		||||
 | 
				      this.$refs.ExamineAndApprove.passTask(this.preview.processData); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    backTask() { | 
			
		||||
 | 
				      this.$refs.ExamineAndApprove.backTask(this.preview.processData); | 
			
		||||
 | 
				      // this.close(); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    refresh(){ | 
			
		||||
 | 
				      this.$emit("refresh"); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    close() { | 
			
		||||
 | 
				      this.dialogVisible = false; | 
			
		||||
 | 
				      this.reset(); | 
			
		||||
 | 
				      this.$emit("close"); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,198 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <!--流程业务表单--> | 
			
		||||
 | 
				  <div class="form-main"> | 
			
		||||
 | 
				    <el-card :bordered="false"> | 
			
		||||
 | 
				      <el-form ref="editForm" :model="form" @submit="handleSubmit"> | 
			
		||||
 | 
				        <el-form-item label="年度"> | 
			
		||||
 | 
				          <el-input | 
			
		||||
 | 
				            v-model="form.annual" | 
			
		||||
 | 
				            :disabled="disabled" | 
			
		||||
 | 
				            placeholder="请输入年度" | 
			
		||||
 | 
				          /> | 
			
		||||
 | 
				        </el-form-item> | 
			
		||||
 | 
				        <el-form-item label="组织"> | 
			
		||||
 | 
				          <SelectDepart v-model="form.departId" :disabled="!form.id"></SelectDepart> | 
			
		||||
 | 
				        </el-form-item> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        <el-form-item label="请假事由"> | 
			
		||||
 | 
				          <el-input | 
			
		||||
 | 
				            v-model="form.name" | 
			
		||||
 | 
				            :disabled="disabled" | 
			
		||||
 | 
				            placeholder="请输入请假事由" | 
			
		||||
 | 
				          /> | 
			
		||||
 | 
				        </el-form-item> | 
			
		||||
 | 
				        <el-form-item label="catalogId"> | 
			
		||||
 | 
				          <el-input | 
			
		||||
 | 
				            v-model="form.catalogId" | 
			
		||||
 | 
				            :disabled="disabled" | 
			
		||||
 | 
				            placeholder="请输入catalog_id" | 
			
		||||
 | 
				          /> | 
			
		||||
 | 
				        </el-form-item> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        <el-form-item v-if="!disabled" style="text-align: center"> | 
			
		||||
 | 
				          <el-button | 
			
		||||
 | 
				            type="primary" | 
			
		||||
 | 
				            :disabled="disabled || btndisabled" | 
			
		||||
 | 
				            @click="handleSubmit" | 
			
		||||
 | 
				            >保存</el-button | 
			
		||||
 | 
				          > | 
			
		||||
 | 
				          <el-button | 
			
		||||
 | 
				            style="margin-left: 8px" | 
			
		||||
 | 
				            :disabled="disabled" | 
			
		||||
 | 
				            @click="close" | 
			
		||||
 | 
				            >取消</el-button | 
			
		||||
 | 
				          > | 
			
		||||
 | 
				        </el-form-item> | 
			
		||||
 | 
				        <el-form-item v-if="task" style="text-align: center"> | 
			
		||||
 | 
				          <el-button type="primary" @click="passTask">通过</el-button> | 
			
		||||
 | 
				          <el-button style="margin-left: 8px" @click="backTask">驳回</el-button> | 
			
		||||
 | 
				        </el-form-item> | 
			
		||||
 | 
				      </el-form> | 
			
		||||
 | 
				    </el-card> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				import qs from "qs"; | 
			
		||||
 | 
				import SelectDepart from "@/components/sys/depart/SelectDepart.vue"; | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  name: "LeaveForm", | 
			
		||||
 | 
				  components: { | 
			
		||||
 | 
				    SelectDepart, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    /* 全局禁用,可表示查看 */ | 
			
		||||
 | 
				    disabled: { | 
			
		||||
 | 
				      type: Boolean, | 
			
		||||
 | 
				      default: false, | 
			
		||||
 | 
				      required: false, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    /* 流程数据 */ | 
			
		||||
 | 
				    processData: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => ({}), | 
			
		||||
 | 
				      required: false, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    /* 是否新增 */ | 
			
		||||
 | 
				    isNew: { type: Boolean, default: false, required: false }, | 
			
		||||
 | 
				    /* 是否处理流程 */ | 
			
		||||
 | 
				    task: { type: Boolean, default: false, required: false }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  emits: ["onSave", "close", "passTask", "backTask"], | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      url: { | 
			
		||||
 | 
				        getForm: "/actBusiness/getForm", | 
			
		||||
 | 
				        addApply: "/actBusiness/add", | 
			
		||||
 | 
				        editForm: "/actBusiness/editForm", | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      // form | 
			
		||||
 | 
				      form: { | 
			
		||||
 | 
				        // id: "", | 
			
		||||
 | 
				        departId: [], | 
			
		||||
 | 
				        annual: "", | 
			
		||||
 | 
				        name: "", | 
			
		||||
 | 
				        catalogId: "", | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      /* 表单回显数据 */ | 
			
		||||
 | 
				      data: {}, | 
			
		||||
 | 
				      btndisabled: false, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      departList: [], | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  created() { | 
			
		||||
 | 
				    console.log("流程数据", this.processData); | 
			
		||||
 | 
				    if (!this.isNew) { | 
			
		||||
 | 
				      this.init(); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    /* 回显数据 */ | 
			
		||||
 | 
				    init() { | 
			
		||||
 | 
				      this.btndisabled = true; | 
			
		||||
 | 
				      const r = this.processData; | 
			
		||||
 | 
				      this.$axios | 
			
		||||
 | 
				        .get(this.url.getForm, { | 
			
		||||
 | 
				          params: { | 
			
		||||
 | 
				            tableId: r.tableId, | 
			
		||||
 | 
				            tableName: r.tableName, | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				        .then((res) => { | 
			
		||||
 | 
				          if (res.success) { | 
			
		||||
 | 
				            const formData = res.result; | 
			
		||||
 | 
				            formData.tableName = r.tableName; | 
			
		||||
 | 
				            this.data = formData; | 
			
		||||
 | 
				            console.log("表单回显数据", this.data); | 
			
		||||
 | 
				            this.$nextTick(() => { | 
			
		||||
 | 
				              this.form = { | 
			
		||||
 | 
				                name: this.data.name, | 
			
		||||
 | 
				                departId: String(this.data.departId).split(","), | 
			
		||||
 | 
				                catalogId: this.data.catalogId, | 
			
		||||
 | 
				                annual: this.data.annual, | 
			
		||||
 | 
				              }; | 
			
		||||
 | 
				            }); | 
			
		||||
 | 
				            this.btndisabled = false; | 
			
		||||
 | 
				          } else { | 
			
		||||
 | 
				            this.$message.error(res.message); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    // handler | 
			
		||||
 | 
				    handleSubmit(e) { | 
			
		||||
 | 
				      e.preventDefault(); | 
			
		||||
 | 
				      this.$refs.editForm.validate((valid) => { | 
			
		||||
 | 
				        if (!valid) { | 
			
		||||
 | 
				          return false; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        const formData = Object.assign(this.data || {}, this.form); | 
			
		||||
 | 
				        formData.procDefId = this.processData.id; | 
			
		||||
 | 
				        formData.procDeTitle = this.processData.name; | 
			
		||||
 | 
				        if (formData.departId) { | 
			
		||||
 | 
				          formData.departId = formData.departId.join(","); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        if (!formData.tableName) { | 
			
		||||
 | 
				          formData.tableName = this.processData.businessTable; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        formData.filedNames = Object.keys(this.form).join(","); | 
			
		||||
 | 
				        console.log("formData", this.form); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        let url = this.url.addApply; | 
			
		||||
 | 
				        if (!this.isNew) { | 
			
		||||
 | 
				          url = this.url.editForm; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        this.btndisabled = true; | 
			
		||||
 | 
				        this.$axios | 
			
		||||
 | 
				          .post(url + "?" + qs.stringify(formData)) | 
			
		||||
 | 
				          .then((res) => { | 
			
		||||
 | 
				            if (res.success) { | 
			
		||||
 | 
				              this.$message.success("保存成功!"); | 
			
		||||
 | 
				              // todo 将表单的数据传给父组件 | 
			
		||||
 | 
				              this.$emit("onSave", formData); | 
			
		||||
 | 
				            } else { | 
			
		||||
 | 
				              this.$message.error(res.message); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				          }) | 
			
		||||
 | 
				          .finally(() => { | 
			
		||||
 | 
				            this.btndisabled = false; | 
			
		||||
 | 
				          }); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    close() { | 
			
		||||
 | 
				      // todo 关闭后的回调 | 
			
		||||
 | 
				      this.$emit("close"); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    /* 通过审批 */ | 
			
		||||
 | 
				    passTask() { | 
			
		||||
 | 
				      this.$emit("passTask"); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    /* 驳回审批 */ | 
			
		||||
 | 
				    backTask() { | 
			
		||||
 | 
				      this.$emit("backTask"); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,44 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <div style="padding: 0 15px;" @click="toggleClick"> | 
			
		||||
 | 
				    <svg | 
			
		||||
 | 
				      :class="{'is-active':isActive}" | 
			
		||||
 | 
				      class="hamburger" | 
			
		||||
 | 
				      viewBox="0 0 1024 1024" | 
			
		||||
 | 
				      xmlns="http://www.w3.org/2000/svg" | 
			
		||||
 | 
				      width="64" | 
			
		||||
 | 
				      height="64" | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				      <path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" /> | 
			
		||||
 | 
				    </svg> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  name: 'Hamburger', | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    isActive: { | 
			
		||||
 | 
				      type: Boolean, | 
			
		||||
 | 
				      default: false | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    toggleClick() { | 
			
		||||
 | 
				      this.$emit('toggleClick') | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style scoped> | 
			
		||||
 | 
				.hamburger { | 
			
		||||
 | 
				  display: inline-block; | 
			
		||||
 | 
				  vertical-align: middle; | 
			
		||||
 | 
				  width: 20px; | 
			
		||||
 | 
				  height: 20px; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.hamburger.is-active { | 
			
		||||
 | 
				  transform: rotate(180deg); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,187 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <div :class="{'hidden':hidden}" class="pagination-container"> | 
			
		||||
 | 
				    <el-pagination | 
			
		||||
 | 
				      :background="background" | 
			
		||||
 | 
				      :current-page.sync="currentPage" | 
			
		||||
 | 
				      :page-size.sync="pageSize" | 
			
		||||
 | 
				      :layout="layout" | 
			
		||||
 | 
				      :page-sizes="pageSizes" | 
			
		||||
 | 
				      :total="total" | 
			
		||||
 | 
				      v-bind="$attrs" | 
			
		||||
 | 
				      @size-change="handleSizeChange" | 
			
		||||
 | 
				      @current-change="handleCurrentChange" | 
			
		||||
 | 
				    /> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				import { scrollTo } from '@/utils/scroll-to.js' | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  name: 'Pagination', | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    total: { | 
			
		||||
 | 
				      required: true, | 
			
		||||
 | 
				      type: Number | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    page: { | 
			
		||||
 | 
				      type: Number, | 
			
		||||
 | 
				      default: 1 | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    limit: { | 
			
		||||
 | 
				      type: Number, | 
			
		||||
 | 
				      default: 10 | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    pageSizes: { | 
			
		||||
 | 
				      type: Array, | 
			
		||||
 | 
				      default() { | 
			
		||||
 | 
				        return [5,10, 20, 30, 50,100,200] | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    layout: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: 'total, sizes, prev, pager, next, jumper' | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    background: { | 
			
		||||
 | 
				      type: Boolean, | 
			
		||||
 | 
				      default: true | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    autoScroll: { | 
			
		||||
 | 
				      type: Boolean, | 
			
		||||
 | 
				      default: true | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    hidden: { | 
			
		||||
 | 
				      type: Boolean, | 
			
		||||
 | 
				      default: false | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  computed: { | 
			
		||||
 | 
				    currentPage: { | 
			
		||||
 | 
				      get() { | 
			
		||||
 | 
				        return this.page | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      set(val) { | 
			
		||||
 | 
				        this.$emit('update:page', val) | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    pageSize: { | 
			
		||||
 | 
				      get() { | 
			
		||||
 | 
				        return this.limit | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      set(val) { | 
			
		||||
 | 
				        this.$emit('update:limit', val) | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    handleSizeChange(val) { | 
			
		||||
 | 
				      this.$emit('pagination', { page: this.currentPage, limit: val }) | 
			
		||||
 | 
				      if (this.autoScroll) { | 
			
		||||
 | 
				        scrollTo(0, 800) | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    handleCurrentChange(val) { | 
			
		||||
 | 
				      this.$emit('pagination', { page: val, limit: this.pageSize }) | 
			
		||||
 | 
				      if (this.autoScroll) { | 
			
		||||
 | 
				        scrollTo(0, 800) | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style lang="scss" scoped> | 
			
		||||
 | 
				/* 自定义滚动条样式 */ | 
			
		||||
 | 
				:deep(*) { | 
			
		||||
 | 
				  /* 整个滚动条 */ | 
			
		||||
 | 
				  &::-webkit-scrollbar { | 
			
		||||
 | 
				    width: 8px; | 
			
		||||
 | 
				    height: 8px; | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  /* 滚动条轨道 */ | 
			
		||||
 | 
				  &::-webkit-scrollbar-track { | 
			
		||||
 | 
				    background: rgba(15, 12, 97, 0.2); | 
			
		||||
 | 
				    border-radius: 4px; | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  /* 滚动条滑块 */ | 
			
		||||
 | 
				  &::-webkit-scrollbar-thumb { | 
			
		||||
 | 
				    background: rgba(75, 72, 178, 0.6); | 
			
		||||
 | 
				    border-radius: 4px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    &:hover { | 
			
		||||
 | 
				      background: rgba(75, 72, 178, 0.8); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  /* 滚动条边角 */ | 
			
		||||
 | 
				  &::-webkit-scrollbar-corner { | 
			
		||||
 | 
				    background: rgba(15, 12, 97, 0.2); | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.pagination-container { | 
			
		||||
 | 
				  background: transparent; | 
			
		||||
 | 
				  padding: 15px 0; | 
			
		||||
 | 
				  text-align: right; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  &.hidden { | 
			
		||||
 | 
				    display: none; | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  :deep(.el-pagination) { | 
			
		||||
 | 
				    color: #c0c4cc; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .btn-prev, | 
			
		||||
 | 
				    .btn-next { | 
			
		||||
 | 
				      background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				      color: #c0c4cc; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &:disabled { | 
			
		||||
 | 
				        background-color: rgba(25, 22, 104, 0.4); | 
			
		||||
 | 
				        color: rgba(192, 196, 204, 0.5); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-pager li { | 
			
		||||
 | 
				      background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				      color: #c0c4cc; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &.active { | 
			
		||||
 | 
				        background-color: #1976d2; | 
			
		||||
 | 
				        color: #ffffff; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &:hover { | 
			
		||||
 | 
				        color: #64b5f6; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-pagination__total, | 
			
		||||
 | 
				    .el-pagination__jump { | 
			
		||||
 | 
				      color: #c0c4cc; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-pagination__sizes { | 
			
		||||
 | 
				      .el-input { | 
			
		||||
 | 
				        .el-input__inner { | 
			
		||||
 | 
				          background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				          border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				          color: #c0c4cc; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-pagination__editor { | 
			
		||||
 | 
				      &.el-input { | 
			
		||||
 | 
				        .el-input__inner { | 
			
		||||
 | 
				          background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				          border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				          color: #c0c4cc; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,30 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    <i v-if="isElIcon" :class="[icon, className]" ></i> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    <svg-icon v-else :icon-class="icon" :class-name="className" /> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  name: "AnyIcons", | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    icon: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: "", | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    className: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: "", | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  computed: { | 
			
		||||
 | 
				    isElIcon() { | 
			
		||||
 | 
				      return this.icon.indexOf("el-icon-") == 0; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style lang="scss" scoped></style> | 
			
		||||
@ -0,0 +1,62 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" /> | 
			
		||||
 | 
				  <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners"> | 
			
		||||
 | 
				    <use :xlink:href="iconName" /> | 
			
		||||
 | 
				  </svg> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage | 
			
		||||
 | 
				import { isExternal } from '@/utils/validate' | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  name: 'SvgIcon', | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    iconClass: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      required: true | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    className: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: '' | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  computed: { | 
			
		||||
 | 
				    isExternal() { | 
			
		||||
 | 
				      return isExternal(this.iconClass) | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    iconName() { | 
			
		||||
 | 
				      return `#icon-${this.iconClass}` | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    svgClass() { | 
			
		||||
 | 
				      if (this.className) { | 
			
		||||
 | 
				        return 'svg-icon ' + this.className | 
			
		||||
 | 
				      } else { | 
			
		||||
 | 
				        return 'svg-icon' | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    styleExternalIcon() { | 
			
		||||
 | 
				      return { | 
			
		||||
 | 
				        mask: `url(${this.iconClass}) no-repeat 50% 50%`, | 
			
		||||
 | 
				        '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%` | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style scoped> | 
			
		||||
 | 
				.svg-icon { | 
			
		||||
 | 
				  width: 1em; | 
			
		||||
 | 
				  height: 1em; | 
			
		||||
 | 
				  vertical-align: -0.15em; | 
			
		||||
 | 
				  fill: currentColor; | 
			
		||||
 | 
				  overflow: hidden; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.svg-external-icon { | 
			
		||||
 | 
				  background-color: currentColor; | 
			
		||||
 | 
				  mask-size: cover!important; | 
			
		||||
 | 
				  display: inline-block; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,886 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <div | 
			
		||||
 | 
				ref="container" class="container" | 
			
		||||
 | 
				    style="width: 100%; height: 100%; background-color: #000000; margin: 0 auto" @dblclick="fullscreenSwich"> | 
			
		||||
 | 
				    <div id="buttonsBox" class="buttons-box"> | 
			
		||||
 | 
				      <div class="buttons-box-left"> | 
			
		||||
 | 
				        <i v-if="!playing" class="iconfont icon-play jessibuca-btn" @click="playBtnClick"></i> | 
			
		||||
 | 
				        <i v-if="playing" class="iconfont icon-pause jessibuca-btn" @click="pause"></i> | 
			
		||||
 | 
				        <i class="iconfont icon-stop jessibuca-btn" @click="destroy"></i> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				      <div class="buttons-box-right"> | 
			
		||||
 | 
				        <i class="iconfont icon-shuaxin11 jessibuca-btn" @click="playBtnClick"></i> | 
			
		||||
 | 
				        <i v-if="!fullscreen" class="iconfont icon-weibiaoti10 jessibuca-btn" @click="fullscreenSwich"></i> | 
			
		||||
 | 
				        <i v-if="fullscreen" class="iconfont icon-weibiaoti11 jessibuca-btn" @click="fullscreenSwich"></i> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				    <div v-if="ptzControl" class="ptzControl" @dblclick.stop> | 
			
		||||
 | 
				      <div class="control-wrapper"> | 
			
		||||
 | 
				        <template> | 
			
		||||
 | 
				          <div | 
			
		||||
 | 
				ref="tooltipWrap" class="control-btn control-top" @mousedown="ptzCamera('up')" | 
			
		||||
 | 
				            @mouseup="ptzCamera('stop')"> | 
			
		||||
 | 
				            <el-tooltip class="item" effect="dark" content="向上移动" placement="top-start"> | 
			
		||||
 | 
				              <i class="el-icon-caret-top"></i> | 
			
		||||
 | 
				            </el-tooltip> | 
			
		||||
 | 
				            <div class="control-inner-btn control-inner"></div> | 
			
		||||
 | 
				          </div> | 
			
		||||
 | 
				          <div class="control-btn control-left" @mousedown="ptzCamera('left')" @mouseup="ptzCamera('stop')"> | 
			
		||||
 | 
				            <el-tooltip class="item" effect="dark" content="向左移动" placement="left-start"> | 
			
		||||
 | 
				              <i class="el-icon-caret-left"></i> | 
			
		||||
 | 
				            </el-tooltip> | 
			
		||||
 | 
				            <div class="control-inner-btn control-inner"></div> | 
			
		||||
 | 
				          </div> | 
			
		||||
 | 
				          <div class="control-btn control-bottom" @mousedown="ptzCamera('down')" @mouseup="ptzCamera('stop')"> | 
			
		||||
 | 
				            <el-tooltip class="item" effect="dark" content="向下移动" placement="bottom-start"> | 
			
		||||
 | 
				              <i class="el-icon-caret-bottom"></i> | 
			
		||||
 | 
				            </el-tooltip> | 
			
		||||
 | 
				            <div class="control-inner-btn control-inner"></div> | 
			
		||||
 | 
				          </div> | 
			
		||||
 | 
				          <div class="control-btn control-right" @mousedown="ptzCamera('right')" @mouseup="ptzCamera('stop')"> | 
			
		||||
 | 
				            <el-tooltip class="item" effect="dark" content="向右移动" placement="right-start"> | 
			
		||||
 | 
				              <i class="el-icon-caret-right"></i> | 
			
		||||
 | 
				            </el-tooltip> | 
			
		||||
 | 
				            <div class="control-inner-btn control-inner"></div> | 
			
		||||
 | 
				          </div> | 
			
		||||
 | 
				          <div class="control-round"> | 
			
		||||
 | 
				            <div class="control-round-inner"> | 
			
		||||
 | 
				              <i class="fa fa-pause-circle"></i> | 
			
		||||
 | 
				            </div> | 
			
		||||
 | 
				          </div> | 
			
		||||
 | 
				        </template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        <div | 
			
		||||
 | 
				style="position: absolute; left: 8.25rem; top: 0rem; color: #78aee4" @mousedown="ptzCamera('zoomin')" | 
			
		||||
 | 
				          @mouseup="ptzCamera('stop')"> | 
			
		||||
 | 
				          <el-tooltip class="item" effect="dark" content="放大" placement="right"> | 
			
		||||
 | 
				            <i class="el-icon-zoom-in control-zoom-btn" style="font-size: 1.875rem"></i> | 
			
		||||
 | 
				          </el-tooltip> | 
			
		||||
 | 
				        </div> | 
			
		||||
 | 
				        <div | 
			
		||||
 | 
				style="position: absolute; left: 8.25rem; top: 4rem; font-size: 1.875rem; color: #78aee4" | 
			
		||||
 | 
				          @mousedown="ptzCamera('zoomout')" @mouseup="ptzCamera('stop')"> | 
			
		||||
 | 
				          <el-tooltip class="item" effect="dark" content="缩小" placement="right"> | 
			
		||||
 | 
				            <i class="el-icon-zoom-out control-zoom-btn"></i> | 
			
		||||
 | 
				          </el-tooltip> | 
			
		||||
 | 
				        </div> | 
			
		||||
 | 
				        <el-tooltip class="item" effect="dark" content="移动速度控制" placement="top"> | 
			
		||||
 | 
				          <div class="contro-speed" style="position: absolute; left: 100px; top: 0rem; width: 1rem; height: 7rem"> | 
			
		||||
 | 
				            <el-slider v-model="controSpeed" vertical height="6rem" :max="100" type="vertical"></el-slider> | 
			
		||||
 | 
				          </div> | 
			
		||||
 | 
				        </el-tooltip> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				import { setChannelPTZ } from "@/api/video.js"; | 
			
		||||
 | 
				function getCurrentIPAndPortOrDomain() { | 
			
		||||
 | 
				  var ipAndPort = ""; | 
			
		||||
 | 
				  // 如果端口是80或443,则默认端口,无需显示在 URL 中 | 
			
		||||
 | 
				  if (window.location.port === "80" || window.location.port === "443") { | 
			
		||||
 | 
				    ipAndPort = window.location.hostname; | 
			
		||||
 | 
				  } else { | 
			
		||||
 | 
				    ipAndPort = window.location.hostname + ":" + window.location.port; | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  return ipAndPort; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				let jessibucaPlayer = {}; | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  name: "Player", | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    video: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => ({}), | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      playing: false, | 
			
		||||
 | 
				      fullscreen: false, | 
			
		||||
 | 
				      loaded: false, | 
			
		||||
 | 
				      speed: 0, | 
			
		||||
 | 
				      performance: "", // 工作情况 | 
			
		||||
 | 
				      videoUrl: "", | 
			
		||||
 | 
				      btnDom: null, | 
			
		||||
 | 
				      volume: 1, | 
			
		||||
 | 
				      rotate: 0, | 
			
		||||
 | 
				      ptzControl: false, | 
			
		||||
 | 
				      forceNoOffscreen: false, | 
			
		||||
 | 
				      controSpeed: 30, | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  watch: { | 
			
		||||
 | 
				    video: { | 
			
		||||
 | 
				      handler(val) { | 
			
		||||
 | 
				        if (val.deviceId) { | 
			
		||||
 | 
				          this.$nextTick(() => { | 
			
		||||
 | 
				            this.play(); | 
			
		||||
 | 
				          }); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      deep: true, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  mounted() { | 
			
		||||
 | 
				    this.$nextTick(() => { | 
			
		||||
 | 
				      this.updatePlayerDomSize(); | 
			
		||||
 | 
				      window.onresize = () => { | 
			
		||||
 | 
				        this.updatePlayerDomSize(); | 
			
		||||
 | 
				      }; | 
			
		||||
 | 
				      this.btnDom = document.getElementById("buttonsBox"); | 
			
		||||
 | 
				      this.play(); | 
			
		||||
 | 
				    }); | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  async destroyed() { | 
			
		||||
 | 
				    if (jessibucaPlayer[this._uid]) { | 
			
		||||
 | 
				      await jessibucaPlayer[this._uid].destroy(); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				    this.playing = false; | 
			
		||||
 | 
				    this.loaded = false; | 
			
		||||
 | 
				    this.performance = ""; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    updatePlayerDomSize() { | 
			
		||||
 | 
				      let dom = this.$refs.container; | 
			
		||||
 | 
				      let width = dom.parentNode.clientWidth; | 
			
		||||
 | 
				      let height = (9 / 16) * width; | 
			
		||||
 | 
				      const clientHeight = Math.min(document.body.clientHeight, document.documentElement.clientHeight); | 
			
		||||
 | 
				      if (height > clientHeight) { | 
			
		||||
 | 
				        height = clientHeight; | 
			
		||||
 | 
				        width = (16 / 9) * height; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      dom.style.width = width + "px"; | 
			
		||||
 | 
				      dom.style.height = height + "px"; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    create() { | 
			
		||||
 | 
				      this._uid = this.video.deviceId; | 
			
		||||
 | 
				      let options = {}; | 
			
		||||
 | 
				      jessibucaPlayer[this._uid] = new window.Jessibuca( | 
			
		||||
 | 
				        Object.assign( | 
			
		||||
 | 
				          { | 
			
		||||
 | 
				            container: this.$refs.container, | 
			
		||||
 | 
				            videoBuffer: 0.2, // 最大缓冲时长,单位秒 | 
			
		||||
 | 
				            isResize: true, | 
			
		||||
 | 
				            decoder: "./js/jessibuca/decoder.js", | 
			
		||||
 | 
				            useWCS: false, | 
			
		||||
 | 
				            useMSE: false, | 
			
		||||
 | 
				            autoWasm: true, //推荐配置 | 
			
		||||
 | 
				            useSIMD: true, | 
			
		||||
 | 
				            showBandwidth: false, | 
			
		||||
 | 
				            isFlv: true, | 
			
		||||
 | 
				            loadingText: "", | 
			
		||||
 | 
				            debug: false, | 
			
		||||
 | 
				            supportDblclickFullscreen: false, // 是否支持屏幕的双击事件,触发全屏,取消全屏事件。 | 
			
		||||
 | 
				            operateBtns: { | 
			
		||||
 | 
				              fullscreen: false, | 
			
		||||
 | 
				              screenshot: false, | 
			
		||||
 | 
				              play: false, | 
			
		||||
 | 
				              audio: false, | 
			
		||||
 | 
				              recorder: false, | 
			
		||||
 | 
				            }, | 
			
		||||
 | 
				            record: "record", | 
			
		||||
 | 
				            vod: true, | 
			
		||||
 | 
				            forceNoOffscreen: true, | 
			
		||||
 | 
				            isNotMute: false, | 
			
		||||
 | 
				            timeout: 10, | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				          options | 
			
		||||
 | 
				        ) | 
			
		||||
 | 
				      ); | 
			
		||||
 | 
				      let jessibuca = jessibucaPlayer[this._uid]; | 
			
		||||
 | 
				      jessibuca.on("error", async (err) => { | 
			
		||||
 | 
				        console.log(err); | 
			
		||||
 | 
				        await this.destroy(); | 
			
		||||
 | 
				        this.play(); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				      jessibuca.on("timeout", async (err) => { | 
			
		||||
 | 
				        console.log(err); | 
			
		||||
 | 
				        await this.destroy(); | 
			
		||||
 | 
				        this.play(); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    playBtnClick() { | 
			
		||||
 | 
				      this.play(); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    async play() { | 
			
		||||
 | 
				      const ipAndPort = getCurrentIPAndPortOrDomain(); | 
			
		||||
 | 
				        // 使用原有系统的播放地址 | 
			
		||||
 | 
				      this.videoUrl = "ws://" + ipAndPort + "/play/" + this.video.deviceId + '_' + this.video.channelId + ".live.flv"; | 
			
		||||
 | 
				      this.create(); | 
			
		||||
 | 
				      jessibucaPlayer[this._uid].on("play", () => { | 
			
		||||
 | 
				        this.playing = true; | 
			
		||||
 | 
				        this.loaded = true; | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				      if (jessibucaPlayer[this._uid].hasLoaded()) { | 
			
		||||
 | 
				        jessibucaPlayer[this._uid].play(this.videoUrl); | 
			
		||||
 | 
				      } else { | 
			
		||||
 | 
				        jessibucaPlayer[this._uid].on("load", () => { | 
			
		||||
 | 
				          jessibucaPlayer[this._uid].play(this.videoUrl); | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    pause() { | 
			
		||||
 | 
				      if (jessibucaPlayer[this._uid]) { | 
			
		||||
 | 
				        jessibucaPlayer[this._uid].pause(); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      this.playing = false; | 
			
		||||
 | 
				      this.err = ""; | 
			
		||||
 | 
				      this.performance = ""; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    async destroy() { | 
			
		||||
 | 
				      if (jessibucaPlayer[this._uid]) { | 
			
		||||
 | 
				        await jessibucaPlayer[this._uid].destroy(); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      if (document.getElementById("buttonsBox") == null) { | 
			
		||||
 | 
				        this.$refs.container.appendChild(this.btnDom); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      jessibucaPlayer[this._uid] = null; | 
			
		||||
 | 
				      this.playing = false; | 
			
		||||
 | 
				      this.err = ""; | 
			
		||||
 | 
				      this.performance = ""; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    fullscreenSwich() { | 
			
		||||
 | 
				      let isFull = this.isFullscreen(); | 
			
		||||
 | 
				      jessibucaPlayer[this._uid].setFullscreen(!isFull); | 
			
		||||
 | 
				      this.fullscreen = !isFull; | 
			
		||||
 | 
				      this.ptzControl = false; | 
			
		||||
 | 
				      if (isFull) { | 
			
		||||
 | 
				        this.$emit('outFullscreen', this.index); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    isFullscreen() { | 
			
		||||
 | 
				      return ( | 
			
		||||
 | 
				        document.fullscreenElement || | 
			
		||||
 | 
				        document.msFullscreenElement || | 
			
		||||
 | 
				        document.mozFullScreenElement || | 
			
		||||
 | 
				        document.webkitFullscreenElement || | 
			
		||||
 | 
				        false | 
			
		||||
 | 
				      ); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    changePTZControl() { | 
			
		||||
 | 
				      this.ptzControl = !this.ptzControl; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    ptzCamera(command) { | 
			
		||||
 | 
				      if (this.isEzvizDevice) { | 
			
		||||
 | 
				        // 萤石云设备的云台控制 | 
			
		||||
 | 
				        setChannelPTZ({ | 
			
		||||
 | 
				          deviceType: 'ezviz', | 
			
		||||
 | 
				          accessToken: this.accessToken, | 
			
		||||
 | 
				          deviceSerial: this.deviceSerial, | 
			
		||||
 | 
				          direction: command, | 
			
		||||
 | 
				          speed: this.controSpeed | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      } else { | 
			
		||||
 | 
				        // 原有系统的云台控制 | 
			
		||||
 | 
				        setChannelPTZ({ | 
			
		||||
 | 
				          cameraIp: this.video.ip, | 
			
		||||
 | 
				          direction: command, | 
			
		||||
 | 
				          speed: this.controSpeed, | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style> | 
			
		||||
 | 
				.jessibuca-btn { | 
			
		||||
 | 
				  width: 20px; | 
			
		||||
 | 
				  color: rgb(255, 255, 255); | 
			
		||||
 | 
				  line-height: 27px; | 
			
		||||
 | 
				  margin: 0px 10px; | 
			
		||||
 | 
				  padding: 0px 2px; | 
			
		||||
 | 
				  cursor: pointer; | 
			
		||||
 | 
				  text-align: center; | 
			
		||||
 | 
				  font-size: 0.8rem !important; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.buttons-box-right { | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  right: 0; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.container { | 
			
		||||
 | 
				  width: 100%; | 
			
		||||
 | 
				  height: 100%; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .buttons-box { | 
			
		||||
 | 
				    width: 100%; | 
			
		||||
 | 
				    height: 28px; | 
			
		||||
 | 
				    position: absolute; | 
			
		||||
 | 
				    display: -webkit-box; | 
			
		||||
 | 
				    display: -ms-flexbox; | 
			
		||||
 | 
				    display: flex; | 
			
		||||
 | 
				    left: 0; | 
			
		||||
 | 
				    bottom: 0; | 
			
		||||
 | 
				    user-select: none; | 
			
		||||
 | 
				    z-index: 10; | 
			
		||||
 | 
				    overflow: hidden; | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.turn-left { | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  left: 0; | 
			
		||||
 | 
				  top: 10%; | 
			
		||||
 | 
				  width: 10%; | 
			
		||||
 | 
				  height: 80%; | 
			
		||||
 | 
				  cursor: pointer; | 
			
		||||
 | 
				  z-index: 999; | 
			
		||||
 | 
				  background-color: transparent; | 
			
		||||
 | 
				  /* 初始背景色为透明 */ | 
			
		||||
 | 
				  transition: background-color 0.3s ease; | 
			
		||||
 | 
				  /* 平滑的过渡效果 */ | 
			
		||||
 | 
				  overflow: hidden; | 
			
		||||
 | 
				  /* 隐藏超出部分 */ | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.turn-left::after { | 
			
		||||
 | 
				  content: ""; | 
			
		||||
 | 
				  /* 伪元素需要content属性 */ | 
			
		||||
 | 
				  border: 10px solid transparent; | 
			
		||||
 | 
				  /* 创建箭头形状 */ | 
			
		||||
 | 
				  border-right-color: transparent; | 
			
		||||
 | 
				  /* 初始状态透明 */ | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  left: 50%; | 
			
		||||
 | 
				  /* 位置调整到正中 */ | 
			
		||||
 | 
				  top: 50%; | 
			
		||||
 | 
				  /* 位置调整到正中 */ | 
			
		||||
 | 
				  transform: translate(-50%, -50%) rotate(180deg); | 
			
		||||
 | 
				  /* 精确居中调整 */ | 
			
		||||
 | 
				  transition: border-right-color 0.3s; | 
			
		||||
 | 
				  /* 箭头颜色渐变 */ | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.turn-left:hover { | 
			
		||||
 | 
				  background-color: rgba(255, 255, 255, 0.5); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.turn-left:hover::after { | 
			
		||||
 | 
				  border-left-color: black; | 
			
		||||
 | 
				  /* 悬停时显示箭头 */ | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.turn-right { | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  right: 0; | 
			
		||||
 | 
				  top: 10%; | 
			
		||||
 | 
				  width: 10%; | 
			
		||||
 | 
				  height: 80%; | 
			
		||||
 | 
				  background-color: transparent; | 
			
		||||
 | 
				  /* 初始背景色为透明 */ | 
			
		||||
 | 
				  transition: background-color 0.3s ease; | 
			
		||||
 | 
				  /* 平滑的过渡效果 */ | 
			
		||||
 | 
				  cursor: pointer; | 
			
		||||
 | 
				  z-index: 999; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.turn-right::after { | 
			
		||||
 | 
				  content: ""; | 
			
		||||
 | 
				  /* 伪元素需要content属性 */ | 
			
		||||
 | 
				  border: 10px solid transparent; | 
			
		||||
 | 
				  /* 创建箭头形状 */ | 
			
		||||
 | 
				  border-left-color: transparent; | 
			
		||||
 | 
				  /* 初始状态透明 */ | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  right: 50%; | 
			
		||||
 | 
				  /* 位置调整到正中 */ | 
			
		||||
 | 
				  top: 50%; | 
			
		||||
 | 
				  /* 位置调整到正中 */ | 
			
		||||
 | 
				  transform: translate(50%, -50%); | 
			
		||||
 | 
				  /* 精确居中调整 */ | 
			
		||||
 | 
				  transition: border-left-color 0.3s; | 
			
		||||
 | 
				  /* 箭头颜色渐变 */ | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.turn-right:hover { | 
			
		||||
 | 
				  background-color: rgba(255, 255, 255, 0.5); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.turn-right:hover::after { | 
			
		||||
 | 
				  border-left-color: black; | 
			
		||||
 | 
				  /* 悬停时显示箭头 */ | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-btn { | 
			
		||||
 | 
				  display: flex; | 
			
		||||
 | 
				  justify-content: center; | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  width: 44%; | 
			
		||||
 | 
				  height: 44%; | 
			
		||||
 | 
				  border-radius: 5px; | 
			
		||||
 | 
				  border: 1px solid #78aee4; | 
			
		||||
 | 
				  box-sizing: border-box; | 
			
		||||
 | 
				  transition: all 0.3s linear; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-btn:hover { | 
			
		||||
 | 
				  cursor: pointer; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-btn i { | 
			
		||||
 | 
				  font-size: 20px; | 
			
		||||
 | 
				  color: #78aee4; | 
			
		||||
 | 
				  display: flex; | 
			
		||||
 | 
				  justify-content: center; | 
			
		||||
 | 
				  align-items: center; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-btn i:hover { | 
			
		||||
 | 
				  cursor: pointer; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-wrapper { | 
			
		||||
 | 
				  /* background-color: #fff; */ | 
			
		||||
 | 
				  position: relative; | 
			
		||||
 | 
				  width: 6.25rem; | 
			
		||||
 | 
				  height: 6.25rem; | 
			
		||||
 | 
				  max-width: 6.25rem; | 
			
		||||
 | 
				  max-height: 6.25rem; | 
			
		||||
 | 
				  border-radius: 100%; | 
			
		||||
 | 
				  margin-top: 1.5rem; | 
			
		||||
 | 
				  margin-left: 0.5rem; | 
			
		||||
 | 
				  float: left; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.ptzControl { | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  bottom: 10%; | 
			
		||||
 | 
				  left: 10%; | 
			
		||||
 | 
				  width: 100%; | 
			
		||||
 | 
				  height: 30%; | 
			
		||||
 | 
				  background-color: rgba(0, 0, 0, 0); | 
			
		||||
 | 
				  display: flex; | 
			
		||||
 | 
				  /* justify-content: center; */ | 
			
		||||
 | 
				  align-items: center; | 
			
		||||
 | 
				  z-index: 999; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-wrapper { | 
			
		||||
 | 
				  position: relative; | 
			
		||||
 | 
				  width: 6.25rem; | 
			
		||||
 | 
				  height: 6.25rem; | 
			
		||||
 | 
				  max-width: 6.25rem; | 
			
		||||
 | 
				  max-height: 6.25rem; | 
			
		||||
 | 
				  border-radius: 100%; | 
			
		||||
 | 
				  margin-top: 1.5rem; | 
			
		||||
 | 
				  margin-left: 0.5rem; | 
			
		||||
 | 
				  float: left; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-panel { | 
			
		||||
 | 
				  position: relative; | 
			
		||||
 | 
				  top: 0; | 
			
		||||
 | 
				  left: 5rem; | 
			
		||||
 | 
				  height: 11rem; | 
			
		||||
 | 
				  max-height: 11rem; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-btn { | 
			
		||||
 | 
				  display: flex; | 
			
		||||
 | 
				  justify-content: center; | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  width: 44%; | 
			
		||||
 | 
				  height: 44%; | 
			
		||||
 | 
				  border-radius: 5px; | 
			
		||||
 | 
				  border: 1px solid #78aee4; | 
			
		||||
 | 
				  box-sizing: border-box; | 
			
		||||
 | 
				  transition: all 0.3s linear; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-btn:hover { | 
			
		||||
 | 
				  cursor: pointer; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-btn i { | 
			
		||||
 | 
				  font-size: 20px; | 
			
		||||
 | 
				  color: #78aee4; | 
			
		||||
 | 
				  display: flex; | 
			
		||||
 | 
				  justify-content: center; | 
			
		||||
 | 
				  align-items: center; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-btn i:hover { | 
			
		||||
 | 
				  cursor: pointer; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-zoom-btn:hover { | 
			
		||||
 | 
				  cursor: pointer; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-round { | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  top: 21%; | 
			
		||||
 | 
				  left: 21%; | 
			
		||||
 | 
				  width: 58%; | 
			
		||||
 | 
				  height: 58%; | 
			
		||||
 | 
				  /* background: #fff; */ | 
			
		||||
 | 
				  border-radius: 100%; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-round-inner { | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  left: 13%; | 
			
		||||
 | 
				  top: 13%; | 
			
		||||
 | 
				  display: flex; | 
			
		||||
 | 
				  justify-content: center; | 
			
		||||
 | 
				  align-items: center; | 
			
		||||
 | 
				  width: 70%; | 
			
		||||
 | 
				  height: 70%; | 
			
		||||
 | 
				  font-size: 40px; | 
			
		||||
 | 
				  color: #78aee4; | 
			
		||||
 | 
				  border: 1px solid #78aee4; | 
			
		||||
 | 
				  border-radius: 100%; | 
			
		||||
 | 
				  transition: all 0.3s linear; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-inner-btn { | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  width: 60%; | 
			
		||||
 | 
				  height: 60%; | 
			
		||||
 | 
				  background: rgba(0, 0, 0, 0); | 
			
		||||
 | 
				  visibility: hidden; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-top { | 
			
		||||
 | 
				  top: -8%; | 
			
		||||
 | 
				  left: 27%; | 
			
		||||
 | 
				  transform: rotate(-45deg); | 
			
		||||
 | 
				  border-radius: 5px 100% 5px 0; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-top i { | 
			
		||||
 | 
				  transform: rotate(45deg); | 
			
		||||
 | 
				  border-radius: 5px 100% 5px 0; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-top .control-inner { | 
			
		||||
 | 
				  left: -1px; | 
			
		||||
 | 
				  bottom: 0; | 
			
		||||
 | 
				  border-top: 1px solid #78aee4; | 
			
		||||
 | 
				  border-right: 1px solid #78aee4; | 
			
		||||
 | 
				  border-radius: 0 100% 0 0; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-top .fa { | 
			
		||||
 | 
				  transform: rotate(45deg) translateY(-7px); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-left { | 
			
		||||
 | 
				  top: 27%; | 
			
		||||
 | 
				  left: -8%; | 
			
		||||
 | 
				  transform: rotate(45deg); | 
			
		||||
 | 
				  border-radius: 5px 0 5px 100%; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-left i { | 
			
		||||
 | 
				  transform: rotate(-45deg); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-left .control-inner { | 
			
		||||
 | 
				  right: -1px; | 
			
		||||
 | 
				  top: -1px; | 
			
		||||
 | 
				  border-bottom: 1px solid #78aee4; | 
			
		||||
 | 
				  border-left: 1px solid #78aee4; | 
			
		||||
 | 
				  border-radius: 0 0 0 100%; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-left .fa { | 
			
		||||
 | 
				  transform: rotate(-45deg) translateX(-7px); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-right { | 
			
		||||
 | 
				  top: 27%; | 
			
		||||
 | 
				  right: -8%; | 
			
		||||
 | 
				  transform: rotate(45deg); | 
			
		||||
 | 
				  border-radius: 5px 100% 5px 0; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-right i { | 
			
		||||
 | 
				  transform: rotate(-45deg); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-right .control-inner { | 
			
		||||
 | 
				  left: -1px; | 
			
		||||
 | 
				  bottom: -1px; | 
			
		||||
 | 
				  border-top: 1px solid #78aee4; | 
			
		||||
 | 
				  border-right: 1px solid #78aee4; | 
			
		||||
 | 
				  border-radius: 0 100% 0 0; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-right .fa { | 
			
		||||
 | 
				  transform: rotate(-45deg) translateX(7px); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-bottom { | 
			
		||||
 | 
				  left: 27%; | 
			
		||||
 | 
				  bottom: -8%; | 
			
		||||
 | 
				  transform: rotate(45deg); | 
			
		||||
 | 
				  border-radius: 0 5px 100% 5px; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-bottom i { | 
			
		||||
 | 
				  transform: rotate(-45deg); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-bottom .control-inner { | 
			
		||||
 | 
				  top: -1px; | 
			
		||||
 | 
				  left: -1px; | 
			
		||||
 | 
				  border-bottom: 1px solid #78aee4; | 
			
		||||
 | 
				  border-right: 1px solid #78aee4; | 
			
		||||
 | 
				  border-radius: 0 0 100% 0; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.control-bottom .fa { | 
			
		||||
 | 
				  transform: rotate(-45deg) translateY(7px); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.trank { | 
			
		||||
 | 
				  width: 80%; | 
			
		||||
 | 
				  height: 180px; | 
			
		||||
 | 
				  text-align: left; | 
			
		||||
 | 
				  padding: 0 10%; | 
			
		||||
 | 
				  overflow: auto; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.trankInfo { | 
			
		||||
 | 
				  width: 80%; | 
			
		||||
 | 
				  padding: 0 10%; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.location { | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  display: flex; | 
			
		||||
 | 
				  width: 100%; | 
			
		||||
 | 
				  text-align: center; | 
			
		||||
 | 
				  align-items: center; | 
			
		||||
 | 
				  justify-content: center; | 
			
		||||
 | 
				  top: 0; | 
			
		||||
 | 
				  left: 0; | 
			
		||||
 | 
				  color: #fff; | 
			
		||||
 | 
				  font-size: 1rem; | 
			
		||||
 | 
				  padding: 0.5rem; | 
			
		||||
 | 
				  background-color: rgba(0, 0, 0, 0.1); | 
			
		||||
 | 
				  z-index: 999; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .cruise-name { | 
			
		||||
 | 
				    flex: 1; | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .current-cruise { | 
			
		||||
 | 
				    color: #fff; | 
			
		||||
 | 
				    background-color: rgb(255, 234, 0); | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .past-cruise { | 
			
		||||
 | 
				    color: #fff; | 
			
		||||
 | 
				    background-color: rgba(73, 196, 77, 0.5); | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .future-cruise { | 
			
		||||
 | 
				    color: #fff; | 
			
		||||
 | 
				    background-color: rgba(255, 255, 255, 0.3); | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.cruise { | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  bottom: 30px; | 
			
		||||
 | 
				  right: 10px; | 
			
		||||
 | 
				  color: #fff; | 
			
		||||
 | 
				  font-size: 1rem; | 
			
		||||
 | 
				  padding: 0.5rem; | 
			
		||||
 | 
				  z-index: 999; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.report { | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  z-index: 9; | 
			
		||||
 | 
				  right: 30px; | 
			
		||||
 | 
				  bottom: 30px; | 
			
		||||
 | 
				  color: #fff; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.rules { | 
			
		||||
 | 
				  border: 1px solid #78aee4; | 
			
		||||
 | 
				  padding: 10px; | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  z-index: 999; | 
			
		||||
 | 
				  right: 30px; | 
			
		||||
 | 
				  top: 60px; | 
			
		||||
 | 
				  background-color: rgba(0, 0, 0, 0.5); | 
			
		||||
 | 
				  color: #fff; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.undoTask { | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  z-index: 99999; | 
			
		||||
 | 
				  right: 140px; | 
			
		||||
 | 
				  bottom: 160px; | 
			
		||||
 | 
				  background-color: rgba(0, 0, 0, 0.7); | 
			
		||||
 | 
				  width: 300px; | 
			
		||||
 | 
				  border-radius: 10px; | 
			
		||||
 | 
				  box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); | 
			
		||||
 | 
				  transition: all 0.3s ease; | 
			
		||||
 | 
				  border: 1px solid rgba(120, 174, 228, 0.5); | 
			
		||||
 | 
				  overflow: hidden; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .undoTask-header { | 
			
		||||
 | 
				    padding: 8px 12px; | 
			
		||||
 | 
				    background-color: rgba(120, 174, 228, 0.2); | 
			
		||||
 | 
				    color: #fff; | 
			
		||||
 | 
				    font-size: 14px; | 
			
		||||
 | 
				    cursor: pointer; | 
			
		||||
 | 
				    display: flex; | 
			
		||||
 | 
				    justify-content: space-between; | 
			
		||||
 | 
				    align-items: center; | 
			
		||||
 | 
				    border-bottom: 1px solid rgba(120, 174, 228, 0.3); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    &:hover { | 
			
		||||
 | 
				      background-color: rgba(120, 174, 228, 0.3); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    i { | 
			
		||||
 | 
				      font-size: 16px; | 
			
		||||
 | 
				      transition: transform 0.3s; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .undoTask-content { | 
			
		||||
 | 
				    max-height: 250px; | 
			
		||||
 | 
				    overflow-y: auto; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /* 自定义滚动条样式 */ | 
			
		||||
 | 
				    &::-webkit-scrollbar { | 
			
		||||
 | 
				      width: 6px; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    &::-webkit-scrollbar-track { | 
			
		||||
 | 
				      background: rgba(0, 0, 0, 0.1); | 
			
		||||
 | 
				      border-radius: 3px; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    &::-webkit-scrollbar-thumb { | 
			
		||||
 | 
				      background: rgba(120, 174, 228, 0.7); | 
			
		||||
 | 
				      border-radius: 3px; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    &::-webkit-scrollbar-thumb:hover { | 
			
		||||
 | 
				      background: rgba(120, 174, 228, 1); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .undoTask-item { | 
			
		||||
 | 
				    border-bottom: 1px solid rgba(120, 174, 228, 0.2); | 
			
		||||
 | 
				    padding: 8px 0; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    &:last-child { | 
			
		||||
 | 
				      border-bottom: none; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .undoTask-item-title { | 
			
		||||
 | 
				    display: flex; | 
			
		||||
 | 
				    align-items: center; | 
			
		||||
 | 
				    padding: 4px 12px; | 
			
		||||
 | 
				    color: #fff; | 
			
		||||
 | 
				    font-size: 13px; | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .undoTask-item-info { | 
			
		||||
 | 
				    display: flex; | 
			
		||||
 | 
				    justify-content: space-between; | 
			
		||||
 | 
				    align-items: center; | 
			
		||||
 | 
				    padding: 0 12px 4px; | 
			
		||||
 | 
				    font-size: 12px; | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .undoTask-time { | 
			
		||||
 | 
				    color: #bbb; | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .undoTask-status { | 
			
		||||
 | 
				    padding: 1px 6px; | 
			
		||||
 | 
				    border-radius: 10px; | 
			
		||||
 | 
				    font-size: 11px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    &.status-pending { | 
			
		||||
 | 
				      background-color: #E6A23C; | 
			
		||||
 | 
				      color: #fff; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    &.status-processing { | 
			
		||||
 | 
				      background-color: #409EFF; | 
			
		||||
 | 
				      color: #fff; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .undoTask-empty { | 
			
		||||
 | 
				    padding: 20px; | 
			
		||||
 | 
				    text-align: center; | 
			
		||||
 | 
				    color: #999; | 
			
		||||
 | 
				    font-size: 14px; | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.fade-enter-active, | 
			
		||||
 | 
				.fade-leave-active { | 
			
		||||
 | 
				  transition: opacity 0.3s, max-height 0.3s ease; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.fade-enter, | 
			
		||||
 | 
				.fade-leave-to { | 
			
		||||
 | 
				  opacity: 0; | 
			
		||||
 | 
				  max-height: 0; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.popper-class-top { | 
			
		||||
 | 
				  color: red !important; | 
			
		||||
 | 
				  transform: rotate(45deg); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.fullscreen-loading { | 
			
		||||
 | 
				  z-index: 9999999 !important; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.fullscreen-loading .el-loading-mask { | 
			
		||||
 | 
				  position: fixed !important; | 
			
		||||
 | 
				  top: 0 !important; | 
			
		||||
 | 
				  left: 0 !important; | 
			
		||||
 | 
				  width: 100vw !important; | 
			
		||||
 | 
				  height: 100vh !important; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				/* 自定义loading样式 */ | 
			
		||||
 | 
				.custom-loading-mask { | 
			
		||||
 | 
				  position: fixed; | 
			
		||||
 | 
				  top: 0; | 
			
		||||
 | 
				  left: 0; | 
			
		||||
 | 
				  width: 100vw; | 
			
		||||
 | 
				  height: 100vh; | 
			
		||||
 | 
				  background-color: rgba(0, 0, 0, 0.7); | 
			
		||||
 | 
				  display: flex; | 
			
		||||
 | 
				  justify-content: center; | 
			
		||||
 | 
				  align-items: center; | 
			
		||||
 | 
				  z-index: 999999999; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.custom-loading-spinner { | 
			
		||||
 | 
				  text-align: center; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.custom-loading-spinner i { | 
			
		||||
 | 
				  color: #fff; | 
			
		||||
 | 
				  font-size: 32px; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.custom-loading-text { | 
			
		||||
 | 
				  color: #fff; | 
			
		||||
 | 
				  margin-top: 10px; | 
			
		||||
 | 
				  font-size: 14px; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -1,126 +0,0 @@ | 
			
		|||||
<template> | 
				 | 
			
		||||
  <el-dialog :close-on-click-modal="false" v-if="dialogVisible" v-el-drag-dialog :title="showTitle" :visible.sync="dialogVisible"> | 
				 | 
			
		||||
    <el-form v-if="dialogVisible" ref="editForm" :rules="rules" size="mini" :model="form" label-position="right" | 
				 | 
			
		||||
      label-width="100px"> | 
				 | 
			
		||||
      <el-form-item label="方案名称" prop="name"> | 
				 | 
			
		||||
        <el-input v-model="form.name" type="text" /> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="管径配置" prop="pipeDiameterId"> | 
				 | 
			
		||||
        <el-select v-model="form.pipeDiameterId" placeholder="请选择"> | 
				 | 
			
		||||
          <el-option v-for="item in options.pipeDiameterConfigOptions" :key="item.value" :label="item.label" | 
				 | 
			
		||||
            :value="item.value"></el-option> | 
				 | 
			
		||||
        </el-select> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="排序" prop="sortOrder"> | 
				 | 
			
		||||
        <el-input v-model="form.sortOrder" type="text" /> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="备注" prop="remark"> | 
				 | 
			
		||||
        <el-input v-model="form.remark" type="text" /> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
    </el-form> | 
				 | 
			
		||||
    <div slot="footer" class="dialog-footer"> | 
				 | 
			
		||||
      <el-button @click="dialogVisible = false"> 取消 </el-button> | 
				 | 
			
		||||
      <el-button type="primary" :loading="loading" @click="onSubmit"> | 
				 | 
			
		||||
        确定 | 
				 | 
			
		||||
      </el-button> | 
				 | 
			
		||||
    </div> | 
				 | 
			
		||||
  </el-dialog> | 
				 | 
			
		||||
</template> | 
				 | 
			
		||||
 | 
				 | 
			
		||||
<script> | 
				 | 
			
		||||
export default { | 
				 | 
			
		||||
  props: { | 
				 | 
			
		||||
    title: { | 
				 | 
			
		||||
      type: String, | 
				 | 
			
		||||
      default: "", | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    url: { | 
				 | 
			
		||||
      type: Object, | 
				 | 
			
		||||
      default: () => { | 
				 | 
			
		||||
        return {}; | 
				 | 
			
		||||
      }, | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    options: { | 
				 | 
			
		||||
      type: Object, | 
				 | 
			
		||||
      default: () => { | 
				 | 
			
		||||
        return {}; | 
				 | 
			
		||||
      }, | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
  data() { | 
				 | 
			
		||||
    return { | 
				 | 
			
		||||
      dialogVisible: false, | 
				 | 
			
		||||
 | 
				 | 
			
		||||
      loading: false, | 
				 | 
			
		||||
      form: { | 
				 | 
			
		||||
        id: "", | 
				 | 
			
		||||
        name: "", | 
				 | 
			
		||||
        totalFlow: "", | 
				 | 
			
		||||
        sortOrder: "", | 
				 | 
			
		||||
        remark: "", | 
				 | 
			
		||||
        delFlag: "", | 
				 | 
			
		||||
        createBy: "", | 
				 | 
			
		||||
        createTime: "", | 
				 | 
			
		||||
        updateBy: "", | 
				 | 
			
		||||
        updateTime: "", | 
				 | 
			
		||||
      }, | 
				 | 
			
		||||
      rules: { | 
				 | 
			
		||||
        name: [ | 
				 | 
			
		||||
          { required: true, message: "请输入方案名称", trigger: "blur" }, | 
				 | 
			
		||||
          { min: 1, max: 50, message: "长度在 1 到 50 个字符", trigger: "blur" }, | 
				 | 
			
		||||
        ], | 
				 | 
			
		||||
        pipeDiameterId: [ | 
				 | 
			
		||||
          { required: true, message: "请选择管径配置", trigger: "blur" }, | 
				 | 
			
		||||
        ], | 
				 | 
			
		||||
      }, | 
				 | 
			
		||||
      editType: "add", //add或edit | 
				 | 
			
		||||
    }; | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
  computed: { | 
				 | 
			
		||||
    showTitle() { | 
				 | 
			
		||||
      return this.editType == "edit" | 
				 | 
			
		||||
        ? "编辑" + this.title | 
				 | 
			
		||||
        : "新增" + this.title; | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
  methods: { | 
				 | 
			
		||||
    reset() { | 
				 | 
			
		||||
      this.editType = "add"; | 
				 | 
			
		||||
      // this.$refs.elForm.resetFields(); | 
				 | 
			
		||||
      this.loading = false; | 
				 | 
			
		||||
      this.form = this.$options.data().form; | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    show(form) { | 
				 | 
			
		||||
      this.reset(); | 
				 | 
			
		||||
      if (form) { | 
				 | 
			
		||||
        this.editType = "edit"; | 
				 | 
			
		||||
        this.form = { ...this.$options.data().form, ...form }; | 
				 | 
			
		||||
      } | 
				 | 
			
		||||
      this.dialogVisible = true; | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    onSubmit() { | 
				 | 
			
		||||
      this.$refs.editForm.validate((valid) => { | 
				 | 
			
		||||
        if (!valid) { | 
				 | 
			
		||||
          return false; | 
				 | 
			
		||||
        } | 
				 | 
			
		||||
        this.loading = true; | 
				 | 
			
		||||
        let q; | 
				 | 
			
		||||
        if (this.editType == "edit") { | 
				 | 
			
		||||
          q = this.$axios.put(this.url.edit, this.form); | 
				 | 
			
		||||
        } else { | 
				 | 
			
		||||
          q = this.$axios.post(this.url.add, this.form); | 
				 | 
			
		||||
        } | 
				 | 
			
		||||
        q.then(({ message }) => { | 
				 | 
			
		||||
          this.$message({ type: "info", message: message }); | 
				 | 
			
		||||
          this.dialogVisible = false; | 
				 | 
			
		||||
          this.$emit("refresh"); | 
				 | 
			
		||||
        }).finally(() => { | 
				 | 
			
		||||
          this.loading = false; | 
				 | 
			
		||||
        }); | 
				 | 
			
		||||
      }); | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
}; | 
				 | 
			
		||||
</script> | 
				 | 
			
		||||
 | 
				 | 
			
		||||
<style lang="scss" scoped></style> | 
				 | 
			
		||||
@ -1,169 +0,0 @@ | 
			
		|||||
<template> | 
				 | 
			
		||||
  <el-dialog v-if="dialogVisible" v-el-drag-dialog :title="showTitle" :visible.sync="dialogVisible"> | 
				 | 
			
		||||
    <el-form v-if="dialogVisible" ref="editForm" size="mini" :model="form" label-position="right" label-width="100px" | 
				 | 
			
		||||
      :rules="rules"> | 
				 | 
			
		||||
      <el-form-item label="所属系统" prop="systemId"> | 
				 | 
			
		||||
        <el-select v-model="form.systemId" placeholder="请选择所属系统"> | 
				 | 
			
		||||
          <el-option v-for="item in options.systemOptions" :key="item.value" :label="item.label" | 
				 | 
			
		||||
            :value="item.value"></el-option> | 
				 | 
			
		||||
        </el-select> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="除尘器进口压力" prop="inletPressureDataTagId"> | 
				 | 
			
		||||
        <el-select v-model="form.inletPressureDataTagId" placeholder="请选择除尘器进口压力"> | 
				 | 
			
		||||
          <el-option v-for="item in options.allTagOptions" :key="item.value" :label="item.label" | 
				 | 
			
		||||
            :value="item.value"></el-option> | 
				 | 
			
		||||
        </el-select> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="除尘器出口压力" prop="outletPressureDataTagId"> | 
				 | 
			
		||||
        <el-select v-model="form.outletPressureDataTagId" placeholder="请选择除尘器出口压力"> | 
				 | 
			
		||||
          <el-option v-for="item in options.allTagOptions" :key="item.value" :label="item.label" | 
				 | 
			
		||||
            :value="item.value"></el-option> | 
				 | 
			
		||||
        </el-select> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="风机速度" prop="fanSpeedDataTagId"> | 
				 | 
			
		||||
        <el-select v-model="form.fanSpeedDataTagId" placeholder="请选择风机速度"> | 
				 | 
			
		||||
          <el-option v-for="item in options.allTagOptions" :key="item.value" :label="item.label" | 
				 | 
			
		||||
            :value="item.value"></el-option> | 
				 | 
			
		||||
        </el-select> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="电机电流" prop="motorCurrentDataTagId"> | 
				 | 
			
		||||
        <el-select v-model="form.motorCurrentDataTagId" placeholder="请选择电机电流"> | 
				 | 
			
		||||
          <el-option v-for="item in options.allTagOptions" :key="item.value" :label="item.label" | 
				 | 
			
		||||
            :value="item.value"></el-option> | 
				 | 
			
		||||
        </el-select> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="烟囱CEMS风量" prop="cemsAirVolumeDataTagId"> | 
				 | 
			
		||||
        <el-select v-model="form.cemsAirVolumeDataTagId" placeholder="请选择烟囱CEMS风量"> | 
				 | 
			
		||||
          <el-option v-for="item in options.allTagOptions" :key="item.value" :label="item.label" | 
				 | 
			
		||||
            :value="item.value"></el-option> | 
				 | 
			
		||||
        </el-select> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="粉尘浓度" prop="dustConcentrationDataTagId"> | 
				 | 
			
		||||
        <el-select v-model="form.dustConcentrationDataTagId" placeholder="请选择粉尘浓度"> | 
				 | 
			
		||||
          <el-option v-for="item in options.allTagOptions" :key="item.value" :label="item.label" | 
				 | 
			
		||||
            :value="item.value"></el-option> | 
				 | 
			
		||||
        </el-select> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="风机运行状态" prop="fanStatusDataTagId"> | 
				 | 
			
		||||
        <el-select v-model="form.fanStatusDataTagId" placeholder="请选择风机运行状态"> | 
				 | 
			
		||||
          <el-option v-for="item in options.allTagOptions" :key="item.value" :label="item.label" | 
				 | 
			
		||||
            :value="item.value"></el-option> | 
				 | 
			
		||||
        </el-select> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="排序" prop="sortOrder"> | 
				 | 
			
		||||
        <el-input v-model="form.sortOrder" type="number" /> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="备注" prop="remark"> | 
				 | 
			
		||||
        <el-input v-model="form.remark" type="text" /> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
    </el-form> | 
				 | 
			
		||||
    <div slot="footer" class="dialog-footer"> | 
				 | 
			
		||||
      <el-button @click="dialogVisible = false"> 取消 </el-button> | 
				 | 
			
		||||
      <el-button type="primary" :loading="loading" @click="onSubmit"> | 
				 | 
			
		||||
        确定 | 
				 | 
			
		||||
      </el-button> | 
				 | 
			
		||||
    </div> | 
				 | 
			
		||||
  </el-dialog> | 
				 | 
			
		||||
</template> | 
				 | 
			
		||||
 | 
				 | 
			
		||||
<script> | 
				 | 
			
		||||
export default { | 
				 | 
			
		||||
  props: { | 
				 | 
			
		||||
    title: { | 
				 | 
			
		||||
      type: String, | 
				 | 
			
		||||
      default: "", | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    url: { | 
				 | 
			
		||||
      type: Object, | 
				 | 
			
		||||
      default: () => { | 
				 | 
			
		||||
        return {}; | 
				 | 
			
		||||
      }, | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    options: { | 
				 | 
			
		||||
      type: Object, | 
				 | 
			
		||||
      default: () => { | 
				 | 
			
		||||
        return {}; | 
				 | 
			
		||||
      }, | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
  data() { | 
				 | 
			
		||||
    return { | 
				 | 
			
		||||
 | 
				 | 
			
		||||
      dialogVisible: false, | 
				 | 
			
		||||
 | 
				 | 
			
		||||
      loading: false, | 
				 | 
			
		||||
      form: { | 
				 | 
			
		||||
        systemId: "", | 
				 | 
			
		||||
        inletPressureDataTagId: "", | 
				 | 
			
		||||
        outletPressureDataTagId: "", | 
				 | 
			
		||||
        fanSpeedDataTagId: "", | 
				 | 
			
		||||
        motorCurrentDataTagId: "", | 
				 | 
			
		||||
        cemsAirVolumeDataTagId: "", | 
				 | 
			
		||||
        dustConcentrationDataTagId: "", | 
				 | 
			
		||||
        fanStatusDataTagId: "", | 
				 | 
			
		||||
        sortOrder: "", | 
				 | 
			
		||||
        remark: "", | 
				 | 
			
		||||
        createTime: "", | 
				 | 
			
		||||
        createBy: "", | 
				 | 
			
		||||
        updateTime: "", | 
				 | 
			
		||||
        updateBy: "", | 
				 | 
			
		||||
      }, | 
				 | 
			
		||||
      rules: { | 
				 | 
			
		||||
        systemId: [{ required: true, message: "请选择所属系统", trigger: "blur" }], | 
				 | 
			
		||||
        inletPressureDataTagId: [{ required: true, message: "请选择除尘器进口压力", trigger: "blur" }], | 
				 | 
			
		||||
        outletPressureDataTagId: [{ required: true, message: "请选择除尘器出口压力", trigger: "blur" }], | 
				 | 
			
		||||
        fanSpeedDataTagId: [{ required: true, message: "请选择风机速度", trigger: "blur" }], | 
				 | 
			
		||||
        motorCurrentDataTagId: [{ required: true, message: "请选择电机电流", trigger: "blur" }], | 
				 | 
			
		||||
        cemsAirVolumeDataTagId: [{ required: true, message: "请选择烟囱CEMS风量", trigger: "blur" }], | 
				 | 
			
		||||
        dustConcentrationDataTagId: [{ required: true, message: "请选择粉尘浓度", trigger: "blur" }], | 
				 | 
			
		||||
        fanStatusDataTagId: [{ required: true, message: "请选择风机运行状态", trigger: "blur" }], | 
				 | 
			
		||||
      }, | 
				 | 
			
		||||
      editType: "add", //add或edit | 
				 | 
			
		||||
    }; | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
  computed: { | 
				 | 
			
		||||
    showTitle() { | 
				 | 
			
		||||
      return this.editType == 'edit' ? "编辑" + this.title : "新增" + this.title; | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
  methods: { | 
				 | 
			
		||||
    reset() { | 
				 | 
			
		||||
      this.editType = 'add' | 
				 | 
			
		||||
      // this.$refs.elForm.resetFields(); | 
				 | 
			
		||||
      this.loading = false; | 
				 | 
			
		||||
      this.form = this.$options.data().form; | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    show(form) { | 
				 | 
			
		||||
      this.reset(); | 
				 | 
			
		||||
      if (form) { | 
				 | 
			
		||||
        this.editType = 'edit' | 
				 | 
			
		||||
        this.form = { ...this.$options.data().form, ...form }; | 
				 | 
			
		||||
      } | 
				 | 
			
		||||
      this.dialogVisible = true; | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    onSubmit() { | 
				 | 
			
		||||
      this.$refs.editForm.validate((valid) => { | 
				 | 
			
		||||
        if (!valid) { | 
				 | 
			
		||||
          return false; | 
				 | 
			
		||||
        } | 
				 | 
			
		||||
        this.loading = true; | 
				 | 
			
		||||
        let q; | 
				 | 
			
		||||
        if (this.editType == 'edit') { | 
				 | 
			
		||||
          q = this.$axios.put(this.url.edit, this.form); | 
				 | 
			
		||||
        } else { | 
				 | 
			
		||||
          q = this.$axios.post(this.url.add, this.form); | 
				 | 
			
		||||
        } | 
				 | 
			
		||||
        q.then(({ message }) => { | 
				 | 
			
		||||
          this.$message({ type: "info", message: message }); | 
				 | 
			
		||||
          this.dialogVisible = false; | 
				 | 
			
		||||
          this.$emit("refresh"); | 
				 | 
			
		||||
        }).finally(() => { | 
				 | 
			
		||||
          this.loading = false; | 
				 | 
			
		||||
        }); | 
				 | 
			
		||||
      }); | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
}; | 
				 | 
			
		||||
</script> | 
				 | 
			
		||||
 | 
				 | 
			
		||||
<style lang="scss" scoped></style> | 
				 | 
			
		||||
@ -1,106 +0,0 @@ | 
			
		|||||
<template> | 
				 | 
			
		||||
  <el-dialog v-if="dialogVisible" v-el-drag-dialog :title="showTitle" :visible.sync="dialogVisible"> | 
				 | 
			
		||||
    <el-form v-if="dialogVisible" ref="editForm" size="mini" :model="form" label-position="right" label-width="100px"> | 
				 | 
			
		||||
      <el-form-item label="名称" prop="name"> | 
				 | 
			
		||||
        <el-input v-model="form.name" type="text" /> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="排序" prop="sortOrder"> | 
				 | 
			
		||||
        <el-input v-model="form.sortOrder" type="text" /> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="备注" prop="remark"> | 
				 | 
			
		||||
        <el-input v-model="form.remark" type="text" /> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
    </el-form> | 
				 | 
			
		||||
    <div slot="footer" class="dialog-footer"> | 
				 | 
			
		||||
      <el-button @click="dialogVisible = false"> 取消 </el-button> | 
				 | 
			
		||||
      <el-button type="primary" :loading="loading" @click="onSubmit"> | 
				 | 
			
		||||
        确定 | 
				 | 
			
		||||
      </el-button> | 
				 | 
			
		||||
    </div> | 
				 | 
			
		||||
  </el-dialog> | 
				 | 
			
		||||
</template> | 
				 | 
			
		||||
 | 
				 | 
			
		||||
<script> | 
				 | 
			
		||||
export default { | 
				 | 
			
		||||
  props: { | 
				 | 
			
		||||
    title: { | 
				 | 
			
		||||
      type: String, | 
				 | 
			
		||||
      default: "", | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    url: { | 
				 | 
			
		||||
      type: Object, | 
				 | 
			
		||||
      default: () => { | 
				 | 
			
		||||
        return {}; | 
				 | 
			
		||||
      }, | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    options: { | 
				 | 
			
		||||
      type: Object, | 
				 | 
			
		||||
      default: () => { | 
				 | 
			
		||||
        return {}; | 
				 | 
			
		||||
      }, | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
  data() { | 
				 | 
			
		||||
    return { | 
				 | 
			
		||||
 | 
				 | 
			
		||||
      dialogVisible: false, | 
				 | 
			
		||||
 | 
				 | 
			
		||||
      loading: false, | 
				 | 
			
		||||
      form: { | 
				 | 
			
		||||
        name: "", | 
				 | 
			
		||||
        sortOrder: "", | 
				 | 
			
		||||
        remark: "", | 
				 | 
			
		||||
        createTime: "", | 
				 | 
			
		||||
        createBy: "", | 
				 | 
			
		||||
        updateTime: "", | 
				 | 
			
		||||
        updateBy: "", | 
				 | 
			
		||||
      }, | 
				 | 
			
		||||
      editType: "add", //add或edit | 
				 | 
			
		||||
    }; | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
  computed: { | 
				 | 
			
		||||
    showTitle() { | 
				 | 
			
		||||
      return this.editType == 'edit' ? "编辑" + this.title : "新增" + this.title; | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
  methods: { | 
				 | 
			
		||||
    reset() { | 
				 | 
			
		||||
      this.editType = 'add' | 
				 | 
			
		||||
      // this.$refs.elForm.resetFields(); | 
				 | 
			
		||||
      this.loading = false; | 
				 | 
			
		||||
      this.form = this.$options.data().form; | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    show(form) { | 
				 | 
			
		||||
      this.reset(); | 
				 | 
			
		||||
      if (form) { | 
				 | 
			
		||||
        this.editType = 'edit' | 
				 | 
			
		||||
        this.form = { ...this.$options.data().form, ...form }; | 
				 | 
			
		||||
      } | 
				 | 
			
		||||
      this.dialogVisible = true; | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    onSubmit() { | 
				 | 
			
		||||
      this.$refs.editForm.validate((valid) => { | 
				 | 
			
		||||
        if (!valid) { | 
				 | 
			
		||||
          return false; | 
				 | 
			
		||||
        } | 
				 | 
			
		||||
        this.loading = true; | 
				 | 
			
		||||
        let q; | 
				 | 
			
		||||
        if (this.editType == 'edit') { | 
				 | 
			
		||||
          q = this.$axios.put(this.url.edit, this.form); | 
				 | 
			
		||||
        } else { | 
				 | 
			
		||||
          q = this.$axios.post(this.url.add, this.form); | 
				 | 
			
		||||
        } | 
				 | 
			
		||||
        q.then(({ message }) => { | 
				 | 
			
		||||
          this.$message({ type: "info", message: message }); | 
				 | 
			
		||||
          this.dialogVisible = false; | 
				 | 
			
		||||
          this.$emit("refresh"); | 
				 | 
			
		||||
        }).finally(() => { | 
				 | 
			
		||||
          this.loading = false; | 
				 | 
			
		||||
        }); | 
				 | 
			
		||||
      }); | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
}; | 
				 | 
			
		||||
</script> | 
				 | 
			
		||||
 | 
				 | 
			
		||||
<style lang="scss" scoped></style> | 
				 | 
			
		||||
@ -1,281 +0,0 @@ | 
			
		|||||
<template> | 
				 | 
			
		||||
  <div class="monitor-chart2"> | 
				 | 
			
		||||
    <!-- 旁通阀 --> | 
				 | 
			
		||||
    <div class="bypass-valve"> | 
				 | 
			
		||||
      <div class="valve-container"> | 
				 | 
			
		||||
        <div class="valve-label">旁通阀</div> | 
				 | 
			
		||||
        <div class="valve-icon green"> | 
				 | 
			
		||||
          <img :src="openStatus[0] ? valveOpen : valveClose" /> | 
				 | 
			
		||||
        </div> | 
				 | 
			
		||||
      </div> | 
				 | 
			
		||||
    </div> | 
				 | 
			
		||||
    <div class="dashed-line horizontal-line top-line"></div> | 
				 | 
			
		||||
 | 
				 | 
			
		||||
    <!-- 入口阀门 --> | 
				 | 
			
		||||
    <div class="entry-valve"> | 
				 | 
			
		||||
      <div class="text-box">副原料除尘</div> | 
				 | 
			
		||||
      <div class="valve-container"> | 
				 | 
			
		||||
        <div class="valve-label">入口阀门</div> | 
				 | 
			
		||||
        <div class="valve-icon green"> | 
				 | 
			
		||||
          <img :src="openStatus[1] ? valveOpen : valveClose" /> | 
				 | 
			
		||||
        </div> | 
				 | 
			
		||||
      </div> | 
				 | 
			
		||||
    </div> | 
				 | 
			
		||||
    <div class="dashed-line horizontal-line  bottom-line"></div> | 
				 | 
			
		||||
 | 
				 | 
			
		||||
    <!-- 垂直连接线 --> | 
				 | 
			
		||||
    <div class="dashed-line vertical-line"></div> | 
				 | 
			
		||||
  </div> | 
				 | 
			
		||||
</template> | 
				 | 
			
		||||
 | 
				 | 
			
		||||
<script> | 
				 | 
			
		||||
import valveOpen from '@/assets/monitor/valve-open.svg' | 
				 | 
			
		||||
import valveClose from '@/assets/monitor/valve-close.svg' | 
				 | 
			
		||||
 | 
				 | 
			
		||||
export default { | 
				 | 
			
		||||
  name: 'MonitorChart2', | 
				 | 
			
		||||
  props: { | 
				 | 
			
		||||
    openStatus: { | 
				 | 
			
		||||
      type: Array, | 
				 | 
			
		||||
      default: () => [] | 
				 | 
			
		||||
    } | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
  data() { | 
				 | 
			
		||||
    return { | 
				 | 
			
		||||
      valveOpen, | 
				 | 
			
		||||
      valveClose | 
				 | 
			
		||||
    } | 
				 | 
			
		||||
  } | 
				 | 
			
		||||
} | 
				 | 
			
		||||
</script> | 
				 | 
			
		||||
 | 
				 | 
			
		||||
<style scoped> | 
				 | 
			
		||||
.monitor-chart2 { | 
				 | 
			
		||||
  width: 100%; | 
				 | 
			
		||||
  height: 100%; | 
				 | 
			
		||||
  position: relative; | 
				 | 
			
		||||
  padding: 2%; | 
				 | 
			
		||||
  box-sizing: border-box; | 
				 | 
			
		||||
  min-height: 350px; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.bypass-valve { | 
				 | 
			
		||||
  position: absolute; | 
				 | 
			
		||||
  top: 15%; | 
				 | 
			
		||||
  right: 15%; | 
				 | 
			
		||||
  display: flex; | 
				 | 
			
		||||
  flex-direction: column; | 
				 | 
			
		||||
  align-items: center; | 
				 | 
			
		||||
  z-index: 3; | 
				 | 
			
		||||
  transition: all 0.3s ease; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.bypass-valve:hover { | 
				 | 
			
		||||
  transform: translateY(-3px); | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.entry-valve { | 
				 | 
			
		||||
  position: absolute; | 
				 | 
			
		||||
  bottom: 30%; | 
				 | 
			
		||||
  left: 5%; | 
				 | 
			
		||||
  display: flex; | 
				 | 
			
		||||
  align-items: center; | 
				 | 
			
		||||
  z-index: 3; | 
				 | 
			
		||||
  transition: all 0.3s ease; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.entry-valve:hover { | 
				 | 
			
		||||
  transform: translateX(3px); | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.text-box { | 
				 | 
			
		||||
  background-color: #f0f0f8; | 
				 | 
			
		||||
  color: #1a237e; | 
				 | 
			
		||||
  padding: 2% 3%; | 
				 | 
			
		||||
  border-radius: 4px; | 
				 | 
			
		||||
  font-weight: bold; | 
				 | 
			
		||||
  font-size: 0.9rem; | 
				 | 
			
		||||
  margin-right: 8%; | 
				 | 
			
		||||
  min-width: 150px; | 
				 | 
			
		||||
  max-width: 180px; | 
				 | 
			
		||||
  text-align: center; | 
				 | 
			
		||||
  transition: all 0.3s ease; | 
				 | 
			
		||||
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.text-box:hover { | 
				 | 
			
		||||
  transform: translateY(-2px); | 
				 | 
			
		||||
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); | 
				 | 
			
		||||
  background-color: #e8e8f5; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.valve-container { | 
				 | 
			
		||||
  display: flex; | 
				 | 
			
		||||
  flex-direction: column; | 
				 | 
			
		||||
  align-items: center; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.valve-icon { | 
				 | 
			
		||||
  width: 3.5rem; | 
				 | 
			
		||||
  height: 3.5rem; | 
				 | 
			
		||||
  max-width: 60px; | 
				 | 
			
		||||
  max-height: 60px; | 
				 | 
			
		||||
  z-index: 5; | 
				 | 
			
		||||
  padding: 3px; | 
				 | 
			
		||||
  background-color: #1d2061; | 
				 | 
			
		||||
  border-radius: 50%; | 
				 | 
			
		||||
  transition: all 0.3s ease; | 
				 | 
			
		||||
  cursor: pointer; | 
				 | 
			
		||||
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); | 
				 | 
			
		||||
  position: relative; | 
				 | 
			
		||||
  overflow: hidden; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.valve-icon:hover { | 
				 | 
			
		||||
  transform: scale(1.1); | 
				 | 
			
		||||
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.valve-icon::after { | 
				 | 
			
		||||
  content: ''; | 
				 | 
			
		||||
  position: absolute; | 
				 | 
			
		||||
  top: 0; | 
				 | 
			
		||||
  left: 0; | 
				 | 
			
		||||
  right: 0; | 
				 | 
			
		||||
  bottom: 0; | 
				 | 
			
		||||
  background: radial-gradient(circle, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 70%); | 
				 | 
			
		||||
  opacity: 0; | 
				 | 
			
		||||
  transition: opacity 0.3s ease; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.valve-icon:hover::after { | 
				 | 
			
		||||
  opacity: 1; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.valve-icon img { | 
				 | 
			
		||||
  width: 100%; | 
				 | 
			
		||||
  height: 100%; | 
				 | 
			
		||||
  transition: transform 0.5s ease, filter 0.5s ease; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.green img { | 
				 | 
			
		||||
  filter: brightness(1.2) drop-shadow(0 0 3px rgba(0, 255, 0, 0.5)); | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.red img { | 
				 | 
			
		||||
  filter: hue-rotate(180deg) drop-shadow(0 0 3px rgba(255, 0, 0, 0.5)); | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.valve-label { | 
				 | 
			
		||||
  color: white; | 
				 | 
			
		||||
  font-size: 0.85rem; | 
				 | 
			
		||||
  margin-bottom: 5px; | 
				 | 
			
		||||
  text-align: center; | 
				 | 
			
		||||
  transition: all 0.3s ease; | 
				 | 
			
		||||
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5); | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.valve-icon:hover + .valve-label, | 
				 | 
			
		||||
.valve-label:hover { | 
				 | 
			
		||||
  transform: scale(1.05); | 
				 | 
			
		||||
  color: #a5c7fe; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.dashed-line { | 
				 | 
			
		||||
  position: absolute; | 
				 | 
			
		||||
  border: 2px dashed rgba(255, 255, 255, 0.7); | 
				 | 
			
		||||
  z-index: 1; | 
				 | 
			
		||||
  transition: all 0.5s ease; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.horizontal-line { | 
				 | 
			
		||||
  height: 0; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.horizontal-line.bottom-line { | 
				 | 
			
		||||
  position: absolute; | 
				 | 
			
		||||
  top: 63%; | 
				 | 
			
		||||
  left: 35%; | 
				 | 
			
		||||
  width: 30%; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.horizontal-line.top-line { | 
				 | 
			
		||||
  position: absolute; | 
				 | 
			
		||||
  top: 30%; | 
				 | 
			
		||||
  left: 65%; | 
				 | 
			
		||||
  width: 15%; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.vertical-line { | 
				 | 
			
		||||
  width: 0; | 
				 | 
			
		||||
  height: 34.3%; | 
				 | 
			
		||||
  left: 65%; | 
				 | 
			
		||||
  top: 30%; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
@keyframes flowAnimation { | 
				 | 
			
		||||
  0% { | 
				 | 
			
		||||
    background-position: 0% 50%; | 
				 | 
			
		||||
  } | 
				 | 
			
		||||
  50% { | 
				 | 
			
		||||
    background-position: 100% 50%; | 
				 | 
			
		||||
  } | 
				 | 
			
		||||
  100% { | 
				 | 
			
		||||
    background-position: 0% 50%; | 
				 | 
			
		||||
  } | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
.dashed-line { | 
				 | 
			
		||||
  background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0) 100%); | 
				 | 
			
		||||
  background-size: 200% 100%; | 
				 | 
			
		||||
  animation: flowAnimation 4s infinite; | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
/* 响应式布局 */ | 
				 | 
			
		||||
@media screen and (max-width: 768px) { | 
				 | 
			
		||||
  .monitor-chart2 { | 
				 | 
			
		||||
    padding: 10px; | 
				 | 
			
		||||
  } | 
				 | 
			
		||||
 | 
				 | 
			
		||||
  .text-box { | 
				 | 
			
		||||
    font-size: 0.8rem; | 
				 | 
			
		||||
    padding: 5px 4px; | 
				 | 
			
		||||
    min-width: 100px; | 
				 | 
			
		||||
    max-width: 150px; | 
				 | 
			
		||||
  } | 
				 | 
			
		||||
 | 
				 | 
			
		||||
  .valve-icon { | 
				 | 
			
		||||
    width: 2.5rem; | 
				 | 
			
		||||
    height: 2.5rem; | 
				 | 
			
		||||
  } | 
				 | 
			
		||||
 | 
				 | 
			
		||||
  .valve-label { | 
				 | 
			
		||||
    font-size: 0.75rem; | 
				 | 
			
		||||
  } | 
				 | 
			
		||||
} | 
				 | 
			
		||||
 | 
				 | 
			
		||||
@media screen and (max-width: 480px) { | 
				 | 
			
		||||
  .bypass-valve { | 
				 | 
			
		||||
    right: 20%; | 
				 | 
			
		||||
  } | 
				 | 
			
		||||
 | 
				 | 
			
		||||
  .entry-valve { | 
				 | 
			
		||||
    flex-direction: column; | 
				 | 
			
		||||
    align-items: flex-start; | 
				 | 
			
		||||
    left: 5%; | 
				 | 
			
		||||
  } | 
				 | 
			
		||||
 | 
				 | 
			
		||||
  .text-box { | 
				 | 
			
		||||
    margin-bottom: 15px; | 
				 | 
			
		||||
    margin-right: 0; | 
				 | 
			
		||||
  } | 
				 | 
			
		||||
 | 
				 | 
			
		||||
  .entry-valve .valve-container { | 
				 | 
			
		||||
    margin-left: 20%; | 
				 | 
			
		||||
  } | 
				 | 
			
		||||
 | 
				 | 
			
		||||
  .vertical-line { | 
				 | 
			
		||||
    left: 28%; | 
				 | 
			
		||||
  } | 
				 | 
			
		||||
} | 
				 | 
			
		||||
</style> | 
				 | 
			
		||||
@ -1,144 +0,0 @@ | 
			
		|||||
<template> | 
				 | 
			
		||||
  <el-dialog | 
				 | 
			
		||||
    v-if="dialogVisible" | 
				 | 
			
		||||
    v-el-drag-dialog | 
				 | 
			
		||||
    :title="showTitle" | 
				 | 
			
		||||
    :visible.sync="dialogVisible" | 
				 | 
			
		||||
  > | 
				 | 
			
		||||
    <el-form | 
				 | 
			
		||||
      v-if="dialogVisible" | 
				 | 
			
		||||
      ref="editForm" | 
				 | 
			
		||||
      size="mini" | 
				 | 
			
		||||
      :model="form" | 
				 | 
			
		||||
      label-position="right" | 
				 | 
			
		||||
      label-width="100px" | 
				 | 
			
		||||
    > | 
				 | 
			
		||||
      <el-form-item label="推荐方案" prop="recommendPlanId"> | 
				 | 
			
		||||
        <el-select v-model="form.recommendPlanId" placeholder="请选择推荐方案"> | 
				 | 
			
		||||
          <el-option | 
				 | 
			
		||||
            v-for="item in options.recommendPlanOtions" | 
				 | 
			
		||||
            :key="item.value" | 
				 | 
			
		||||
            :label="item.label" | 
				 | 
			
		||||
            :value="item.value" | 
				 | 
			
		||||
          ></el-option> | 
				 | 
			
		||||
        </el-select> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="管道" prop="pipeId"> | 
				 | 
			
		||||
        <el-select v-model="form.pipeId" placeholder="请选择管道"> | 
				 | 
			
		||||
          <el-option | 
				 | 
			
		||||
            v-for="item in options.rootDesignPipeOptions" | 
				 | 
			
		||||
            :key="item.value" | 
				 | 
			
		||||
            :label="item.label" | 
				 | 
			
		||||
            :value="item.value" | 
				 | 
			
		||||
          ></el-option> | 
				 | 
			
		||||
        </el-select> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="节点阀门打开度(%)" prop="valveOpening"> | 
				 | 
			
		||||
        <el-input-number | 
				 | 
			
		||||
          v-model="form.valveOpening" | 
				 | 
			
		||||
          :min="0" | 
				 | 
			
		||||
          :max="100" | 
				 | 
			
		||||
          :step="10" | 
				 | 
			
		||||
        /> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
      <el-form-item label="管道风量" prop="pipeFlow"> | 
				 | 
			
		||||
        <el-input v-model="form.pipeFlow" type="text" /> | 
				 | 
			
		||||
      </el-form-item> | 
				 | 
			
		||||
    </el-form> | 
				 | 
			
		||||
    <div slot="footer" class="dialog-footer"> | 
				 | 
			
		||||
      <el-button @click="dialogVisible = false"> 取消 </el-button> | 
				 | 
			
		||||
      <el-button type="primary" :loading="loading" @click="onSubmit"> | 
				 | 
			
		||||
        确定 | 
				 | 
			
		||||
      </el-button> | 
				 | 
			
		||||
    </div> | 
				 | 
			
		||||
  </el-dialog> | 
				 | 
			
		||||
</template> | 
				 | 
			
		||||
 | 
				 | 
			
		||||
<script> | 
				 | 
			
		||||
export default { | 
				 | 
			
		||||
  props: { | 
				 | 
			
		||||
    title: { | 
				 | 
			
		||||
      type: String, | 
				 | 
			
		||||
      default: "", | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    url: { | 
				 | 
			
		||||
      type: Object, | 
				 | 
			
		||||
      default: () => { | 
				 | 
			
		||||
        return {}; | 
				 | 
			
		||||
      }, | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    options: { | 
				 | 
			
		||||
      type: Object, | 
				 | 
			
		||||
      default: () => { | 
				 | 
			
		||||
        return {}; | 
				 | 
			
		||||
      }, | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
  data() { | 
				 | 
			
		||||
    return { | 
				 | 
			
		||||
      dialogVisible: false, | 
				 | 
			
		||||
 | 
				 | 
			
		||||
      loading: false, | 
				 | 
			
		||||
      form: { | 
				 | 
			
		||||
        id: "", | 
				 | 
			
		||||
        recommendPlanId: "", | 
				 | 
			
		||||
        pipeId: "", | 
				 | 
			
		||||
        valveOpening: "", | 
				 | 
			
		||||
        pipeFlow: "", | 
				 | 
			
		||||
        delFlag: "", | 
				 | 
			
		||||
        createBy: "", | 
				 | 
			
		||||
        createTime: "", | 
				 | 
			
		||||
        updateBy: "", | 
				 | 
			
		||||
        updateTime: "", | 
				 | 
			
		||||
      }, | 
				 | 
			
		||||
      editType: "add", //add或edit | 
				 | 
			
		||||
    }; | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
  computed: { | 
				 | 
			
		||||
    showTitle() { | 
				 | 
			
		||||
      return this.editType == "edit" | 
				 | 
			
		||||
        ? "编辑" + this.title | 
				 | 
			
		||||
        : "新增" + this.title; | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
  methods: { | 
				 | 
			
		||||
    reset() { | 
				 | 
			
		||||
      this.editType = "add"; | 
				 | 
			
		||||
      // this.$refs.elForm.resetFields(); | 
				 | 
			
		||||
      this.loading = false; | 
				 | 
			
		||||
      this.form = this.$options.data().form; | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    show(form) { | 
				 | 
			
		||||
      this.reset(); | 
				 | 
			
		||||
      if (form) { | 
				 | 
			
		||||
        this.editType = "edit"; | 
				 | 
			
		||||
        this.form = { ...this.$options.data().form, ...form }; | 
				 | 
			
		||||
      } | 
				 | 
			
		||||
      this.dialogVisible = true; | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
    onSubmit() { | 
				 | 
			
		||||
      this.$refs.editForm.validate((valid) => { | 
				 | 
			
		||||
        if (!valid) { | 
				 | 
			
		||||
          return false; | 
				 | 
			
		||||
        } | 
				 | 
			
		||||
        this.loading = true; | 
				 | 
			
		||||
        let q; | 
				 | 
			
		||||
        if (this.editType == "edit") { | 
				 | 
			
		||||
          q = this.$axios.put(this.url.edit, this.form); | 
				 | 
			
		||||
        } else { | 
				 | 
			
		||||
          q = this.$axios.post(this.url.add, this.form); | 
				 | 
			
		||||
        } | 
				 | 
			
		||||
        q.then(({ message }) => { | 
				 | 
			
		||||
          this.$message({ type: "info", message: message }); | 
				 | 
			
		||||
          this.dialogVisible = false; | 
				 | 
			
		||||
          this.$emit("refresh"); | 
				 | 
			
		||||
        }).finally(() => { | 
				 | 
			
		||||
          this.loading = false; | 
				 | 
			
		||||
        }); | 
				 | 
			
		||||
      }); | 
				 | 
			
		||||
    }, | 
				 | 
			
		||||
  }, | 
				 | 
			
		||||
}; | 
				 | 
			
		||||
</script> | 
				 | 
			
		||||
 | 
				 | 
			
		||||
<style lang="scss" scoped></style> | 
				 | 
			
		||||
@ -0,0 +1,379 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <el-dialog | 
			
		||||
 | 
				    v-if="dialogVisible" | 
			
		||||
 | 
				    v-el-drag-dialog | 
			
		||||
 | 
				    :title="showTitle" | 
			
		||||
 | 
				    :visible.sync="dialogVisible" | 
			
		||||
 | 
				    width="650px" | 
			
		||||
 | 
				    class="custom-dialog" | 
			
		||||
 | 
				  > | 
			
		||||
 | 
				    <el-form | 
			
		||||
 | 
				      v-if="dialogVisible" | 
			
		||||
 | 
				      :rules="rules" | 
			
		||||
 | 
				      ref="editForm" | 
			
		||||
 | 
				      size="mini" | 
			
		||||
 | 
				      :model="form" | 
			
		||||
 | 
				      label-position="right" | 
			
		||||
 | 
				      label-width="120px" | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="指标类别" prop="targetType"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              show-search | 
			
		||||
 | 
				              v-model="form.targetType" | 
			
		||||
 | 
				              placeholder="请选择指标类别" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option | 
			
		||||
 | 
				                v-for="item in options.targetTypes" | 
			
		||||
 | 
				                :key="item.value" | 
			
		||||
 | 
				                :label="item.label" | 
			
		||||
 | 
				                :value="item.value" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="指标名称" prop="targetName"> | 
			
		||||
 | 
				            <el-input v-model="form.targetName" placeholder="请输入指标名称" /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="指标编码" prop="targetCode"> | 
			
		||||
 | 
				            <el-input v-model="form.targetCode" placeholder="请输入指标编码" /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="报警等级" prop="rank"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.rank" | 
			
		||||
 | 
				              placeholder="请选择报警等级" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option | 
			
		||||
 | 
				                v-for="item in options.rankOptions" | 
			
		||||
 | 
				                :key="item.value" | 
			
		||||
 | 
				                :label="item.label" | 
			
		||||
 | 
				                :value="item.value" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="报警状态" prop="warnStatus"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.warnStatus" | 
			
		||||
 | 
				              placeholder="请选择报警状态" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option | 
			
		||||
 | 
				                v-for="item in options.warnStatusOptions" | 
			
		||||
 | 
				                :key="item.value" | 
			
		||||
 | 
				                :label="item.label" | 
			
		||||
 | 
				                :value="item.value" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="报警开始时间" prop="startTime"> | 
			
		||||
 | 
				            <el-date-picker | 
			
		||||
 | 
				              value-format="yyyy-MM-dd HH:mm:ss" | 
			
		||||
 | 
				              v-model="form.startTime" | 
			
		||||
 | 
				              type="datetime" | 
			
		||||
 | 
				              placeholder="选择报警开始时间" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="报警结束时间" prop="endTime"> | 
			
		||||
 | 
				            <el-date-picker | 
			
		||||
 | 
				              value-format="yyyy-MM-dd HH:mm:ss" | 
			
		||||
 | 
				              v-model="form.endTime" | 
			
		||||
 | 
				              type="datetime" | 
			
		||||
 | 
				              placeholder="选择报警结束时间" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="处置情况" prop="processStatus"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.processStatus" | 
			
		||||
 | 
				              placeholder="请选择处置情况" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option | 
			
		||||
 | 
				                v-for="item in options.processStatusOptions" | 
			
		||||
 | 
				                :key="item.value" | 
			
		||||
 | 
				                :label="item.label" | 
			
		||||
 | 
				                :value="item.value" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="有效标记" prop="actived"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.actived" | 
			
		||||
 | 
				              placeholder="请选择有效标记" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option | 
			
		||||
 | 
				                v-for="item in options.activedOptions" | 
			
		||||
 | 
				                :key="item.value" | 
			
		||||
 | 
				                :label="item.label" | 
			
		||||
 | 
				                :value="item.value" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-form-item label="报警描述" prop="message"> | 
			
		||||
 | 
				        <el-input | 
			
		||||
 | 
				          v-model="form.message" | 
			
		||||
 | 
				          type="textarea" | 
			
		||||
 | 
				          placeholder="请输入报警描述" | 
			
		||||
 | 
				          :rows="3" | 
			
		||||
 | 
				        /> | 
			
		||||
 | 
				      </el-form-item> | 
			
		||||
 | 
				    </el-form> | 
			
		||||
 | 
				    <div slot="footer" class="dialog-footer"> | 
			
		||||
 | 
				      <el-button @click="dialogVisible = false"> 取消 </el-button> | 
			
		||||
 | 
				      <el-button type="primary" :loading="loading" @click="onSubmit"> | 
			
		||||
 | 
				        确定 | 
			
		||||
 | 
				      </el-button> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				  </el-dialog> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    title: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: "", | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    url: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return {}; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    options: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return { | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        }; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      dialogVisible: false, | 
			
		||||
 | 
				      loading: false, | 
			
		||||
 | 
				      form: { | 
			
		||||
 | 
				        targetType: "", | 
			
		||||
 | 
				        targetName: "", | 
			
		||||
 | 
				        targetCode: "", | 
			
		||||
 | 
				        targetPlace: "", | 
			
		||||
 | 
				        equipinfoId: "", | 
			
		||||
 | 
				        warnUnit: "", | 
			
		||||
 | 
				        dataId: "", | 
			
		||||
 | 
				        rank: "", | 
			
		||||
 | 
				        startTime: "", | 
			
		||||
 | 
				        warnStatus: "0", // 默认未消警 | 
			
		||||
 | 
				        endTime: "", | 
			
		||||
 | 
				        message: "", | 
			
		||||
 | 
				        processStatus: "0", // 默认未处置 | 
			
		||||
 | 
				        actived: "1", // 默认为有效 | 
			
		||||
 | 
				        creatorName: "", | 
			
		||||
 | 
				        createTime: "", | 
			
		||||
 | 
				        updatorName: "", | 
			
		||||
 | 
				        updateTime: "", | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      editType: "add", //add或edit | 
			
		||||
 | 
				      rules: { | 
			
		||||
 | 
				        targetType: [ | 
			
		||||
 | 
				          { required: true, message: "请选择指标类别", trigger: "change" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        targetName: [ | 
			
		||||
 | 
				          { required: true, message: "请输入指标名称", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        targetCode: [ | 
			
		||||
 | 
				          { required: true, message: "请输入指标编码", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        rank: [ | 
			
		||||
 | 
				          { required: true, message: "请选择报警等级", trigger: "change" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        startTime: [ | 
			
		||||
 | 
				          { required: true, message: "请选择报警开始时间", trigger: "change" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        warnStatus: [ | 
			
		||||
 | 
				          { required: true, message: "请选择报警状态", trigger: "change" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        message: [ | 
			
		||||
 | 
				          { required: true, message: "请输入报警描述", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        processStatus: [ | 
			
		||||
 | 
				          { required: true, message: "请选择处置情况", trigger: "change" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  computed: { | 
			
		||||
 | 
				    showTitle() { | 
			
		||||
 | 
				      return this.editType == "edit" | 
			
		||||
 | 
				        ? "编辑" + this.title | 
			
		||||
 | 
				        : "新增" + this.title; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    reset() { | 
			
		||||
 | 
				      this.editType = "add"; | 
			
		||||
 | 
				      // this.$refs.elForm.resetFields(); | 
			
		||||
 | 
				      this.loading = false; | 
			
		||||
 | 
				      this.form = this.$options.data().form; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    show(form) { | 
			
		||||
 | 
				      this.reset(); | 
			
		||||
 | 
				      if (form) { | 
			
		||||
 | 
				        this.editType = "edit"; | 
			
		||||
 | 
				        this.form = { ...this.$options.data().form, ...form }; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      this.dialogVisible = true; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    onSubmit() { | 
			
		||||
 | 
				      this.$refs.editForm.validate((valid) => { | 
			
		||||
 | 
				        if (!valid) { | 
			
		||||
 | 
				          return false; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        this.loading = true; | 
			
		||||
 | 
				        let q; | 
			
		||||
 | 
				        if (this.editType == "edit") { | 
			
		||||
 | 
				          q = this.$axios.put(this.url.edit, this.form); | 
			
		||||
 | 
				        } else { | 
			
		||||
 | 
				          q = this.$axios.post(this.url.add, this.form); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        q.then(({ message }) => { | 
			
		||||
 | 
				          this.$message({ type: "info", message: message }); | 
			
		||||
 | 
				          this.dialogVisible = false; | 
			
		||||
 | 
				          this.$emit("refresh"); | 
			
		||||
 | 
				        }).finally(() => { | 
			
		||||
 | 
				          this.loading = false; | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style lang="scss" scoped> | 
			
		||||
 | 
				.custom-dialog { | 
			
		||||
 | 
				  ::v-deep .el-dialog { | 
			
		||||
 | 
				    background-color: rgba(4, 0, 79, 0.98); | 
			
		||||
 | 
				    border: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				    border-radius: 4px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-dialog__header { | 
			
		||||
 | 
				      background-color: rgba(0, 8, 59, 0.9); | 
			
		||||
 | 
				      padding: 15px 20px; | 
			
		||||
 | 
				      border-bottom: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      .el-dialog__title { | 
			
		||||
 | 
				        color: #e0e0ff; | 
			
		||||
 | 
				        font-weight: bold; | 
			
		||||
 | 
				        font-size: 16px; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      .el-dialog__headerbtn .el-dialog__close { | 
			
		||||
 | 
				        color: #e0e0ff; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-dialog__body { | 
			
		||||
 | 
				      padding: 20px; | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-dialog__footer { | 
			
		||||
 | 
				      padding: 10px 20px; | 
			
		||||
 | 
				      border-top: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      background-color: rgba(0, 8, 59, 0.7); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .el-form-item { | 
			
		||||
 | 
				    margin-bottom: 15px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-form-item__label { | 
			
		||||
 | 
				      color: #c0c4cc; | 
			
		||||
 | 
				      font-size: 13px; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-input__inner { | 
			
		||||
 | 
				      background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				      border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &::placeholder { | 
			
		||||
 | 
				        color: rgba(195, 195, 219, 0.5); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-textarea__inner { | 
			
		||||
 | 
				      background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				      border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &::placeholder { | 
			
		||||
 | 
				        color: rgba(195, 195, 219, 0.5); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-select .el-input .el-select__caret { | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .dialog-footer { | 
			
		||||
 | 
				    text-align: right; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-button { | 
			
		||||
 | 
				      background-color: rgba(30, 27, 110, 0.7); | 
			
		||||
 | 
				      border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &:hover { | 
			
		||||
 | 
				        background-color: rgba(40, 36, 124, 0.8); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &[type="primary"] { | 
			
		||||
 | 
				        background-color: #1976d2; | 
			
		||||
 | 
				        border-color: #1565c0; | 
			
		||||
 | 
				        color: #ffffff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        &:hover { | 
			
		||||
 | 
				          background-color: #1e88e5; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,289 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <el-dialog | 
			
		||||
 | 
				      v-if="dialogVisible" | 
			
		||||
 | 
				      v-el-drag-dialog | 
			
		||||
 | 
				      :title="showTitle" | 
			
		||||
 | 
				      :visible.sync="dialogVisible" | 
			
		||||
 | 
				      width="650px" | 
			
		||||
 | 
				      class="custom-dialog" | 
			
		||||
 | 
				  > | 
			
		||||
 | 
				      <el-form | 
			
		||||
 | 
				          v-if="dialogVisible" | 
			
		||||
 | 
				          ref="editForm" | 
			
		||||
 | 
				          size="mini" | 
			
		||||
 | 
				          :model="form" | 
			
		||||
 | 
				          label-position="right" | 
			
		||||
 | 
				          label-width="100px" | 
			
		||||
 | 
				      > | 
			
		||||
 | 
				          <el-row :gutter="20"> | 
			
		||||
 | 
				              <el-col :span="24"> | 
			
		||||
 | 
				                  <el-form-item label="清理项目" prop="clearItemName"> | 
			
		||||
 | 
				                      <el-select v-model="form.clearItemName" placeholder="请选择清理项目" style="width: 100%;"> | 
			
		||||
 | 
				                          <el-option | 
			
		||||
 | 
				                              v-for="item in options.clearItems" | 
			
		||||
 | 
				                              :key="item.value" | 
			
		||||
 | 
				                              :label="item.label" | 
			
		||||
 | 
				                              :value="item.value" | 
			
		||||
 | 
				                          /> | 
			
		||||
 | 
				                      </el-select> | 
			
		||||
 | 
				                  </el-form-item> | 
			
		||||
 | 
				              </el-col> | 
			
		||||
 | 
				          </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				          <el-row :gutter="20"> | 
			
		||||
 | 
				              <el-col :span="24"> | 
			
		||||
 | 
				                  <el-form-item label="完成情况" prop="taskProcess"> | 
			
		||||
 | 
				                      <el-select v-model="form.taskProcess" placeholder="请选择完成情况" style="width: 100%;"> | 
			
		||||
 | 
				                          <el-option | 
			
		||||
 | 
				                              v-for="item in options.taskProcesses" | 
			
		||||
 | 
				                              :key="item.value" | 
			
		||||
 | 
				                              :label="item.label" | 
			
		||||
 | 
				                              :value="item.value" | 
			
		||||
 | 
				                          /> | 
			
		||||
 | 
				                      </el-select> | 
			
		||||
 | 
				                  </el-form-item> | 
			
		||||
 | 
				              </el-col> | 
			
		||||
 | 
				          </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				          <el-row :gutter="20"> | 
			
		||||
 | 
				              <el-col :span="24"> | 
			
		||||
 | 
				                  <el-form-item label="执行人" prop="taskPerson"> | 
			
		||||
 | 
				                      <el-input v-model="form.taskPerson" type="text"/> | 
			
		||||
 | 
				                  </el-form-item> | 
			
		||||
 | 
				              </el-col> | 
			
		||||
 | 
				          </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				          <el-row :gutter="20"> | 
			
		||||
 | 
				              <el-col :span="24"> | 
			
		||||
 | 
				                  <el-form-item label="执行日期" prop="taskTime"> | 
			
		||||
 | 
				                      <el-date-picker | 
			
		||||
 | 
				                          value-format="yyyy-MM-dd HH:mm:ss" | 
			
		||||
 | 
				                          v-model="form.taskTime" | 
			
		||||
 | 
				                          type="datetime" | 
			
		||||
 | 
				                          placeholder="请选择执行日期" | 
			
		||||
 | 
				                          style="width: 100%;" | 
			
		||||
 | 
				                      /> | 
			
		||||
 | 
				                  </el-form-item> | 
			
		||||
 | 
				              </el-col> | 
			
		||||
 | 
				          </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				          <el-row :gutter="20"> | 
			
		||||
 | 
				              <el-col :span="24"> | 
			
		||||
 | 
				                  <el-form-item label="有效标志" prop="actived"> | 
			
		||||
 | 
				                      <el-select v-model="form.actived" placeholder="请选择有效标志" style="width: 100%;"> | 
			
		||||
 | 
				                          <el-option | 
			
		||||
 | 
				                              v-for="item in options.activedOptions" | 
			
		||||
 | 
				                              :key="item.value" | 
			
		||||
 | 
				                              :label="item.label" | 
			
		||||
 | 
				                              :value="item.value" | 
			
		||||
 | 
				                          /> | 
			
		||||
 | 
				                      </el-select> | 
			
		||||
 | 
				                  </el-form-item> | 
			
		||||
 | 
				              </el-col> | 
			
		||||
 | 
				          </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				          <el-row :gutter="20" v-if="editType != 'edit'"> | 
			
		||||
 | 
				              <el-col :span="24"> | 
			
		||||
 | 
				                  <el-form-item label="创建人" prop="creatorName"> | 
			
		||||
 | 
				                      <el-input v-model="form.creatorName" type="text"/> | 
			
		||||
 | 
				                  </el-form-item> | 
			
		||||
 | 
				              </el-col> | 
			
		||||
 | 
				          </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				          <el-row :gutter="20" v-if="editType == 'edit'"> | 
			
		||||
 | 
				              <el-col :span="24"> | 
			
		||||
 | 
				                  <el-form-item label="修改人" prop="updatorName"> | 
			
		||||
 | 
				                      <el-input v-model="form.updatorName" type="text"/> | 
			
		||||
 | 
				                  </el-form-item> | 
			
		||||
 | 
				              </el-col> | 
			
		||||
 | 
				          </el-row> | 
			
		||||
 | 
				      </el-form> | 
			
		||||
 | 
				      <div slot="footer" class="dialog-footer"> | 
			
		||||
 | 
				          <el-button @click="dialogVisible = false"> 取消 </el-button> | 
			
		||||
 | 
				          <el-button type="primary" :loading="loading" @click="onSubmit"> | 
			
		||||
 | 
				              确定 | 
			
		||||
 | 
				          </el-button> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				  </el-dialog> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				  export default { | 
			
		||||
 | 
				      props: { | 
			
		||||
 | 
				          title: { | 
			
		||||
 | 
				              type: String, | 
			
		||||
 | 
				              default: "", | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				          url: { | 
			
		||||
 | 
				              type: Object, | 
			
		||||
 | 
				              default: () => { | 
			
		||||
 | 
				                  return {}; | 
			
		||||
 | 
				              }, | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				          options: { | 
			
		||||
 | 
				              type: Object, | 
			
		||||
 | 
				              default: () => { | 
			
		||||
 | 
				                  return {}; | 
			
		||||
 | 
				              }, | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      data() { | 
			
		||||
 | 
				          return { | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				              dialogVisible: false, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				              loading: false, | 
			
		||||
 | 
				              form: { | 
			
		||||
 | 
				                  id:"", | 
			
		||||
 | 
				                  dataId:"", | 
			
		||||
 | 
				                  clearItemName:"", | 
			
		||||
 | 
				                  taskProcess:"", | 
			
		||||
 | 
				                  taskPerson:"", | 
			
		||||
 | 
				                  taskTime:"", | 
			
		||||
 | 
				                  actived:"", | 
			
		||||
 | 
				                  creatorName:"", | 
			
		||||
 | 
				                  createTime:"", | 
			
		||||
 | 
				                  updatorName:"", | 
			
		||||
 | 
				                  updateTime:"", | 
			
		||||
 | 
				              }, | 
			
		||||
 | 
				              editType:"add", //add或edit | 
			
		||||
 | 
				          }; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      computed: { | 
			
		||||
 | 
				          showTitle() { | 
			
		||||
 | 
				              return this.editType=='edit' ? "编辑" + this.title : "新增" + this.title; | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      methods: { | 
			
		||||
 | 
				          reset() { | 
			
		||||
 | 
				              this.editType='add' | 
			
		||||
 | 
				              // this.$refs.elForm.resetFields(); | 
			
		||||
 | 
				              this.loading=false; | 
			
		||||
 | 
				              this.form = this.$options.data().form; | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				          show(form) { | 
			
		||||
 | 
				              this.reset(); | 
			
		||||
 | 
				              if (form) { | 
			
		||||
 | 
				                  this.editType='edit' | 
			
		||||
 | 
				                  this.form = { ...this.$options.data().form, ...form }; | 
			
		||||
 | 
				              } | 
			
		||||
 | 
				              this.dialogVisible = true; | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				          onSubmit() { | 
			
		||||
 | 
				              this.$refs.editForm.validate((valid) => { | 
			
		||||
 | 
				                  if (!valid) { | 
			
		||||
 | 
				                      return false; | 
			
		||||
 | 
				                  } | 
			
		||||
 | 
				                  this.loading = true; | 
			
		||||
 | 
				                  let q; | 
			
		||||
 | 
				                  if (this.editType=='edit') { | 
			
		||||
 | 
				                      q = this.$axios.put( this.url.edit, this.form); | 
			
		||||
 | 
				                  } else { | 
			
		||||
 | 
				                      q = this.$axios.post(this.url.add, this.form); | 
			
		||||
 | 
				                  } | 
			
		||||
 | 
				                  q.then(({ message }) => { | 
			
		||||
 | 
				                      this.$message({ type: "info", message: message }); | 
			
		||||
 | 
				                      this.dialogVisible = false; | 
			
		||||
 | 
				                      this.$emit("refresh"); | 
			
		||||
 | 
				                  }).finally(() => { | 
			
		||||
 | 
				                      this.loading = false; | 
			
		||||
 | 
				                  }); | 
			
		||||
 | 
				              }); | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				  }; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style lang="scss" scoped> | 
			
		||||
 | 
				.custom-dialog { | 
			
		||||
 | 
				    ::v-deep .el-dialog { | 
			
		||||
 | 
				        background-color: rgba(4, 0, 79, 0.98); | 
			
		||||
 | 
				        border: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				        border-radius: 4px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .el-dialog__header { | 
			
		||||
 | 
				            background-color: rgba(0, 8, 59, 0.9); | 
			
		||||
 | 
				            padding: 15px 20px; | 
			
		||||
 | 
				            border-bottom: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            .el-dialog__title { | 
			
		||||
 | 
				                color: #e0e0ff; | 
			
		||||
 | 
				                font-weight: bold; | 
			
		||||
 | 
				                font-size: 16px; | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            .el-dialog__headerbtn .el-dialog__close { | 
			
		||||
 | 
				                color: #e0e0ff; | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .el-dialog__body { | 
			
		||||
 | 
				            padding: 20px; | 
			
		||||
 | 
				            color: #e0e0ff; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .el-dialog__footer { | 
			
		||||
 | 
				            padding: 10px 20px; | 
			
		||||
 | 
				            border-top: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				            background-color: rgba(0, 8, 59, 0.7); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-form-item { | 
			
		||||
 | 
				        margin-bottom: 15px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        ::v-deep .el-form-item__label { | 
			
		||||
 | 
				            color: #c0c4cc; | 
			
		||||
 | 
				            font-size: 13px; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        ::v-deep .el-input__inner { | 
			
		||||
 | 
				            background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				            border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				            color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            &::placeholder { | 
			
		||||
 | 
				                color: rgba(195, 195, 219, 0.5); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        ::v-deep .el-textarea__inner { | 
			
		||||
 | 
				            background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				            border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				            color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            &::placeholder { | 
			
		||||
 | 
				                color: rgba(195, 195, 219, 0.5); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        ::v-deep .el-select .el-input .el-select__caret { | 
			
		||||
 | 
				            color: #e0e0ff; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .dialog-footer { | 
			
		||||
 | 
				        text-align: right; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .el-button { | 
			
		||||
 | 
				            background-color: rgba(30, 27, 110, 0.7); | 
			
		||||
 | 
				            border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				            color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            &:hover { | 
			
		||||
 | 
				                background-color: rgba(40, 36, 124, 0.8); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            &[type="primary"] { | 
			
		||||
 | 
				                background-color: #1976d2; | 
			
		||||
 | 
				                border-color: #1565c0; | 
			
		||||
 | 
				                color: #ffffff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				                &:hover { | 
			
		||||
 | 
				                    background-color: #1e88e5; | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,487 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <el-dialog | 
			
		||||
 | 
				    v-if="dialogVisible" | 
			
		||||
 | 
				    v-el-drag-dialog | 
			
		||||
 | 
				    :title="showTitle" | 
			
		||||
 | 
				    :visible.sync="dialogVisible" | 
			
		||||
 | 
				    width="650px" | 
			
		||||
 | 
				    class="custom-dialog" | 
			
		||||
 | 
				  > | 
			
		||||
 | 
				    <el-form | 
			
		||||
 | 
				      v-if="dialogVisible" | 
			
		||||
 | 
				      ref="editForm" | 
			
		||||
 | 
				      :rules="rules" | 
			
		||||
 | 
				      size="mini" | 
			
		||||
 | 
				      :model="form" | 
			
		||||
 | 
				      label-position="right" | 
			
		||||
 | 
				      label-width="130px" | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="指标编码" prop="targetCode"> | 
			
		||||
 | 
				            <el-input | 
			
		||||
 | 
				              v-model="form.targetCode" | 
			
		||||
 | 
				              placeholder="设备编码+3位流水编码" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="指标名称" prop="targetName"> | 
			
		||||
 | 
				            <el-input v-model="form.targetName" placeholder="请输入指标名称" /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="24"> | 
			
		||||
 | 
				          <el-form-item label="除尘系统" prop="equipId"> | 
			
		||||
 | 
				            <el-select @change="handleEquipChange" v-model="form.equipId" placeholder="请选择除尘系统" style="width: 100%"> | 
			
		||||
 | 
				              <el-option v-for="item in options.equipList" :key="item.id" :label="item.equipName" :value="item.id" /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="指标类别" prop="targetType"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.targetType" | 
			
		||||
 | 
				              placeholder="请选择指标类别" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option | 
			
		||||
 | 
				                v-for="item in options.targetTypes" | 
			
		||||
 | 
				                :key="item.value" | 
			
		||||
 | 
				                :label="item.label" | 
			
		||||
 | 
				                :value="item.value" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="信号类型" prop="signalType"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.signalType" | 
			
		||||
 | 
				              placeholder="请选择信号类型" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				              @change="handleSignalTypeChange" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option | 
			
		||||
 | 
				                v-for="item in options.signalTypes" | 
			
		||||
 | 
				                :key="item.value" | 
			
		||||
 | 
				                :label="item.label" | 
			
		||||
 | 
				                :value="item.value" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="采集点位置" prop="targetPlace"> | 
			
		||||
 | 
				            <el-input | 
			
		||||
 | 
				              v-model="form.targetPlace" | 
			
		||||
 | 
				              placeholder="请输入指标采集点位置" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="位号" prop="bitNo"> | 
			
		||||
 | 
				            <el-input v-model="form.bitNo" placeholder="请输入位号" /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row v-if="form.signalType === '02'" :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="开关量报警值" prop="alarmValue"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.alarmValue" | 
			
		||||
 | 
				              placeholder="请选择报警值" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option label="0" value="0" /> | 
			
		||||
 | 
				              <el-option label="1" value="1" /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <template v-if="form.signalType === '01'"> | 
			
		||||
 | 
				        <el-row :gutter="20"> | 
			
		||||
 | 
				          <el-col :span="12"> | 
			
		||||
 | 
				            <el-form-item label="计量单位" prop="targetUnit"> | 
			
		||||
 | 
				              <el-input v-model="form.targetUnit" placeholder="模拟量必填" /> | 
			
		||||
 | 
				            </el-form-item> | 
			
		||||
 | 
				          </el-col> | 
			
		||||
 | 
				        </el-row> | 
			
		||||
 | 
				        <el-row :gutter="20"> | 
			
		||||
 | 
				          <el-col :span="12"> | 
			
		||||
 | 
				            <el-form-item label="阈值上限" prop="thresholdUpLimit"> | 
			
		||||
 | 
				              <el-input-number | 
			
		||||
 | 
				v-model="form.thresholdUpLimit" | 
			
		||||
 | 
				                :controls="false" | 
			
		||||
 | 
				                placeholder="高报阈值" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-form-item> | 
			
		||||
 | 
				          </el-col> | 
			
		||||
 | 
				          <el-col :span="12"> | 
			
		||||
 | 
				            <el-form-item label="阈值上上限" prop="thresholdUpUpLimit"> | 
			
		||||
 | 
				              <el-input-number | 
			
		||||
 | 
				v-model="form.thresholdUpUpLimit" | 
			
		||||
 | 
				                :controls="false" | 
			
		||||
 | 
				                placeholder="高高报阈值" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-form-item> | 
			
		||||
 | 
				          </el-col> | 
			
		||||
 | 
				        </el-row> | 
			
		||||
 | 
				        <el-row :gutter="20"> | 
			
		||||
 | 
				          <el-col :span="12"> | 
			
		||||
 | 
				            <el-form-item label="阈值下限" prop="thresholdDownLimit"> | 
			
		||||
 | 
				              <el-input-number | 
			
		||||
 | 
				v-model="form.thresholdDownLimit" | 
			
		||||
 | 
				                :controls="false" | 
			
		||||
 | 
				                placeholder="低报阈值" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-form-item> | 
			
		||||
 | 
				          </el-col> | 
			
		||||
 | 
				          <el-col :span="12"> | 
			
		||||
 | 
				            <el-form-item label="阈值下下限" prop="thresholdDownDownLimit"> | 
			
		||||
 | 
				              <el-input-number | 
			
		||||
 | 
				v-model="form.thresholdDownDownLimit" | 
			
		||||
 | 
				                :controls="false" | 
			
		||||
 | 
				                placeholder="低低报阈值" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-form-item> | 
			
		||||
 | 
				          </el-col> | 
			
		||||
 | 
				        </el-row> | 
			
		||||
 | 
				        <el-row :gutter="20"> | 
			
		||||
 | 
				          <el-col :span="12"> | 
			
		||||
 | 
				            <el-form-item label="量程上限" prop="rangeUp" > | 
			
		||||
 | 
				              <el-input-number v-model="form.rangeUp" :controls="false" placeholder="模拟量指标需填写" /> | 
			
		||||
 | 
				            </el-form-item> | 
			
		||||
 | 
				          </el-col> | 
			
		||||
 | 
				          <el-col :span="12"> | 
			
		||||
 | 
				            <el-form-item label="量程下限" prop="rangeDown"> | 
			
		||||
 | 
				              <el-input-number | 
			
		||||
 | 
				v-model="form.rangeDown" | 
			
		||||
 | 
				                :controls="false" | 
			
		||||
 | 
				                placeholder="模拟量指标需填写" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-form-item> | 
			
		||||
 | 
				          </el-col> | 
			
		||||
 | 
				        </el-row> | 
			
		||||
 | 
				      </template> | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="报警保持时间(秒)" prop="alarmTime"> | 
			
		||||
 | 
				            <el-input | 
			
		||||
 | 
				              v-model="form.alarmTime" | 
			
		||||
 | 
				              placeholder="请输入报警保持时间" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="报警保持次数" prop="alarmDataRepeatedly"> | 
			
		||||
 | 
				            <el-input | 
			
		||||
 | 
				              v-model="form.alarmDataRepeatedly" | 
			
		||||
 | 
				              placeholder="请输入报警保持次数" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="指标状态" prop="targetStatus"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.targetStatus" | 
			
		||||
 | 
				              placeholder="请选择指标状态" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option | 
			
		||||
 | 
				                v-for="item in options.targetStatuses" | 
			
		||||
 | 
				                :key="item.value" | 
			
		||||
 | 
				                :label="item.label" | 
			
		||||
 | 
				                :value="item.value" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="有效标记" prop="actived"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.actived" | 
			
		||||
 | 
				              placeholder="请选择有效标记" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option | 
			
		||||
 | 
				                v-for="item in options.activedOptions" | 
			
		||||
 | 
				                :key="item.value" | 
			
		||||
 | 
				                :label="item.label" | 
			
		||||
 | 
				                :value="item.value" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-form-item label="描述" prop="targetDescription"> | 
			
		||||
 | 
				        <el-input | 
			
		||||
 | 
				          v-model="form.targetDescription" | 
			
		||||
 | 
				          type="textarea" | 
			
		||||
 | 
				          placeholder="请输入描述内容" | 
			
		||||
 | 
				          :rows="3" | 
			
		||||
 | 
				        /> | 
			
		||||
 | 
				      </el-form-item> | 
			
		||||
 | 
				    </el-form> | 
			
		||||
 | 
				    <div slot="footer" class="dialog-footer"> | 
			
		||||
 | 
				      <el-button @click="dialogVisible = false"> 取消 </el-button> | 
			
		||||
 | 
				      <el-button type="primary" :loading="loading" @click="onSubmit"> | 
			
		||||
 | 
				        确定 | 
			
		||||
 | 
				      </el-button> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				  </el-dialog> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    title: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: "", | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    url: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return {}; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    options: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return { | 
			
		||||
 | 
				          signalTypes: [], | 
			
		||||
 | 
				          targetStatuses: [], | 
			
		||||
 | 
				          activedOptions: [], | 
			
		||||
 | 
				          targetTypes: [], | 
			
		||||
 | 
				          equipList: [], | 
			
		||||
 | 
				        }; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      dialogVisible: false, | 
			
		||||
 | 
				      loading: false, | 
			
		||||
 | 
				      form: { | 
			
		||||
 | 
				        targetCode: "", | 
			
		||||
 | 
				        equipCode: "", | 
			
		||||
 | 
				        equipId: "", | 
			
		||||
 | 
				        targetName: "", | 
			
		||||
 | 
				        targetType: "", | 
			
		||||
 | 
				        targetPlace: "", | 
			
		||||
 | 
				        targetUnit: "", | 
			
		||||
 | 
				        thresholdUpLimit: "", | 
			
		||||
 | 
				        thresholdUpUpLimit: "", | 
			
		||||
 | 
				        thresholdDownLimit: "", | 
			
		||||
 | 
				        thresholdDownDownLimit: "", | 
			
		||||
 | 
				        rangeUp: "", | 
			
		||||
 | 
				        rangeDown: "", | 
			
		||||
 | 
				        targetDescription: "", | 
			
		||||
 | 
				        bitNo: "", | 
			
		||||
 | 
				        signalType: "", | 
			
		||||
 | 
				        alarmValue: "", | 
			
		||||
 | 
				        targetStatus: "1", // 默认为有效 | 
			
		||||
 | 
				        actived: "1", // 默认为有效 | 
			
		||||
 | 
				        creatorName: "", | 
			
		||||
 | 
				        createTime: "", | 
			
		||||
 | 
				        updatorName: "", | 
			
		||||
 | 
				        updateTime: "", | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      editType: "add", //add或edit | 
			
		||||
 | 
				      rules: { | 
			
		||||
 | 
				        targetCode: [ | 
			
		||||
 | 
				          { required: true, message: "请输入指标编码", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        targetName: [ | 
			
		||||
 | 
				          { required: true, message: "请输入指标名称", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        equipCode: [ | 
			
		||||
 | 
				          { required: true, message: "请输入除尘系统编码", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        equipId: [ | 
			
		||||
 | 
				          { required: true, message: "请输入除尘系统ID", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        targetType: [ | 
			
		||||
 | 
				          { required: true, message: "请选择指标类别", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        signalType: [ | 
			
		||||
 | 
				          { required: true, message: "请选择信号类型", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        targetPlace: [ | 
			
		||||
 | 
				          { required: true, message: "请输入指标采集点位置", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        bitNo: [{ required: true, message: "请输入位号", trigger: "blur" }], | 
			
		||||
 | 
				        targetUnit: [ | 
			
		||||
 | 
				          { required: true, message: "请输入计量单位", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  computed: { | 
			
		||||
 | 
				    showTitle() { | 
			
		||||
 | 
				      return this.editType == "edit" | 
			
		||||
 | 
				        ? "编辑" + this.title | 
			
		||||
 | 
				        : "新增" + this.title; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    reset() { | 
			
		||||
 | 
				      this.editType = "add"; | 
			
		||||
 | 
				      this.loading = false; | 
			
		||||
 | 
				      this.form = this.$options.data().form; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    show(form) { | 
			
		||||
 | 
				      this.reset(); | 
			
		||||
 | 
				      if (form) { | 
			
		||||
 | 
				        this.editType = "edit"; | 
			
		||||
 | 
				        this.form = { ...this.$options.data().form, ...form }; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      this.dialogVisible = true; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    onSubmit() { | 
			
		||||
 | 
				      this.$refs.editForm.validate((valid) => { | 
			
		||||
 | 
				        if (!valid) { | 
			
		||||
 | 
				          return false; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        this.loading = true; | 
			
		||||
 | 
				        let q; | 
			
		||||
 | 
				        if (this.editType == "edit") { | 
			
		||||
 | 
				          q = this.$axios.put(this.url.edit, this.form); | 
			
		||||
 | 
				        } else { | 
			
		||||
 | 
				          q = this.$axios.post(this.url.add, this.form); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        q.then(({ message }) => { | 
			
		||||
 | 
				          this.$message({ type: "info", message: message }); | 
			
		||||
 | 
				          this.dialogVisible = false; | 
			
		||||
 | 
				          this.$emit("refresh"); | 
			
		||||
 | 
				        }).finally(() => { | 
			
		||||
 | 
				          this.loading = false; | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    handleSignalTypeChange(value) { | 
			
		||||
 | 
				      this.form.alarmValue = ""; | 
			
		||||
 | 
				      this.form.alarmTime = ""; | 
			
		||||
 | 
				      this.form.alarmDataRepeatedly = ""; | 
			
		||||
 | 
				      this.form.thresholdUpLimit = ""; | 
			
		||||
 | 
				      this.form.thresholdUpUpLimit = ""; | 
			
		||||
 | 
				      this.form.thresholdDownLimit = ""; | 
			
		||||
 | 
				      this.form.thresholdDownDownLimit = ""; | 
			
		||||
 | 
				      this.form.rangeUp = ""; | 
			
		||||
 | 
				      this.form.rangeDown = ""; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    handleEquipChange(value) { | 
			
		||||
 | 
				      this.form.equipId = value; | 
			
		||||
 | 
				      this.form.equipCode = this.options.equipList.find(item => item.id === value).equipCode; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style lang="scss" scoped> | 
			
		||||
 | 
				.custom-dialog { | 
			
		||||
 | 
				  ::v-deep .el-dialog { | 
			
		||||
 | 
				    background-color: rgba(4, 0, 79, 0.98); | 
			
		||||
 | 
				    border: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				    border-radius: 4px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-dialog__header { | 
			
		||||
 | 
				      background-color: rgba(0, 8, 59, 0.9); | 
			
		||||
 | 
				      padding: 15px 20px; | 
			
		||||
 | 
				      border-bottom: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      .el-dialog__title { | 
			
		||||
 | 
				        color: #e0e0ff; | 
			
		||||
 | 
				        font-weight: bold; | 
			
		||||
 | 
				        font-size: 16px; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      .el-dialog__headerbtn .el-dialog__close { | 
			
		||||
 | 
				        color: #e0e0ff; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-dialog__body { | 
			
		||||
 | 
				      padding: 20px; | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-dialog__footer { | 
			
		||||
 | 
				      padding: 10px 20px; | 
			
		||||
 | 
				      border-top: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      background-color: rgba(0, 8, 59, 0.7); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .el-form-item { | 
			
		||||
 | 
				    margin-bottom: 15px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-form-item__label { | 
			
		||||
 | 
				      color: #c0c4cc; | 
			
		||||
 | 
				      font-size: 13px; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-input__inner { | 
			
		||||
 | 
				      background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				      border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &::placeholder { | 
			
		||||
 | 
				        color: rgba(195, 195, 219, 0.5); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-textarea__inner { | 
			
		||||
 | 
				      background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				      border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &::placeholder { | 
			
		||||
 | 
				        color: rgba(195, 195, 219, 0.5); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-select .el-input .el-select__caret { | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .dialog-footer { | 
			
		||||
 | 
				    text-align: right; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-button { | 
			
		||||
 | 
				      background-color: rgba(30, 27, 110, 0.7); | 
			
		||||
 | 
				      border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &:hover { | 
			
		||||
 | 
				        background-color: rgba(40, 36, 124, 0.8); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &[type="primary"] { | 
			
		||||
 | 
				        background-color: #1976d2; | 
			
		||||
 | 
				        border-color: #1565c0; | 
			
		||||
 | 
				        color: #ffffff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        &:hover { | 
			
		||||
 | 
				          background-color: #1e88e5; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,289 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <div id="DeviceTree" class="device-tree-container"> | 
			
		||||
 | 
				    <el-container> | 
			
		||||
 | 
				      <el-header class="device-tree-header">设备列表</el-header> | 
			
		||||
 | 
				      <el-main class="device-tree-main"> | 
			
		||||
 | 
				        <div class="device-tree-main-box"> | 
			
		||||
 | 
				          <el-tree | 
			
		||||
 | 
				            ref="gdTree" | 
			
		||||
 | 
				            :props="defaultProps" | 
			
		||||
 | 
				            :load="loadNode" | 
			
		||||
 | 
				            lazy | 
			
		||||
 | 
				            node-key="id" | 
			
		||||
 | 
				            class="custom-tree" | 
			
		||||
 | 
				            @node-click="handleNodeClick" | 
			
		||||
 | 
				            @node-contextmenu="handleContextMenu" | 
			
		||||
 | 
				          > | 
			
		||||
 | 
				            <span slot-scope="{ node }" class="custom-tree-node"> | 
			
		||||
 | 
				              <span v-if="node.data.type === 0 && node.data.online" title="在线设备" class="device-online iconfont icon-jiedianleizhukongzhongxin2"></span> | 
			
		||||
 | 
				              <span v-if="node.data.type === 0 && !node.data.online " title="离线设备" class="device-offline iconfont icon-jiedianleizhukongzhongxin2"></span> | 
			
		||||
 | 
				              <span v-if="node.data.type === 2 && node.data.online" title="目录"  class="device-online iconfont icon-jiedianleilianjipingtai"></span> | 
			
		||||
 | 
				              <span v-if="node.data.type === 2 && !node.data.online" title="目录"  class="device-offline iconfont icon-jiedianleilianjipingtai"></span> | 
			
		||||
 | 
				              <span v-if="node.data.type === 3 && node.data.online " title="在线通道" class="device-online iconfont icon-shebeileijiankongdian"></span> | 
			
		||||
 | 
				              <span v-if="node.data.type === 3 && !node.data.online" title="在线通道" class="device-offline iconfont icon-shebeileijiankongdian"></span> | 
			
		||||
 | 
				              <span v-if="node.data.type === 4 && node.data.online " title="在线通道-球机" class="device-online iconfont icon-shebeileiqiuji"></span> | 
			
		||||
 | 
				              <span v-if="node.data.type === 4 && !node.data.online" title="在线通道-球机" class="device-offline iconfont icon-shebeileiqiuji"></span> | 
			
		||||
 | 
				              <span v-if="node.data.type === 5 && node.data.online " title="在线通道-半球" class="device-online iconfont icon-shebeileibanqiu"></span> | 
			
		||||
 | 
				              <span v-if="node.data.type === 5 && !node.data.online" title="在线通道-半球" class="device-offline iconfont icon-shebeileibanqiu"></span> | 
			
		||||
 | 
				              <span v-if="node.data.type === 6 && node.data.online " title="在线通道-枪机" class="device-online iconfont icon-shebeileiqiangjitongdao"></span> | 
			
		||||
 | 
				              <span v-if="node.data.type === 6 && !node.data.online" title="在线通道-枪机" class="device-offline iconfont icon-shebeileiqiangjitongdao"></span> | 
			
		||||
 | 
				              <span v-if="node.data.online" class="device-online device-label">{{ node.label }}</span> | 
			
		||||
 | 
				              <span v-if="!node.data.online" class="device-offline device-label">{{ node.label }}</span> | 
			
		||||
 | 
				              <span> | 
			
		||||
 | 
				                <i v-if="node.data.hasGPS && node.data.online" class="device-online iconfont icon-dizhi gps-icon"></i> | 
			
		||||
 | 
				                <i v-if="node.data.hasGPS && !node.data.online" class="device-offline iconfont icon-dizhi gps-icon"></i> | 
			
		||||
 | 
				              </span> | 
			
		||||
 | 
				            </span> | 
			
		||||
 | 
				          </el-tree> | 
			
		||||
 | 
				        </div> | 
			
		||||
 | 
				      </el-main> | 
			
		||||
 | 
				    </el-container> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				import WvpService from "@/api/wvp.js"; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				    name: 'DeviceTree', | 
			
		||||
 | 
				    props: ['device', 'onlyCatalog', 'clickEvent', 'contextMenuEvent'], | 
			
		||||
 | 
				    data() { | 
			
		||||
 | 
				        return { | 
			
		||||
 | 
				          wvpService: WvpService, | 
			
		||||
 | 
				          defaultProps: { | 
			
		||||
 | 
				            children: 'children', | 
			
		||||
 | 
				            label: 'name', | 
			
		||||
 | 
				            isLeaf: 'isLeaf' | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				        }; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    destroyed() { | 
			
		||||
 | 
				      // if (this.jessibuca) { | 
			
		||||
 | 
				      //   this.jessibuca.destroy(); | 
			
		||||
 | 
				      // } | 
			
		||||
 | 
				      // this.playing = false; | 
			
		||||
 | 
				      // this.loaded = false; | 
			
		||||
 | 
				      // this.performance = ""; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    methods: { | 
			
		||||
 | 
				      handleNodeClick(data) { | 
			
		||||
 | 
				        let deviceNode = this.$refs.gdTree.getNode(data.userData.deviceId) | 
			
		||||
 | 
				        if(typeof (this.clickEvent) == "function") { | 
			
		||||
 | 
				          this.clickEvent(deviceNode.data.userData, data.userData, data.type === 2) | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      handleContextMenu(event, data) { | 
			
		||||
 | 
				        console.log("右键点击事件") | 
			
		||||
 | 
				        let deviceNode = this.$refs.gdTree.getNode(data.userData.deviceId) | 
			
		||||
 | 
				        if(typeof (this.contextMenuEvent) == "function") { | 
			
		||||
 | 
				          this.contextMenuEvent(deviceNode.data.userData, event, data.userData, data.type === 2) | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      loadNode: function(node, resolve){ | 
			
		||||
 | 
				        if (node.level === 0) { | 
			
		||||
 | 
				          if (this.device) { | 
			
		||||
 | 
				            let node = { | 
			
		||||
 | 
				              name: this.device.name || this.device.deviceId, | 
			
		||||
 | 
				              isLeaf: false, | 
			
		||||
 | 
				              id: this.device.deviceId, | 
			
		||||
 | 
				              type: this.device.online, | 
			
		||||
 | 
				              online: this.device.online === 1, | 
			
		||||
 | 
				              userData: this.device | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            resolve([node]) | 
			
		||||
 | 
				          }else { | 
			
		||||
 | 
				            this.wvpService.deviceList().then((data)=>{ | 
			
		||||
 | 
				              if (data.length > 0) { | 
			
		||||
 | 
				                let nodeList = [] | 
			
		||||
 | 
				                for (let i = 0; i < data.length; i++) { | 
			
		||||
 | 
				                  let node = { | 
			
		||||
 | 
				                    name: data[i].name || data[i].deviceId, | 
			
		||||
 | 
				                    isLeaf: false, | 
			
		||||
 | 
				                    id: data[i].deviceId, | 
			
		||||
 | 
				                    type: data[i].online, | 
			
		||||
 | 
				                    online: data[i].online === 1, | 
			
		||||
 | 
				                    userData: data[i] | 
			
		||||
 | 
				                  } | 
			
		||||
 | 
				                  nodeList.push(node); | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				                resolve(nodeList) | 
			
		||||
 | 
				              }else { | 
			
		||||
 | 
				                resolve([]) | 
			
		||||
 | 
				              } | 
			
		||||
 | 
				            }) | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				        }else { | 
			
		||||
 | 
				          let channelArray = [] | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				          this.wvpService.getTree(node.data.userData.deviceId, node.data.id, this.onlyCatalog, catalogData =>{ | 
			
		||||
 | 
				            console.log(catalogData) | 
			
		||||
 | 
				            channelArray = channelArray.concat(catalogData) | 
			
		||||
 | 
				            this.channelDataHandler(channelArray, resolve) | 
			
		||||
 | 
				          },() => { | 
			
		||||
 | 
				            // 处理结束回调,如果需要 | 
			
		||||
 | 
				          }) | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      channelDataHandler: function (data, resolve) { | 
			
		||||
 | 
				        if (data.length > 0) { | 
			
		||||
 | 
				          let nodeList = [] | 
			
		||||
 | 
				          for (let i = 0; i <data.length; i++) { | 
			
		||||
 | 
				            let item = data[i]; | 
			
		||||
 | 
				            let type = 3; | 
			
		||||
 | 
				            if (item.id.length <= 10) { | 
			
		||||
 | 
				              type = 2; | 
			
		||||
 | 
				            }else { | 
			
		||||
 | 
				              if (item.id.length > 14) { | 
			
		||||
 | 
				                let channelType = item.id.substring(10, 13) | 
			
		||||
 | 
				                console.log("channelType: " + channelType) | 
			
		||||
 | 
				                if (channelType === '215' || channelType === '216') { | 
			
		||||
 | 
				                  type = 2; | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				                console.log(type) | 
			
		||||
 | 
				                if (item.basicData.ptzType === 1 ) { // 1-球机;2-半球;3-固定枪机;4-遥控枪机 | 
			
		||||
 | 
				                  type = 4; | 
			
		||||
 | 
				                }else if (item.basicData.ptzType === 2) { | 
			
		||||
 | 
				                  type = 5; | 
			
		||||
 | 
				                }else if (item.basicData.ptzType === 3 || item.basicData.ptzType === 4) { | 
			
		||||
 | 
				                  type = 6; | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				              }else { | 
			
		||||
 | 
				                if (item.basicData.subCount > 0 || item.basicData.parental === 1) { | 
			
		||||
 | 
				                  type = 2; | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				              } | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            let node = { | 
			
		||||
 | 
				              name: item.name || item.basicData.channelId, | 
			
		||||
 | 
				              isLeaf: type !== 2, | 
			
		||||
 | 
				              id: item.id, | 
			
		||||
 | 
				              deviceId: item.deviceId, | 
			
		||||
 | 
				              type: type, | 
			
		||||
 | 
				              online: item.basicData.status === 1, | 
			
		||||
 | 
				              hasGPS: item.basicData.longitude*item.basicData.latitude !== 0, | 
			
		||||
 | 
				              userData: item.basicData | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            nodeList.push(node); | 
			
		||||
 | 
				          } | 
			
		||||
 | 
				          resolve(nodeList) | 
			
		||||
 | 
				        }else { | 
			
		||||
 | 
				          resolve([]) | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      reset: function (){ | 
			
		||||
 | 
				        this.$forceUpdate(); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style lang="scss" scoped> | 
			
		||||
 | 
				.device-tree-container { | 
			
		||||
 | 
				  width: 100%; | 
			
		||||
 | 
				  height: 100%; | 
			
		||||
 | 
				  background-color: rgba(1, 10, 71, 0.9); | 
			
		||||
 | 
				  overflow: auto; | 
			
		||||
 | 
				  border-radius: 8px; | 
			
		||||
 | 
				  box-shadow: 0 0 15px rgba(0, 0, 0, 0.3); | 
			
		||||
 | 
				  border: 1px solid rgb(0, 60, 151); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.device-tree-header { | 
			
		||||
 | 
				  background-color: rgba(0, 19, 86, 0.9); | 
			
		||||
 | 
				  color: white; | 
			
		||||
 | 
				  display: flex; | 
			
		||||
 | 
				  align-items: center; | 
			
		||||
 | 
				  font-size: 16px; | 
			
		||||
 | 
				  font-weight: bold; | 
			
		||||
 | 
				  border-bottom: 1px solid rgba(0, 80, 255, 0.3); | 
			
		||||
 | 
				  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); | 
			
		||||
 | 
				  text-shadow: 0 0 10px rgba(0, 200, 255, 0.4); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.device-tree-main { | 
			
		||||
 | 
				  background-color: rgba(24, 26, 45, 0.7); | 
			
		||||
 | 
				  padding: 10px; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.device-tree-main-box { | 
			
		||||
 | 
				  text-align: left; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.custom-tree { | 
			
		||||
 | 
				  background-color: transparent; | 
			
		||||
 | 
				  color: white; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.custom-tree-node { | 
			
		||||
 | 
				  width: 100%; | 
			
		||||
 | 
				  display: flex; | 
			
		||||
 | 
				  align-items: center; | 
			
		||||
 | 
				  padding: 2px 0; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.device-online { | 
			
		||||
 | 
				  color: rgb(0, 255, 128); | 
			
		||||
 | 
				  margin-right: 5px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  &.iconfont { | 
			
		||||
 | 
				    font-size: 16px; | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.device-offline { | 
			
		||||
 | 
				  color: #727272; | 
			
		||||
 | 
				  margin-right: 5px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  &.iconfont { | 
			
		||||
 | 
				    font-size: 16px; | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.device-label { | 
			
		||||
 | 
				  padding-left: 1px; | 
			
		||||
 | 
				  flex: 1; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				.gps-icon { | 
			
		||||
 | 
				  font-size: 14px; | 
			
		||||
 | 
				  margin-left: 5px; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				/* 覆盖Element-UI树的默认样式 */ | 
			
		||||
 | 
				:deep(.el-tree) { | 
			
		||||
 | 
				  background-color: transparent; | 
			
		||||
 | 
				  color: white; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				:deep(.el-tree-node__content) { | 
			
		||||
 | 
				  background-color: transparent; | 
			
		||||
 | 
				  border-bottom: 1px solid rgba(0, 60, 151, 0.2); | 
			
		||||
 | 
				  padding: 5px 0; | 
			
		||||
 | 
				  transition: all 0.3s; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  &:hover { | 
			
		||||
 | 
				    background-color: rgba(0, 60, 151, 0.3); | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  &:active, &.is-current { | 
			
		||||
 | 
				    background-color: rgba(0, 100, 255, 0.3); | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				:deep(.el-tree-node__expand-icon) { | 
			
		||||
 | 
				  color: rgba(0, 200, 255, 0.8); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				:deep(.el-tree-node__expand-icon.is-leaf) { | 
			
		||||
 | 
				  color: transparent; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				:deep(.el-tree-node__expand-icon.expanded) { | 
			
		||||
 | 
				  transform: rotate(90deg); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				:deep(.el-tree-node:focus > .el-tree-node__content) { | 
			
		||||
 | 
				  background-color: rgba(0, 100, 255, 0.3); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,373 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <el-dialog | 
			
		||||
 | 
				    v-if="dialogVisible" | 
			
		||||
 | 
				    v-el-drag-dialog | 
			
		||||
 | 
				    :title="showTitle" | 
			
		||||
 | 
				    :visible.sync="dialogVisible" | 
			
		||||
 | 
				    width="780px" | 
			
		||||
 | 
				    class="custom-dialog" | 
			
		||||
 | 
				  > | 
			
		||||
 | 
				    <el-form | 
			
		||||
 | 
				      v-if="dialogVisible" | 
			
		||||
 | 
				      ref="editForm" | 
			
		||||
 | 
				      :rules="rules" | 
			
		||||
 | 
				      size="mini" | 
			
		||||
 | 
				      :model="form" | 
			
		||||
 | 
				      label-position="right" | 
			
		||||
 | 
				      label-width="130px" | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="企业ID" prop="companyinfoId"> | 
			
		||||
 | 
				            <el-input v-model="form.companyinfoId" placeholder="请输入企业ID" /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="企业行业类型" prop="industryType"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.industryType" | 
			
		||||
 | 
				              placeholder="请选择行业类型" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option label="金属制品加工" value="1" /> | 
			
		||||
 | 
				              <el-option label="农副产品加工" value="2" /> | 
			
		||||
 | 
				              <el-option label="木制品加工" value="3" /> | 
			
		||||
 | 
				              <el-option label="纸制品加工" value="4" /> | 
			
		||||
 | 
				              <el-option label="纺织品加工" value="5" /> | 
			
		||||
 | 
				              <el-option label="橡胶和塑料制品加工" value="6" /> | 
			
		||||
 | 
				              <el-option label="冶金/有色/建材行业煤粉制备" value="7" /> | 
			
		||||
 | 
				              <el-option label="其他" value="8" /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="24"> | 
			
		||||
 | 
				          <el-form-item label="主要粉尘类型" prop="dustType"> | 
			
		||||
 | 
				            <el-cascader | 
			
		||||
 | 
				              v-model="form.dustType" | 
			
		||||
 | 
				              :options="options.dustTypeOptionsTree" | 
			
		||||
 | 
				              placeholder="请选择主要粉尘类型" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="24"> | 
			
		||||
 | 
				          <el-form-item label="粉尘高风险工艺" prop="dustTechnology"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.dustTechnology" | 
			
		||||
 | 
				              placeholder="可多选" | 
			
		||||
 | 
				              multiple | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option label="铝镁金属打磨抛光" value="1" /> | 
			
		||||
 | 
				              <el-option label="铝镁金属喷砂抛丸" value="2" /> | 
			
		||||
 | 
				              <el-option label="其他金属打磨抛光" value="3" /> | 
			
		||||
 | 
				              <el-option label="其他金属喷砂抛丸" value="4" /> | 
			
		||||
 | 
				              <el-option label="木材砂光" value="5" /> | 
			
		||||
 | 
				              <el-option label="静电喷涂" value="6" /> | 
			
		||||
 | 
				              <el-option label="粉碎研磨" value="7" /> | 
			
		||||
 | 
				              <el-option label="造粒" value="8" /> | 
			
		||||
 | 
				              <el-option label="无" value="9" /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="日产尘量" prop="dailyDustOutput"> | 
			
		||||
 | 
				            <el-input v-model="form.dailyDustOutput" type="number" placeholder="单位:Kg"> | 
			
		||||
 | 
				              <template slot="append">Kg</template> | 
			
		||||
 | 
				            </el-input> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="单班最高涉粉人数" prop="dustInvolvedPersonNo"> | 
			
		||||
 | 
				            <el-input-number | 
			
		||||
 | 
				              v-model="form.dustInvolvedPersonNo" | 
			
		||||
 | 
				              placeholder="每日单班最高涉粉作业人数" | 
			
		||||
 | 
				              :min="0" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="24"> | 
			
		||||
 | 
				          <el-form-item label="其他涉及粉尘信息" prop="otheRdust"> | 
			
		||||
 | 
				            <el-input | 
			
		||||
 | 
				              v-model="form.otheRdust" | 
			
		||||
 | 
				              type="textarea" | 
			
		||||
 | 
				              :rows="3" | 
			
		||||
 | 
				              placeholder="格式:粉尘种类,日产尘量Kg;多记录分号分隔,例如A2,100;A3,300;A5,150" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="有效标记" prop="actived"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.actived" | 
			
		||||
 | 
				              placeholder="请选择是否有效" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option label="无效" value="0" /> | 
			
		||||
 | 
				              <el-option label="有效" value="1" /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20" > | 
			
		||||
 | 
				        <el-col v-if="editType !== 'edit'" :span="12"> | 
			
		||||
 | 
				          <el-form-item label="创建人" prop="creatorName"> | 
			
		||||
 | 
				            <el-input v-model="form.creatorName" disabled /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col v-if="editType === 'edit'" :span="12"> | 
			
		||||
 | 
				          <el-form-item label="修改人" prop="updatorName"> | 
			
		||||
 | 
				            <el-input v-model="form.updatorName" /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				    </el-form> | 
			
		||||
 | 
				    <div slot="footer" class="dialog-footer"> | 
			
		||||
 | 
				      <el-button @click="dialogVisible = false"> 取消 </el-button> | 
			
		||||
 | 
				      <el-button type="primary" :loading="loading" @click="onSubmit"> | 
			
		||||
 | 
				        确定 | 
			
		||||
 | 
				      </el-button> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				  </el-dialog> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    title: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: "", | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    url: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return {}; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    options: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return {}; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      dialogVisible: false, | 
			
		||||
 | 
				      loading: false, | 
			
		||||
 | 
				      form: { | 
			
		||||
 | 
				        companyinfoId: "", | 
			
		||||
 | 
				        industryType: "", | 
			
		||||
 | 
				        dustTechnology: "", | 
			
		||||
 | 
				        dustType: "", | 
			
		||||
 | 
				        dailyDustOutput: "", | 
			
		||||
 | 
				        otheRdust: "", | 
			
		||||
 | 
				        dustInvolvedPersonNo: "", | 
			
		||||
 | 
				        actived: "1", // 默认有效 | 
			
		||||
 | 
				        creatorName: "", | 
			
		||||
 | 
				        createTime: "", | 
			
		||||
 | 
				        updatorName: "", | 
			
		||||
 | 
				        updateTime: "", | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      editType: "add", //add或edit | 
			
		||||
 | 
				      rules: { | 
			
		||||
 | 
				        companyinfoId: [ | 
			
		||||
 | 
				          { required: true, message: "请输入企业ID", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        industryType: [ | 
			
		||||
 | 
				          { required: true, message: "请选择企业行业类型", trigger: "change" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        dustTechnology: [ | 
			
		||||
 | 
				          { | 
			
		||||
 | 
				            required: true, | 
			
		||||
 | 
				            message: "请选择粉尘高风险工艺", | 
			
		||||
 | 
				            trigger: "change", | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        dustType: [ | 
			
		||||
 | 
				          { required: true, message: "请输入主要粉尘类型", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        dailyDustOutput: [ | 
			
		||||
 | 
				          { required: true, message: "请输入日产尘量", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        dustInvolvedPersonNo: [ | 
			
		||||
 | 
				          { | 
			
		||||
 | 
				            required: true, | 
			
		||||
 | 
				            message: "请输入单班最高涉粉人数", | 
			
		||||
 | 
				            trigger: "blur", | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        actived: [ | 
			
		||||
 | 
				          { required: true, message: "请选择是否有效", trigger: "change" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  computed: { | 
			
		||||
 | 
				    showTitle() { | 
			
		||||
 | 
				      return this.editType == "edit" | 
			
		||||
 | 
				        ? "编辑" + this.title | 
			
		||||
 | 
				        : "新增" + this.title; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    reset() { | 
			
		||||
 | 
				      this.editType = "add"; | 
			
		||||
 | 
				      // this.$refs.elForm.resetFields(); | 
			
		||||
 | 
				      this.loading = false; | 
			
		||||
 | 
				      this.form = this.$options.data().form; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    show(form) { | 
			
		||||
 | 
				      this.reset(); | 
			
		||||
 | 
				      if (form) { | 
			
		||||
 | 
				        this.editType = "edit"; | 
			
		||||
 | 
				        this.form = { ...this.$options.data().form, ...form }; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      this.dialogVisible = true; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    onSubmit() { | 
			
		||||
 | 
				      this.$refs.editForm.validate((valid) => { | 
			
		||||
 | 
				        if (!valid) { | 
			
		||||
 | 
				          return false; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        this.loading = true; | 
			
		||||
 | 
				        let q; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        if (this.editType == "edit") { | 
			
		||||
 | 
				          q = this.$axios.put(this.url.edit, { | 
			
		||||
 | 
				            ...this.form, | 
			
		||||
 | 
				            dustTechnology: this.form.dustTechnology.join(","), | 
			
		||||
 | 
				            dustType: this.form.dustType[1], | 
			
		||||
 | 
				          }); | 
			
		||||
 | 
				        } else { | 
			
		||||
 | 
				          q = this.$axios.post(this.url.add, { | 
			
		||||
 | 
				            ...this.form, | 
			
		||||
 | 
				            dustTechnology: this.form.dustTechnology.join(","), | 
			
		||||
 | 
				            dustType: this.form.dustType[1], | 
			
		||||
 | 
				          }); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        q.then(({ message }) => { | 
			
		||||
 | 
				          this.$message({ type: "info", message: message }); | 
			
		||||
 | 
				          this.dialogVisible = false; | 
			
		||||
 | 
				          this.$emit("refresh"); | 
			
		||||
 | 
				        }).finally(() => { | 
			
		||||
 | 
				          this.loading = false; | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style lang="scss" scoped> | 
			
		||||
 | 
				.custom-dialog { | 
			
		||||
 | 
				  ::v-deep .el-dialog { | 
			
		||||
 | 
				    background-color: rgba(4, 0, 79, 0.98); | 
			
		||||
 | 
				    border: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				    border-radius: 4px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-dialog__header { | 
			
		||||
 | 
				      background-color: rgba(0, 8, 59, 0.9); | 
			
		||||
 | 
				      padding: 15px 20px; | 
			
		||||
 | 
				      border-bottom: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      .el-dialog__title { | 
			
		||||
 | 
				        color: #e0e0ff; | 
			
		||||
 | 
				        font-weight: bold; | 
			
		||||
 | 
				        font-size: 16px; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      .el-dialog__headerbtn .el-dialog__close { | 
			
		||||
 | 
				        color: #e0e0ff; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-dialog__body { | 
			
		||||
 | 
				      padding: 20px; | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-dialog__footer { | 
			
		||||
 | 
				      padding: 10px 20px; | 
			
		||||
 | 
				      border-top: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      background-color: rgba(0, 8, 59, 0.7); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .el-form-item { | 
			
		||||
 | 
				    margin-bottom: 15px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-form-item__label { | 
			
		||||
 | 
				      color: #c0c4cc; | 
			
		||||
 | 
				      font-size: 13px; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-input__inner, | 
			
		||||
 | 
				    ::v-deep .el-input-number__decrease, | 
			
		||||
 | 
				    ::v-deep .el-input-number__increase { | 
			
		||||
 | 
				      background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				      border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &::placeholder { | 
			
		||||
 | 
				        color: rgba(195, 195, 219, 0.5); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-textarea__inner { | 
			
		||||
 | 
				      background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				      border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &::placeholder { | 
			
		||||
 | 
				        color: rgba(195, 195, 219, 0.5); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-select .el-input .el-select__caret { | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .dialog-footer { | 
			
		||||
 | 
				    text-align: right; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-button { | 
			
		||||
 | 
				      background-color: rgba(30, 27, 110, 0.7); | 
			
		||||
 | 
				      border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &:hover { | 
			
		||||
 | 
				        background-color: rgba(40, 36, 124, 0.8); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &[type="primary"] { | 
			
		||||
 | 
				        background-color: #1976d2; | 
			
		||||
 | 
				        border-color: #1565c0; | 
			
		||||
 | 
				        color: #ffffff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        &:hover { | 
			
		||||
 | 
				          background-color: #1e88e5; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,459 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <el-dialog | 
			
		||||
 | 
				    v-if="dialogVisible" | 
			
		||||
 | 
				    v-el-drag-dialog | 
			
		||||
 | 
				    :title="showTitle" | 
			
		||||
 | 
				    :visible.sync="dialogVisible" | 
			
		||||
 | 
				    width="650px" | 
			
		||||
 | 
				    class="custom-dialog" | 
			
		||||
 | 
				  > | 
			
		||||
 | 
				    <el-form | 
			
		||||
 | 
				      v-if="dialogVisible" | 
			
		||||
 | 
				      ref="editForm" | 
			
		||||
 | 
				      :rules="rules" | 
			
		||||
 | 
				      size="mini" | 
			
		||||
 | 
				      :model="form" | 
			
		||||
 | 
				      label-position="right" | 
			
		||||
 | 
				      label-width="120px" | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="设备编号" prop="equipCode"> | 
			
		||||
 | 
				            <el-input | 
			
		||||
 | 
				              v-model="form.equipCode" | 
			
		||||
 | 
				              placeholder="数据接入标识(10位)+3位流水编码" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="设备名称" prop="equipName"> | 
			
		||||
 | 
				            <el-input v-model="form.equipName" placeholder="请输入设备名称" /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="企业ID" prop="companyinfoId"> | 
			
		||||
 | 
				            <el-input v-model="form.companyinfoId" placeholder="请输入企业ID" /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="场所编码" prop="placeCode"> | 
			
		||||
 | 
				            <el-input | 
			
		||||
 | 
				              v-model="form.placeCode" | 
			
		||||
 | 
				              placeholder="场所在系统中原属车间" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="设备类型" prop="equipType"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.equipType" | 
			
		||||
 | 
				              placeholder="请选择设备类型" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option label="干式集中式除尘系统" value="1" /> | 
			
		||||
 | 
				              <el-option label="湿式集中式除尘系统" value="2" /> | 
			
		||||
 | 
				              <el-option label="湿式单机除系统" value="3" /> | 
			
		||||
 | 
				              <el-option label="干式单机除系统" value="4" /> | 
			
		||||
 | 
				              <el-option label="其它" value="5" /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="设备厂家" prop="equipFactory"> | 
			
		||||
 | 
				            <el-input | 
			
		||||
 | 
				              v-model="form.equipFactory" | 
			
		||||
 | 
				              placeholder="请输入设备厂家" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="安装日期" prop="setDate"> | 
			
		||||
 | 
				            <el-date-picker | 
			
		||||
 | 
				              value-format="yyyy-MM-dd HH:mm:ss" | 
			
		||||
 | 
				              v-model="form.setDate" | 
			
		||||
 | 
				              type="datetime" | 
			
		||||
 | 
				              placeholder="选择安装日期" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="安装区域" prop="installArea"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.installArea" | 
			
		||||
 | 
				              placeholder="请选择安装区域" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option label="室内" value="1" /> | 
			
		||||
 | 
				              <el-option label="室外" value="2" /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="24"> | 
			
		||||
 | 
				          <el-form-item label="相关控制措施" prop="bombControl"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.bombControl" | 
			
		||||
 | 
				              placeholder="可多选" | 
			
		||||
 | 
				              multiple | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option label="泄爆" value="1" /> | 
			
		||||
 | 
				              <el-option label="抑爆" value="2" /> | 
			
		||||
 | 
				              <el-option label="隔爆" value="3" /> | 
			
		||||
 | 
				              <el-option label="惰化" value="4" /> | 
			
		||||
 | 
				              <el-option label="其他" value="5" /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="24"> | 
			
		||||
 | 
				          <el-form-item label="除去粉尘种类" prop="dustType"> | 
			
		||||
 | 
				            <el-cascader | 
			
		||||
 | 
				              v-model="form.dustType" | 
			
		||||
 | 
				              :options="options.dustTypeOptionsTree" | 
			
		||||
 | 
				              placeholder="请选择粉尘种类" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="除尘涉及人数" prop="workersNumber"> | 
			
		||||
 | 
				            <el-input-number | 
			
		||||
 | 
				              v-model="form.workersNumber" | 
			
		||||
 | 
				              placeholder="单班最高作业人数" | 
			
		||||
 | 
				              :min="0" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="24"> | 
			
		||||
 | 
				          <el-form-item label="涉及云量工艺" prop="dustTechnology"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.dustTechnology" | 
			
		||||
 | 
				              placeholder="可多选" | 
			
		||||
 | 
				              multiple | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option | 
			
		||||
 | 
				                v-for="item in options.dustTechnologyOptions" | 
			
		||||
 | 
				                :key="item.value" | 
			
		||||
 | 
				                :label="item.label" | 
			
		||||
 | 
				                :value="item.value" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="单日产尘量" prop="dailyDustOutput"> | 
			
		||||
 | 
				            <el-input v-model="form.dailyDustOutput" placeholder="单位:Kg" type="number"> | 
			
		||||
 | 
				              <template slot="append">Kg</template> | 
			
		||||
 | 
				            </el-input> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="系统状态" prop="equipStatus"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.equipStatus" | 
			
		||||
 | 
				              placeholder="请选择系统状态" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option | 
			
		||||
 | 
				                v-for="item in options.equipStatusOptions" | 
			
		||||
 | 
				                :key="item.value" | 
			
		||||
 | 
				                :label="item.label" | 
			
		||||
 | 
				                :value="item.value" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col :span="12"> | 
			
		||||
 | 
				          <el-form-item label="有效标志" prop="active"> | 
			
		||||
 | 
				            <el-select | 
			
		||||
 | 
				              v-model="form.active" | 
			
		||||
 | 
				              placeholder="请选择是否有效" | 
			
		||||
 | 
				              style="width: 100%" | 
			
		||||
 | 
				            > | 
			
		||||
 | 
				              <el-option | 
			
		||||
 | 
				                v-for="item in options.activeOptions" | 
			
		||||
 | 
				                :key="item.value" | 
			
		||||
 | 
				                :label="item.label" | 
			
		||||
 | 
				                :value="item.value" | 
			
		||||
 | 
				              /> | 
			
		||||
 | 
				            </el-select> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <el-row :gutter="20"> | 
			
		||||
 | 
				        <el-col v-if="editType === 'add'" :span="12"> | 
			
		||||
 | 
				          <el-form-item label="创建人" prop="creatorName"> | 
			
		||||
 | 
				            <el-input v-model="form.creatorName" /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				        <el-col v-if="editType === 'edit'" :span="12"> | 
			
		||||
 | 
				          <el-form-item label="修改人" prop="updatorName"> | 
			
		||||
 | 
				            <el-input v-model="form.updatorName" /> | 
			
		||||
 | 
				          </el-form-item> | 
			
		||||
 | 
				        </el-col> | 
			
		||||
 | 
				      </el-row> | 
			
		||||
 | 
				    </el-form> | 
			
		||||
 | 
				    <div slot="footer" class="dialog-footer"> | 
			
		||||
 | 
				      <el-button @click="dialogVisible = false"> 取消 </el-button> | 
			
		||||
 | 
				      <el-button type="primary" :loading="loading" @click="onSubmit"> | 
			
		||||
 | 
				        确定 | 
			
		||||
 | 
				      </el-button> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				  </el-dialog> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    title: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: "", | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    url: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return {}; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    options: { | 
			
		||||
 | 
				      type: Object, | 
			
		||||
 | 
				      default: () => { | 
			
		||||
 | 
				        return {}; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      dialogVisible: false, | 
			
		||||
 | 
				      loading: false, | 
			
		||||
 | 
				      form: { | 
			
		||||
 | 
				        id: "", | 
			
		||||
 | 
				        equipCode: "", | 
			
		||||
 | 
				        equipName: "", | 
			
		||||
 | 
				        companyinfoId: "", | 
			
		||||
 | 
				        placeCode: "", | 
			
		||||
 | 
				        equipType: "", | 
			
		||||
 | 
				        equipFactory: "", | 
			
		||||
 | 
				        setDate: "", | 
			
		||||
 | 
				        bombControl: "", | 
			
		||||
 | 
				        installArea: "", | 
			
		||||
 | 
				        dustType: "", | 
			
		||||
 | 
				        workersNumber: "", | 
			
		||||
 | 
				        dustTechnology: "", | 
			
		||||
 | 
				        dailyDustOutput: "", | 
			
		||||
 | 
				        equipStatus: "1", // 默认启用 | 
			
		||||
 | 
				        active: "1", // 默认有效 | 
			
		||||
 | 
				        creatorName: "", | 
			
		||||
 | 
				        createTime: "", | 
			
		||||
 | 
				        updatorName: "", | 
			
		||||
 | 
				        updateTime: "", | 
			
		||||
 | 
				        delFlag: "0", // 默认未删除 | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      editType: "add", //add或edit | 
			
		||||
 | 
				      rules: { | 
			
		||||
 | 
				        equipCode: [ | 
			
		||||
 | 
				          { required: true, message: "请输入设备编号", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        equipName: [ | 
			
		||||
 | 
				          { required: true, message: "请输入设备名称", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        companyinfoId: [ | 
			
		||||
 | 
				          { required: true, message: "请输入企业ID", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        equipType: [ | 
			
		||||
 | 
				          { required: true, message: "请选择设备类型", trigger: "change" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        installArea: [ | 
			
		||||
 | 
				          { required: true, message: "请选择安装区域", trigger: "change" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        dustType: [ | 
			
		||||
 | 
				          { required: true, message: "请输入粉尘种类", trigger: "blur" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        equipStatus: [ | 
			
		||||
 | 
				          { required: true, message: "请选择系统状态", trigger: "change" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				        active: [ | 
			
		||||
 | 
				          { required: true, message: "请选择是否有效", trigger: "change" }, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  computed: { | 
			
		||||
 | 
				    showTitle() { | 
			
		||||
 | 
				      return this.editType == "edit" | 
			
		||||
 | 
				        ? "编辑" + this.title | 
			
		||||
 | 
				        : "新增" + this.title; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    reset() { | 
			
		||||
 | 
				      this.editType = "add"; | 
			
		||||
 | 
				      // this.$refs.elForm.resetFields(); | 
			
		||||
 | 
				      this.loading = false; | 
			
		||||
 | 
				      this.form = this.$options.data().form; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    show(form) { | 
			
		||||
 | 
				      this.reset(); | 
			
		||||
 | 
				      if (form) { | 
			
		||||
 | 
				        this.editType = "edit"; | 
			
		||||
 | 
				        this.form = { ...this.$options.data().form, ...form }; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				      this.dialogVisible = true; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    onSubmit() { | 
			
		||||
 | 
				      this.$refs.editForm.validate((valid) => { | 
			
		||||
 | 
				        if (!valid) { | 
			
		||||
 | 
				          return false; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        this.loading = true; | 
			
		||||
 | 
				        let q; | 
			
		||||
 | 
				        if (this.editType == "edit") { | 
			
		||||
 | 
				          q = this.$axios.put(this.url.edit, { | 
			
		||||
 | 
				            ...this.form, | 
			
		||||
 | 
				            bombControl: this.form.bombControl.join(","), | 
			
		||||
 | 
				            dustTechnology: this.form.dustTechnology.join(","), | 
			
		||||
 | 
				            dustType: this.form.dustType[1], | 
			
		||||
 | 
				          }); | 
			
		||||
 | 
				        } else { | 
			
		||||
 | 
				          q = this.$axios.post(this.url.add, { | 
			
		||||
 | 
				            ...this.form, | 
			
		||||
 | 
				            bombControl: this.form.bombControl.join(","), | 
			
		||||
 | 
				            dustTechnology: this.form.dustTechnology.join(","), | 
			
		||||
 | 
				            dustType: this.form.dustType[1], | 
			
		||||
 | 
				          }); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        q.then(({ message }) => { | 
			
		||||
 | 
				          this.$message({ type: "info", message: message }); | 
			
		||||
 | 
				          this.dialogVisible = false; | 
			
		||||
 | 
				          this.$emit("refresh"); | 
			
		||||
 | 
				        }).finally(() => { | 
			
		||||
 | 
				          this.loading = false; | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style lang="scss" scoped> | 
			
		||||
 | 
				.custom-dialog { | 
			
		||||
 | 
				  ::v-deep .el-dialog { | 
			
		||||
 | 
				    background-color: rgba(4, 0, 79, 0.98); | 
			
		||||
 | 
				    border: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				    border-radius: 4px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-dialog__header { | 
			
		||||
 | 
				      background-color: rgba(0, 8, 59, 0.9); | 
			
		||||
 | 
				      padding: 15px 20px; | 
			
		||||
 | 
				      border-bottom: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      .el-dialog__title { | 
			
		||||
 | 
				        color: #e0e0ff; | 
			
		||||
 | 
				        font-weight: bold; | 
			
		||||
 | 
				        font-size: 16px; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      .el-dialog__headerbtn .el-dialog__close { | 
			
		||||
 | 
				        color: #e0e0ff; | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-dialog__body { | 
			
		||||
 | 
				      padding: 20px; | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-dialog__footer { | 
			
		||||
 | 
				      padding: 10px 20px; | 
			
		||||
 | 
				      border-top: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      background-color: rgba(0, 8, 59, 0.7); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .el-form-item { | 
			
		||||
 | 
				    margin-bottom: 15px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-form-item__label { | 
			
		||||
 | 
				      color: #c0c4cc; | 
			
		||||
 | 
				      font-size: 13px; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-input__inner, | 
			
		||||
 | 
				    ::v-deep .el-input-number__decrease, | 
			
		||||
 | 
				    ::v-deep .el-input-number__increase { | 
			
		||||
 | 
				      background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				      border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &::placeholder { | 
			
		||||
 | 
				        color: rgba(195, 195, 219, 0.5); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-textarea__inner { | 
			
		||||
 | 
				      background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				      border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &::placeholder { | 
			
		||||
 | 
				        color: rgba(195, 195, 219, 0.5); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ::v-deep .el-select .el-input .el-select__caret { | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  .dialog-footer { | 
			
		||||
 | 
				    text-align: right; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-button { | 
			
		||||
 | 
				      background-color: rgba(30, 27, 110, 0.7); | 
			
		||||
 | 
				      border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				      color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &:hover { | 
			
		||||
 | 
				        background-color: rgba(40, 36, 124, 0.8); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      &[type="primary"] { | 
			
		||||
 | 
				        background-color: #1976d2; | 
			
		||||
 | 
				        border-color: #1565c0; | 
			
		||||
 | 
				        color: #ffffff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        &:hover { | 
			
		||||
 | 
				          background-color: #1e88e5; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,324 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				    <el-dialog | 
			
		||||
 | 
				        v-if="dialogVisible" | 
			
		||||
 | 
				        v-el-drag-dialog | 
			
		||||
 | 
				        :title="showTitle" | 
			
		||||
 | 
				        :visible.sync="dialogVisible" | 
			
		||||
 | 
				        width="650px" | 
			
		||||
 | 
				        class="custom-dialog" | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				        <el-form | 
			
		||||
 | 
				            v-if="dialogVisible" | 
			
		||||
 | 
				            :rules="rules" | 
			
		||||
 | 
				            ref="editForm" | 
			
		||||
 | 
				            size="mini" | 
			
		||||
 | 
				            :model="form" | 
			
		||||
 | 
				            label-position="right" | 
			
		||||
 | 
				            label-width="120px" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				            <el-row :gutter="20"> | 
			
		||||
 | 
				                <el-col :span="12"> | 
			
		||||
 | 
				                    <el-form-item label="预警编号" prop="id"> | 
			
		||||
 | 
				                        <el-input v-model="form.id" placeholder="主键,唯一"/> | 
			
		||||
 | 
				                    </el-form-item> | 
			
		||||
 | 
				                </el-col> | 
			
		||||
 | 
				                <el-col :span="12"> | 
			
		||||
 | 
				                    <el-form-item label="系统ID" prop="equipinfoId"> | 
			
		||||
 | 
				                        <el-input v-model="form.equipinfoId" placeholder="请输入系统ID"/> | 
			
		||||
 | 
				                    </el-form-item> | 
			
		||||
 | 
				                </el-col> | 
			
		||||
 | 
				            </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            <el-row :gutter="20"> | 
			
		||||
 | 
				                <el-col :span="12"> | 
			
		||||
 | 
				                    <el-form-item label="数据接入标识" prop="dataId"> | 
			
		||||
 | 
				                        <el-input v-model="form.dataId" placeholder="请输入数据接入标识"/> | 
			
		||||
 | 
				                    </el-form-item> | 
			
		||||
 | 
				                </el-col> | 
			
		||||
 | 
				                <el-col :span="12"> | 
			
		||||
 | 
				                    <el-form-item label="预警等级" prop="warningRank"> | 
			
		||||
 | 
				                        <el-select v-model="form.warningRank" placeholder="请选择预警等级" style="width: 100%;"> | 
			
		||||
 | 
				                            <el-option | 
			
		||||
 | 
				                                v-for="item in options.rankOptions" | 
			
		||||
 | 
				                                :key="item.value" | 
			
		||||
 | 
				                                :label="item.label" | 
			
		||||
 | 
				                                :value="item.value" | 
			
		||||
 | 
				                            /> | 
			
		||||
 | 
				                        </el-select> | 
			
		||||
 | 
				                    </el-form-item> | 
			
		||||
 | 
				                </el-col> | 
			
		||||
 | 
				            </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            <el-row :gutter="20"> | 
			
		||||
 | 
				                <el-col :span="12"> | 
			
		||||
 | 
				                    <el-form-item label="反馈时间" prop="realTime"> | 
			
		||||
 | 
				                        <el-date-picker | 
			
		||||
 | 
				                            v-model="form.realTime" | 
			
		||||
 | 
				                            type="datetime" | 
			
		||||
 | 
				                            placeholder="选择反馈时间" | 
			
		||||
 | 
				                            style="width: 100%;" | 
			
		||||
 | 
				                        /> | 
			
		||||
 | 
				                    </el-form-item> | 
			
		||||
 | 
				                </el-col> | 
			
		||||
 | 
				                <el-col :span="12"> | 
			
		||||
 | 
				                    <el-form-item label="填报人" prop="fillBy"> | 
			
		||||
 | 
				                        <el-input v-model="form.fillBy" placeholder="请输入填报人"/> | 
			
		||||
 | 
				                    </el-form-item> | 
			
		||||
 | 
				                </el-col> | 
			
		||||
 | 
				            </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            <el-row :gutter="20"> | 
			
		||||
 | 
				                <el-col :span="12"> | 
			
		||||
 | 
				                    <el-form-item label="有效标记" prop="actived"> | 
			
		||||
 | 
				                        <el-select v-model="form.actived" placeholder="请选择有效标记" style="width: 100%;"> | 
			
		||||
 | 
				                            <el-option | 
			
		||||
 | 
				                                v-for="item in options.activedOptions" | 
			
		||||
 | 
				                                :key="item.value" | 
			
		||||
 | 
				                                :label="item.label" | 
			
		||||
 | 
				                                :value="item.value" | 
			
		||||
 | 
				                            /> | 
			
		||||
 | 
				                        </el-select> | 
			
		||||
 | 
				                    </el-form-item> | 
			
		||||
 | 
				                </el-col> | 
			
		||||
 | 
				                <el-col :span="12"> | 
			
		||||
 | 
				                    <el-form-item label="删除标记" prop="delFlag"> | 
			
		||||
 | 
				                        <el-select v-model="form.delFlag" placeholder="请选择删除标记" style="width: 100%;"> | 
			
		||||
 | 
				                            <el-option | 
			
		||||
 | 
				                                v-for="item in options.delFlagOptions" | 
			
		||||
 | 
				                                :key="item.value" | 
			
		||||
 | 
				                                :label="item.label" | 
			
		||||
 | 
				                                :value="item.value" | 
			
		||||
 | 
				                            /> | 
			
		||||
 | 
				                        </el-select> | 
			
		||||
 | 
				                    </el-form-item> | 
			
		||||
 | 
				                </el-col> | 
			
		||||
 | 
				            </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            <el-row :gutter="20"> | 
			
		||||
 | 
				                <el-col :span="12"> | 
			
		||||
 | 
				                    <el-form-item label="创建人" prop="creatorName"> | 
			
		||||
 | 
				                        <el-input v-model="form.creatorName" placeholder="请输入创建人"/> | 
			
		||||
 | 
				                    </el-form-item> | 
			
		||||
 | 
				                </el-col> | 
			
		||||
 | 
				                <el-col :span="12"> | 
			
		||||
 | 
				                    <el-form-item label="修改人" prop="updatorName"> | 
			
		||||
 | 
				                        <el-input v-model="form.updatorName" placeholder="请输入修改人"/> | 
			
		||||
 | 
				                    </el-form-item> | 
			
		||||
 | 
				                </el-col> | 
			
		||||
 | 
				            </el-row> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            <el-form-item label="企业反馈信息" prop="warnFeedback"> | 
			
		||||
 | 
				                <el-input v-model="form.warnFeedback" type="textarea" placeholder="请输入企业反馈信息" :rows="3"/> | 
			
		||||
 | 
				            </el-form-item> | 
			
		||||
 | 
				        </el-form> | 
			
		||||
 | 
				        <div slot="footer" class="dialog-footer"> | 
			
		||||
 | 
				            <el-button @click="dialogVisible = false"> 取消 </el-button> | 
			
		||||
 | 
				            <el-button type="primary" :loading="loading" @click="onSubmit"> | 
			
		||||
 | 
				                确定 | 
			
		||||
 | 
				            </el-button> | 
			
		||||
 | 
				        </div> | 
			
		||||
 | 
				    </el-dialog> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				    export default { | 
			
		||||
 | 
				        props: { | 
			
		||||
 | 
				            title: { | 
			
		||||
 | 
				                type: String, | 
			
		||||
 | 
				                default: "", | 
			
		||||
 | 
				            }, | 
			
		||||
 | 
				            url: { | 
			
		||||
 | 
				                type: Object, | 
			
		||||
 | 
				                default: () => { | 
			
		||||
 | 
				                    return {}; | 
			
		||||
 | 
				                }, | 
			
		||||
 | 
				            }, | 
			
		||||
 | 
				            options: { | 
			
		||||
 | 
				                type: Object, | 
			
		||||
 | 
				                default: () => { | 
			
		||||
 | 
				                    return { | 
			
		||||
 | 
				                    }; | 
			
		||||
 | 
				                }, | 
			
		||||
 | 
				            }, | 
			
		||||
 | 
				        }, | 
			
		||||
 | 
				        data() { | 
			
		||||
 | 
				            return { | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				                dialogVisible: false, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				                loading: false, | 
			
		||||
 | 
				                form: { | 
			
		||||
 | 
				                    id:"", | 
			
		||||
 | 
				                    equipinfoId:"", | 
			
		||||
 | 
				                    dataId:"", | 
			
		||||
 | 
				                    warningRank:"", | 
			
		||||
 | 
				                    warnFeedback:"", | 
			
		||||
 | 
				                    realTime:"", | 
			
		||||
 | 
				                    fillBy:"", | 
			
		||||
 | 
				                    actived:"1", // 默认为有效 | 
			
		||||
 | 
				                    creatorName:"", | 
			
		||||
 | 
				                    createTime:"", | 
			
		||||
 | 
				                    updatorName:"", | 
			
		||||
 | 
				                    updateTime:"", | 
			
		||||
 | 
				                }, | 
			
		||||
 | 
				                editType:"add", //add或edit | 
			
		||||
 | 
				                rules: { | 
			
		||||
 | 
				                    equipinfoId: [ | 
			
		||||
 | 
				                        { required: true, message: '请输入系统ID', trigger: 'blur' } | 
			
		||||
 | 
				                    ], | 
			
		||||
 | 
				                    dataId: [ | 
			
		||||
 | 
				                        { required: true, message: '请输入数据接入标识', trigger: 'blur' } | 
			
		||||
 | 
				                    ], | 
			
		||||
 | 
				                    warningRank: [ | 
			
		||||
 | 
				                        { required: true, message: '请选择预警等级', trigger: 'change' } | 
			
		||||
 | 
				                    ], | 
			
		||||
 | 
				                    warnFeedback: [ | 
			
		||||
 | 
				                        { required: true, message: '请输入企业反馈信息', trigger: 'blur' } | 
			
		||||
 | 
				                    ], | 
			
		||||
 | 
				                    realTime: [ | 
			
		||||
 | 
				                        { required: true, message: '请选择反馈时间', trigger: 'change' } | 
			
		||||
 | 
				                    ], | 
			
		||||
 | 
				                    fillBy: [ | 
			
		||||
 | 
				                        { required: true, message: '请输入填报人', trigger: 'blur' } | 
			
		||||
 | 
				                    ] | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				            }; | 
			
		||||
 | 
				        }, | 
			
		||||
 | 
				        computed: { | 
			
		||||
 | 
				            showTitle() { | 
			
		||||
 | 
				                return this.editType=='edit' ? "编辑" + this.title : "新增" + this.title; | 
			
		||||
 | 
				            }, | 
			
		||||
 | 
				        }, | 
			
		||||
 | 
				        methods: { | 
			
		||||
 | 
				            reset() { | 
			
		||||
 | 
				                this.editType='add' | 
			
		||||
 | 
				                // this.$refs.elForm.resetFields(); | 
			
		||||
 | 
				                this.loading=false; | 
			
		||||
 | 
				                this.form = this.$options.data().form; | 
			
		||||
 | 
				            }, | 
			
		||||
 | 
				            show(form) { | 
			
		||||
 | 
				                this.reset(); | 
			
		||||
 | 
				                if (form) { | 
			
		||||
 | 
				                    this.editType='edit' | 
			
		||||
 | 
				                    this.form = { ...this.$options.data().form, ...form }; | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				                this.dialogVisible = true; | 
			
		||||
 | 
				            }, | 
			
		||||
 | 
				            onSubmit() { | 
			
		||||
 | 
				                this.$refs.editForm.validate((valid) => { | 
			
		||||
 | 
				                    if (!valid) { | 
			
		||||
 | 
				                        return false; | 
			
		||||
 | 
				                    } | 
			
		||||
 | 
				                    this.loading = true; | 
			
		||||
 | 
				                    let q; | 
			
		||||
 | 
				                    if (this.editType=='edit') { | 
			
		||||
 | 
				                        q = this.$axios.put( this.url.edit, this.form); | 
			
		||||
 | 
				                    } else { | 
			
		||||
 | 
				                        q = this.$axios.post(this.url.add, this.form); | 
			
		||||
 | 
				                    } | 
			
		||||
 | 
				                    q.then(({ message }) => { | 
			
		||||
 | 
				                        this.$message({ type: "info", message: message }); | 
			
		||||
 | 
				                        this.dialogVisible = false; | 
			
		||||
 | 
				                        this.$emit("refresh"); | 
			
		||||
 | 
				                    }).finally(() => { | 
			
		||||
 | 
				                        this.loading = false; | 
			
		||||
 | 
				                    }); | 
			
		||||
 | 
				                }); | 
			
		||||
 | 
				            }, | 
			
		||||
 | 
				        }, | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style lang="scss" scoped> | 
			
		||||
 | 
				.custom-dialog { | 
			
		||||
 | 
				    ::v-deep .el-dialog { | 
			
		||||
 | 
				        background-color: rgba(4, 0, 79, 0.98); | 
			
		||||
 | 
				        border: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				        border-radius: 4px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .el-dialog__header { | 
			
		||||
 | 
				            background-color: rgba(0, 8, 59, 0.9); | 
			
		||||
 | 
				            padding: 15px 20px; | 
			
		||||
 | 
				            border-bottom: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            .el-dialog__title { | 
			
		||||
 | 
				                color: #e0e0ff; | 
			
		||||
 | 
				                font-weight: bold; | 
			
		||||
 | 
				                font-size: 16px; | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            .el-dialog__headerbtn .el-dialog__close { | 
			
		||||
 | 
				                color: #e0e0ff; | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .el-dialog__body { | 
			
		||||
 | 
				            padding: 20px; | 
			
		||||
 | 
				            color: #e0e0ff; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .el-dialog__footer { | 
			
		||||
 | 
				            padding: 10px 20px; | 
			
		||||
 | 
				            border-top: 1px solid rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				            background-color: rgba(0, 8, 59, 0.7); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .el-form-item { | 
			
		||||
 | 
				        margin-bottom: 15px; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        ::v-deep .el-form-item__label { | 
			
		||||
 | 
				            color: #c0c4cc; | 
			
		||||
 | 
				            font-size: 13px; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        ::v-deep .el-input__inner { | 
			
		||||
 | 
				            background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				            border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				            color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            &::placeholder { | 
			
		||||
 | 
				                color: rgba(195, 195, 219, 0.5); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        ::v-deep .el-textarea__inner { | 
			
		||||
 | 
				            background-color: rgba(25, 22, 104, 0.7); | 
			
		||||
 | 
				            border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				            color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            &::placeholder { | 
			
		||||
 | 
				                color: rgba(195, 195, 219, 0.5); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        ::v-deep .el-select .el-input .el-select__caret { | 
			
		||||
 | 
				            color: #e0e0ff; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    .dialog-footer { | 
			
		||||
 | 
				        text-align: right; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        .el-button { | 
			
		||||
 | 
				            background-color: rgba(30, 27, 110, 0.7); | 
			
		||||
 | 
				            border-color: rgba(75, 72, 178, 0.5); | 
			
		||||
 | 
				            color: #e0e0ff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            &:hover { | 
			
		||||
 | 
				                background-color: rgba(40, 36, 124, 0.8); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            &[type="primary"] { | 
			
		||||
 | 
				                background-color: #1976d2; | 
			
		||||
 | 
				                border-color: #1565c0; | 
			
		||||
 | 
				                color: #ffffff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				                &:hover { | 
			
		||||
 | 
				                    background-color: #1e88e5; | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,267 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <div class="diagram"> | 
			
		||||
 | 
				    <diagram-toolbar | 
			
		||||
 | 
				      v-if="lf" | 
			
		||||
 | 
				      class="diagram-toolbar" | 
			
		||||
 | 
				      :lf="lf" | 
			
		||||
 | 
				      :active-edges="activeEdges" | 
			
		||||
 | 
				      @changeNodeFillColor="$_changeNodeFill" | 
			
		||||
 | 
				      @saveGraph="$_saveGraph" | 
			
		||||
 | 
				      @importData="importData" | 
			
		||||
 | 
				    /> | 
			
		||||
 | 
				    <div class="diagram-main"> | 
			
		||||
 | 
				      <diagram-sidebar class="diagram-sidebar" @dragInNode="$_dragInNode" @exportXML="$_saveGraph" /> | 
			
		||||
 | 
				      <div ref="container" class="diagram-container"> | 
			
		||||
 | 
				        <div class="diagram-wrapper"> | 
			
		||||
 | 
				          <div ref="diagram" class="lf-diagram"></div> | 
			
		||||
 | 
				        </div> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				    <!-- 右侧属性面板 --> | 
			
		||||
 | 
				    <PropertyPanel | 
			
		||||
 | 
				      v-show="activeNodes.length > 0 || activeEdges.length > 0" | 
			
		||||
 | 
				      class="diagram-panel" | 
			
		||||
 | 
				      :only-edge="activeNodes.length === 0" | 
			
		||||
 | 
				      :elements-style="properties" | 
			
		||||
 | 
				      @setStyle="$_setStyle" | 
			
		||||
 | 
				      @setZIndex="$_setZIndex" | 
			
		||||
 | 
				    /> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				import LogicFlow from "@logicflow/core"; | 
			
		||||
 | 
				import { SelectionSelect, Menu } from "@logicflow/extension"; | 
			
		||||
 | 
				import "@logicflow/core/dist/style/index.css"; | 
			
		||||
 | 
				import "@logicflow/extension/lib/style/index.css"; | 
			
		||||
 | 
				import DiagramToolbar from "./DiagramToolbar.vue"; | 
			
		||||
 | 
				import DiagramSidebar from "./DiagramSidebar.vue"; | 
			
		||||
 | 
				import PropertyPanel from "./PropertyPanel.vue"; | 
			
		||||
 | 
				import { registerCustomElement } from "./node"; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				// import { Control } from "@logicflow/extension"; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  name: "Diagram", | 
			
		||||
 | 
				  components: { | 
			
		||||
 | 
				    DiagramToolbar, | 
			
		||||
 | 
				    DiagramSidebar, | 
			
		||||
 | 
				    PropertyPanel, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      sidebarWidth: 200, | 
			
		||||
 | 
				      diagramWidth: 0, | 
			
		||||
 | 
				      diagramHeight: 0, | 
			
		||||
 | 
				      lf: "", | 
			
		||||
 | 
				      filename: "", | 
			
		||||
 | 
				      activeNodes: [], | 
			
		||||
 | 
				      activeEdges: [], | 
			
		||||
 | 
				      properties: {}, | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  mounted() { | 
			
		||||
 | 
				    let data = ""; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    this.filename = "export.json"; | 
			
		||||
 | 
				    const d = window.sessionStorage.getItem(this.filename); | 
			
		||||
 | 
				    if (d) { | 
			
		||||
 | 
				      data = JSON.parse(d); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    this.initLogicFlow(data); | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    initLogicFlow(data) { | 
			
		||||
 | 
				      // 引入框选插件 | 
			
		||||
 | 
				      LogicFlow.use(SelectionSelect); | 
			
		||||
 | 
				      LogicFlow.use(Menu); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      const lf = new LogicFlow({ | 
			
		||||
 | 
				        container: this.$refs.diagram, | 
			
		||||
 | 
				        overlapMode: 1, | 
			
		||||
 | 
				        autoWrap: true, | 
			
		||||
 | 
				        metaKeyMultipleSelected: true, | 
			
		||||
 | 
				        keyboard: { | 
			
		||||
 | 
				          enabled: true, | 
			
		||||
 | 
				        }, | 
			
		||||
 | 
				        grid: { | 
			
		||||
 | 
				          visible: true, | 
			
		||||
 | 
				          size: 10, | 
			
		||||
 | 
				          type: "mesh", | 
			
		||||
 | 
				          config: { | 
			
		||||
 | 
				            color: "rgba(255,255,255,0.1)", | 
			
		||||
 | 
				            thickness: 1, | 
			
		||||
 | 
				          }, | 
			
		||||
 | 
				        }, | 
			
		||||
 | 
				        background: { | 
			
		||||
 | 
				          backgroundColor: "rgba(29, 32, 98, 1)", | 
			
		||||
 | 
				          //   backgroundImage: 'url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImdyaWQiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTSAwIDEwIEwgNDAgMTAgTSAxMCAwIEwgMTAgNDAgTSAwIDIwIEwgNDAgMjAgTSAyMCAwIEwgMjAgNDAgTSAwIDMwIEwgNDAgMzAgTSAzMCAwIEwgMzAgNDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2QwZDBkMCIgb3BhY2l0eT0iMC4yIiBzdHJva2Utd2lkdGg9IjEiLz48cGF0aCBkPSJNIDQwIDAgTCAwIDAgMCA0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZDBkMGQwIiBzdHJva2Utd2lkdGg9IjEiLz48L3BhdHRlcm4+PC9kZWZzPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JpZCkiLz48L3N2Zz4=")', | 
			
		||||
 | 
				          //   backgroundRepeat: 'repeat' | 
			
		||||
 | 
				        }, | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				      lf.setTheme({ | 
			
		||||
 | 
				        baseEdge: { strokeWidth: 1 }, | 
			
		||||
 | 
				        baseNode: { strokeWidth: 1 }, | 
			
		||||
 | 
				        nodeText: { overflowMode: "autoWrap", lineHeight: 1.5 }, | 
			
		||||
 | 
				        edgeText: { overflowMode: "autoWrap", lineHeight: 1.5 }, | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				      // 注册自定义元素 | 
			
		||||
 | 
				      registerCustomElement(lf); | 
			
		||||
 | 
				      lf.setDefaultEdgeType("pro-polyline"); | 
			
		||||
 | 
				      lf.render(data); | 
			
		||||
 | 
				      this.lf = lf; | 
			
		||||
 | 
				      this.lf.on("selection:selected,node:click,blank:click,edge:click", () => { | 
			
		||||
 | 
				        this.$nextTick(() => { | 
			
		||||
 | 
				          const { nodes, edges } = this.lf.getSelectElements(); | 
			
		||||
 | 
				          this.$set(this, "activeNodes", nodes); | 
			
		||||
 | 
				          this.activeNodes = nodes; | 
			
		||||
 | 
				          this.activeEdges = edges; | 
			
		||||
 | 
				          this.$_getProperty(); | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      // lf.renderRawData( ) | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    importData(text) { | 
			
		||||
 | 
				      this.lf.renderRawData(text); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    // 获取可以进行设置的属性 | 
			
		||||
 | 
				    $_getProperty() { | 
			
		||||
 | 
				      let properties = {}; | 
			
		||||
 | 
				      const { nodes, edges } = this.lf.getSelectElements(); | 
			
		||||
 | 
				      console.log("nodes", nodes); | 
			
		||||
 | 
				      nodes.forEach((node) => { | 
			
		||||
 | 
				        console.log(this.lf.getProperties(node.id)); | 
			
		||||
 | 
				        properties = { ...properties, ...node.properties }; | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				      edges.forEach((edge) => { | 
			
		||||
 | 
				        properties = { ...properties, ...edge.properties }; | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				      this.properties = properties; | 
			
		||||
 | 
				      return properties; | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_dragInNode(type) { | 
			
		||||
 | 
				      this.lf.dnd.startDrag({ | 
			
		||||
 | 
				        type, | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_changeNodeFill(color) { | 
			
		||||
 | 
				      const { nodes } = this.lf.graphModel.getSelectElements(); | 
			
		||||
 | 
				      nodes.forEach(({ id }) => { | 
			
		||||
 | 
				        this.lf.setProperties(id, { | 
			
		||||
 | 
				          fill: color, | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_setStyle(item) { | 
			
		||||
 | 
				      this.activeNodes.forEach(({ id }) => { | 
			
		||||
 | 
				        this.lf.setProperties(id, item); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				      this.activeEdges.forEach(({ id }) => { | 
			
		||||
 | 
				        this.lf.setProperties(id, item); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				      this.$_getProperty(); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_setZIndex(type) { | 
			
		||||
 | 
				      this.activeNodes.forEach(({ id }) => { | 
			
		||||
 | 
				        this.lf.setElementZIndex(id, type); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				      this.activeEdges.forEach(({ id }) => { | 
			
		||||
 | 
				        this.lf.setElementZIndex(id, type); | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_saveGraph() { | 
			
		||||
 | 
				      const data = this.lf.getGraphData(); | 
			
		||||
 | 
				      this.download(this.filename, JSON.stringify(data)); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    download(filename, text) { | 
			
		||||
 | 
				      window.sessionStorage.setItem(filename, text); | 
			
		||||
 | 
				      const element = document.createElement("a"); | 
			
		||||
 | 
				      element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text)); | 
			
		||||
 | 
				      element.setAttribute("download", filename); | 
			
		||||
 | 
				      element.style.display = "none"; | 
			
		||||
 | 
				      document.body.appendChild(element); | 
			
		||||
 | 
				      element.click(); | 
			
		||||
 | 
				      document.body.removeChild(element); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style scoped> | 
			
		||||
 | 
				.diagram { | 
			
		||||
 | 
				  width: 100%; | 
			
		||||
 | 
				  height: 100%; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.diagram * { | 
			
		||||
 | 
				  box-sizing: border-box; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.diagram-toolbar { | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  top: 0; | 
			
		||||
 | 
				  left: 200px; | 
			
		||||
 | 
				  height: 40px; | 
			
		||||
 | 
				  padding: 0 10px; | 
			
		||||
 | 
				  /* width: 310px; */ | 
			
		||||
 | 
				  display: flex; | 
			
		||||
 | 
				  align-items: center; | 
			
		||||
 | 
				  /* border-bottom: 1px solid #e5e5e5; */ | 
			
		||||
 | 
				  z-index: 10; | 
			
		||||
 | 
				  background: #fff; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.diagram-main { | 
			
		||||
 | 
				  display: flex; | 
			
		||||
 | 
				  width: 100%; | 
			
		||||
 | 
				  height: 100%; | 
			
		||||
 | 
				  overflow: hidden; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.diagram-sidebar { | 
			
		||||
 | 
				  width: 200px; | 
			
		||||
 | 
				  height: 100%; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.diagram-panel { | 
			
		||||
 | 
				  width: 300px; | 
			
		||||
 | 
				  background: #fff; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  position: absolute; | 
			
		||||
 | 
				  right: 0px; | 
			
		||||
 | 
				  top: 40px; | 
			
		||||
 | 
				  bottom: 40px; | 
			
		||||
 | 
				  overflow: auto; | 
			
		||||
 | 
				  border: 1px solid #dadce0; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.diagram-container { | 
			
		||||
 | 
				  flex: 1; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				/* 由于背景图和gird不对齐,需要css处理一下 */ | 
			
		||||
 | 
				.diagram /deep/ .lf-background { | 
			
		||||
 | 
				  left: -9px; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.diagram-wrapper { | 
			
		||||
 | 
				  box-sizing: border-box; | 
			
		||||
 | 
				  width: 100%; | 
			
		||||
 | 
				  height: 100%; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.lf-diagram { | 
			
		||||
 | 
				  box-shadow: 0px 0px 4px #838284; | 
			
		||||
 | 
				  width: 100%; | 
			
		||||
 | 
				  height: 100%; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				::-webkit-scrollbar { | 
			
		||||
 | 
				  width: 9px; | 
			
		||||
 | 
				  height: 9px; | 
			
		||||
 | 
				  background: white; | 
			
		||||
 | 
				  border-left: 1px solid #e8e8e8; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				::-webkit-scrollbar-thumb { | 
			
		||||
 | 
				  border-width: 1px; | 
			
		||||
 | 
				  border-style: solid; | 
			
		||||
 | 
				  border-color: #fff; | 
			
		||||
 | 
				  border-radius: 6px; | 
			
		||||
 | 
				  background: #c9c9c9; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				::-webkit-scrollbar-thumb:hover { | 
			
		||||
 | 
				  background: #b5b5b5; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,81 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <div class="diagram-sidebar"> | 
			
		||||
 | 
				    <div | 
			
		||||
 | 
				      class="image-node" | 
			
		||||
 | 
				      v-for="(item, index) of list" | 
			
		||||
 | 
				      :key="index" | 
			
		||||
 | 
				      @mousedown.stop.prevent="dragInNode(item.type)" | 
			
		||||
 | 
				    > | 
			
		||||
 | 
				      <img :src="item.imgUrl" alt="" srcset="" /> | 
			
		||||
 | 
				      <div> | 
			
		||||
 | 
				        {{ item.name }} | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    <div class="image-node" @mousedown.stop.prevent="dragInNode('pro-text')"> | 
			
		||||
 | 
				      <div>TEXT</div> | 
			
		||||
 | 
				      <div>文本节点</div> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    <!-- <div @click="exportXML">导出</div> --> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				// import IconCircle from './icon/Circle.vue' | 
			
		||||
 | 
				import { List } from "./node"; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				console.log("List", List); | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  name: "DiagramSidebar", | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      list: List.map((item) => { | 
			
		||||
 | 
				        return { | 
			
		||||
 | 
				          type: item.type, | 
			
		||||
 | 
				          ...item.info, | 
			
		||||
 | 
				        }; | 
			
		||||
 | 
				      }), | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    dragInNode(type) { | 
			
		||||
 | 
				      console.log("dragInNode", type); | 
			
		||||
 | 
				      this.$emit("dragInNode", type); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    exportXML() { | 
			
		||||
 | 
				      this.$emit("exportXML"); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  // components: { | 
			
		||||
 | 
				  //   // IconCircle, | 
			
		||||
 | 
				  // } | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style scoped> | 
			
		||||
 | 
				.diagram-sidebar { | 
			
		||||
 | 
				  user-select: none; | 
			
		||||
 | 
				  text-align: center; | 
			
		||||
 | 
				  overflow: auto; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.image-node { | 
			
		||||
 | 
				  display: inline-block; | 
			
		||||
 | 
				  width: 50%; | 
			
		||||
 | 
				  margin: 10px 0; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  cursor: pointer; | 
			
		||||
 | 
				  background-size: contain; | 
			
		||||
 | 
				  background-repeat: no-repeat; | 
			
		||||
 | 
				  user-select: none; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.image-node img { | 
			
		||||
 | 
				  max-width: 26px; | 
			
		||||
 | 
				  max-height: 26px; | 
			
		||||
 | 
				  user-select: none; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.image-node div { | 
			
		||||
 | 
				  font-size: 12px; | 
			
		||||
 | 
				  user-select: none; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,208 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <div> | 
			
		||||
 | 
				    <div class="toolbar-item" :class="{ 'selection-active': selectionOpened }" @click="$_selectionSelect()"> | 
			
		||||
 | 
				      <area-select size="18" /> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				    <!-- <div class="toolbar-item toolbar-color-picker"> | 
			
		||||
 | 
				      <el-popover | 
			
		||||
 | 
				        placement="top-start" | 
			
		||||
 | 
				        title="填充样式" | 
			
		||||
 | 
				        width="220" | 
			
		||||
 | 
				        trigger="click" | 
			
		||||
 | 
				      > | 
			
		||||
 | 
				        <sketch-picker :value="fillColor"  @input="$_changeFillColor"/> | 
			
		||||
 | 
				        <color-fill size="24" slot="reference" /> | 
			
		||||
 | 
				      </el-popover> | 
			
		||||
 | 
				    </div> --> | 
			
		||||
 | 
				    <!-- <div class="toolbar-item"> | 
			
		||||
 | 
				      <color-text size="20" /> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				    <div class="toolbar-item"> | 
			
		||||
 | 
				      <icon-font size="18" /> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				    <div class="toolbar-item"> | 
			
		||||
 | 
				      <icon-blod size="18" /> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				    <div class="toolbar-item"> | 
			
		||||
 | 
				      <icon-line size="18" /> | 
			
		||||
 | 
				    </div> --> | 
			
		||||
 | 
				    <div class="toolbar-item" @click="$_zoomIn()"> | 
			
		||||
 | 
				      <zoom-in size="18" /> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				    <div class="toolbar-item" @click="$_zoomOut()"> | 
			
		||||
 | 
				      <zoom-out size="18" /> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				    <div class="toolbar-item" :class="{ disabled: !undoAble }" @click="$_undo()"> | 
			
		||||
 | 
				      <step-back size="18" /> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				    <div class="toolbar-item" :class="{ disabled: !redoAble }" @click="$_redo()"> | 
			
		||||
 | 
				      <step-foward size="18" /> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				    <div class="toolbar-item" @click="$import">导入</div> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    <div class="toolbar-item" @click="$_saveGraph">导出</div> | 
			
		||||
 | 
				    <div> | 
			
		||||
 | 
				      <el-select v-model="linetype" size="mini" @change="$_changeLineType"> | 
			
		||||
 | 
				        <el-option v-for="item in lineOptions" :key="item.value" :value="item.value" :label="item.label"></el-option> | 
			
		||||
 | 
				      </el-select> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				// import { Sketch } from 'vue-color' | 
			
		||||
 | 
				// import ColorFill from './icon/ColorFill.vue' | 
			
		||||
 | 
				// import ColorText from './icon/ColorText.vue' | 
			
		||||
 | 
				// import IconFont from './icon/Font.vue' | 
			
		||||
 | 
				// import IconBlod from './icon/Blod.vue' | 
			
		||||
 | 
				// import IconLine from './icon/Line.vue' | 
			
		||||
 | 
				import ZoomIn from "./icon/ZoomIn.vue"; | 
			
		||||
 | 
				import ZoomOut from "./icon/ZoomOut.vue"; | 
			
		||||
 | 
				import StepBack from "./icon/StepBack.vue"; | 
			
		||||
 | 
				import StepFoward from "./icon/StepFoward.vue"; | 
			
		||||
 | 
				import AreaSelect from "./icon/AreaSelect.vue"; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				let fileHandle; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				async function getFile() { | 
			
		||||
 | 
				  [fileHandle] = await window.showOpenFilePicker(); | 
			
		||||
 | 
				  console.log("fileHandle", fileHandle); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				async function getText() { | 
			
		||||
 | 
				  const file = await fileHandle.getFile(); | 
			
		||||
 | 
				  const text = await file.text(); | 
			
		||||
 | 
				  console.log(text); | 
			
		||||
 | 
				  return text; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				async function writeFile() { | 
			
		||||
 | 
				  const writable = await fileHandle.createWritable(); | 
			
		||||
 | 
				  await writable.write("测试一下"); | 
			
		||||
 | 
				  await writable.close(); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    lf: Object, | 
			
		||||
 | 
				    activeEdges: Array, | 
			
		||||
 | 
				    fillColor: { | 
			
		||||
 | 
				      type: String, | 
			
		||||
 | 
				      default: "", | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      selectionOpened: false, | 
			
		||||
 | 
				      undoAble: false, | 
			
		||||
 | 
				      redoAble: false, | 
			
		||||
 | 
				      colors: "#345678", | 
			
		||||
 | 
				      linetype: "pro-polyline", | 
			
		||||
 | 
				      lineOptions: [ | 
			
		||||
 | 
				        { | 
			
		||||
 | 
				          value: "pro-polyline", | 
			
		||||
 | 
				          label: "折线", | 
			
		||||
 | 
				        }, | 
			
		||||
 | 
				        { | 
			
		||||
 | 
				          value: "pro-line", | 
			
		||||
 | 
				          label: "直线", | 
			
		||||
 | 
				        }, | 
			
		||||
 | 
				        { | 
			
		||||
 | 
				          value: "pro-bezier", | 
			
		||||
 | 
				          label: "曲线", | 
			
		||||
 | 
				        }, | 
			
		||||
 | 
				      ], | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  mounted() { | 
			
		||||
 | 
				    this.$props.lf.on("history:change", ({ data: { undoAble, redoAble } }) => { | 
			
		||||
 | 
				      this.$data.redoAble = redoAble; | 
			
		||||
 | 
				      this.$data.undoAble = undoAble; | 
			
		||||
 | 
				    }); | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    async $import() { | 
			
		||||
 | 
				      try { | 
			
		||||
 | 
				        await getFile(); | 
			
		||||
 | 
				        let text = await getText(); | 
			
		||||
 | 
				        if(JSON.parse(text)){ | 
			
		||||
 | 
				          this.$emit("importData",JSON.parse(text)); | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				      } catch (error) { | 
			
		||||
 | 
				        this.$message.error("文件读取错误"); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_changeFillColor(val) { | 
			
		||||
 | 
				      this.$emit("changeNodeFillColor", val.hex); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_saveGraph() { | 
			
		||||
 | 
				      this.$emit("saveGraph"); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_zoomIn() { | 
			
		||||
 | 
				      this.$props.lf.zoom(true); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_zoomOut() { | 
			
		||||
 | 
				      this.$props.lf.zoom(false); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_undo() { | 
			
		||||
 | 
				      if (this.$data.undoAble) { | 
			
		||||
 | 
				        this.$props.lf.undo(); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_redo() { | 
			
		||||
 | 
				      if (this.$data.redoAble) { | 
			
		||||
 | 
				        this.$props.lf.redo(); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_selectionSelect() { | 
			
		||||
 | 
				      this.selectionOpened = !this.selectionOpened; | 
			
		||||
 | 
				      if (this.selectionOpened) { | 
			
		||||
 | 
				        this.lf.extension.selectionSelect.openSelectionSelect(); | 
			
		||||
 | 
				      } else { | 
			
		||||
 | 
				        this.lf.extension.selectionSelect.closeSelectionSelect(); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_changeLineType(value) { | 
			
		||||
 | 
				      const { lf, activeEdges } = this.$props; | 
			
		||||
 | 
				      const { graphModel } = lf; | 
			
		||||
 | 
				      lf.setDefaultEdgeType(value); | 
			
		||||
 | 
				      if (activeEdges && activeEdges.length > 0) { | 
			
		||||
 | 
				        activeEdges.forEach((edge) => { | 
			
		||||
 | 
				          graphModel.changeEdgeType(edge.id, value); | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  components: { | 
			
		||||
 | 
				    // ColorFill, | 
			
		||||
 | 
				    // ColorText, | 
			
		||||
 | 
				    // IconFont, | 
			
		||||
 | 
				    // IconBlod, | 
			
		||||
 | 
				    // IconLine, | 
			
		||||
 | 
				    ZoomIn, | 
			
		||||
 | 
				    ZoomOut, | 
			
		||||
 | 
				    StepBack, | 
			
		||||
 | 
				    StepFoward, | 
			
		||||
 | 
				    AreaSelect, | 
			
		||||
 | 
				    // SketchPicker: Sketch | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style scoped> | 
			
		||||
 | 
				.toolbar-item { | 
			
		||||
 | 
				  /* width: 18px; | 
			
		||||
 | 
				  height: 18px; */ | 
			
		||||
 | 
				  float: left; | 
			
		||||
 | 
				  margin: 12px 6px; | 
			
		||||
 | 
				  cursor: pointer; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.toolbar-color-picker { | 
			
		||||
 | 
				  width: 24px; | 
			
		||||
 | 
				  height: 24px; | 
			
		||||
 | 
				  margin: 8px 4px; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.selection-active { | 
			
		||||
 | 
				  background: #33a3dc; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,398 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <div class="diagram-panel"> | 
			
		||||
 | 
				    <div class="setting-block"> | 
			
		||||
 | 
				      <div>快捷样式</div> | 
			
		||||
 | 
				      <div class="short-styles"> | 
			
		||||
 | 
				        <div | 
			
		||||
 | 
				          v-for="(item, index) in shortStyles" | 
			
		||||
 | 
				          :key="index" | 
			
		||||
 | 
				          :style="{ | 
			
		||||
 | 
				            backgroundColor: item.backgroundColor, | 
			
		||||
 | 
				            borderColor: item.borderColor, | 
			
		||||
 | 
				            borderWidth: item.borderWidth, | 
			
		||||
 | 
				          }" | 
			
		||||
 | 
				          @click="setStyle(item)" | 
			
		||||
 | 
				        ></div> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				    <div class="setting-block"> | 
			
		||||
 | 
				      <div class="setting-item"> | 
			
		||||
 | 
				        <span>背景色</span> | 
			
		||||
 | 
				        <el-popover | 
			
		||||
 | 
				          placement="top-start" | 
			
		||||
 | 
				          title="填充样式" | 
			
		||||
 | 
				          width="220" | 
			
		||||
 | 
				          trigger="click" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <sketch-picker | 
			
		||||
 | 
				            :value="style.backgroundColor" | 
			
		||||
 | 
				            @input="(c) => $_changeColorProperty(c, 'backgroundColor')" | 
			
		||||
 | 
				          /> | 
			
		||||
 | 
				          <div | 
			
		||||
 | 
				            class="border-color" | 
			
		||||
 | 
				            :style="{ backgroundColor: style.backgroundColor }" | 
			
		||||
 | 
				            slot="reference" | 
			
		||||
 | 
				          ></div> | 
			
		||||
 | 
				        </el-popover> | 
			
		||||
 | 
				        <span>背景渐变色</span> | 
			
		||||
 | 
				        <el-popover | 
			
		||||
 | 
				          placement="top-start" | 
			
		||||
 | 
				          title="填充样式" | 
			
		||||
 | 
				          width="220" | 
			
		||||
 | 
				          trigger="click" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <sketch-picker | 
			
		||||
 | 
				            :value="style.gradientColor" | 
			
		||||
 | 
				            @input="(c) => $_changeColorProperty(c, 'gradientColor')" | 
			
		||||
 | 
				          /> | 
			
		||||
 | 
				          <div | 
			
		||||
 | 
				            class="border-color" | 
			
		||||
 | 
				            :style="{ backgroundColor: style.gradientColor }" | 
			
		||||
 | 
				            slot="reference" | 
			
		||||
 | 
				          ></div> | 
			
		||||
 | 
				        </el-popover> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				      <div class="setting-item"> | 
			
		||||
 | 
				        <span>线条样式</span> | 
			
		||||
 | 
				        <el-select | 
			
		||||
 | 
				          v-model="style.borderStyle" | 
			
		||||
 | 
				          size="small" | 
			
		||||
 | 
				          @change="$_selectBorder" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <el-option value="hidden" label="不显示"></el-option> | 
			
		||||
 | 
				          <el-option | 
			
		||||
 | 
				            v-for="(border, index) in borderStyles" | 
			
		||||
 | 
				            :value="border.value" | 
			
		||||
 | 
				            :key="index" | 
			
		||||
 | 
				          > | 
			
		||||
 | 
				            <div | 
			
		||||
 | 
				              class="border-style" | 
			
		||||
 | 
				              :style="{ borderBottomStyle: border.value }" | 
			
		||||
 | 
				            ></div> | 
			
		||||
 | 
				          </el-option> | 
			
		||||
 | 
				        </el-select> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				      <div class="setting-item"> | 
			
		||||
 | 
				        <span>线条颜色</span> | 
			
		||||
 | 
				        <el-popover | 
			
		||||
 | 
				          placement="top-start" | 
			
		||||
 | 
				          title="填充样式" | 
			
		||||
 | 
				          width="220" | 
			
		||||
 | 
				          trigger="click" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <sketch-picker | 
			
		||||
 | 
				            :value="style.borderColor" | 
			
		||||
 | 
				            @input="(c) => $_changeColorProperty(c, 'borderColor')" | 
			
		||||
 | 
				          /> | 
			
		||||
 | 
				          <div | 
			
		||||
 | 
				            class="border-color" | 
			
		||||
 | 
				            :style="{ backgroundColor: style.borderColor }" | 
			
		||||
 | 
				            slot="reference" | 
			
		||||
 | 
				          ></div> | 
			
		||||
 | 
				        </el-popover> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				      <div class="setting-item"> | 
			
		||||
 | 
				        <span>线条宽度</span> | 
			
		||||
 | 
				        <el-select v-model="style.borderWidth" @change="$_changeBorderWidth"> | 
			
		||||
 | 
				          <el-option | 
			
		||||
 | 
				            v-for="item in borderWidthOptions" | 
			
		||||
 | 
				            :key="item" | 
			
		||||
 | 
				            :label="`${item}px`" | 
			
		||||
 | 
				            :value="item" | 
			
		||||
 | 
				          ></el-option> | 
			
		||||
 | 
				        </el-select> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				      <div class="setting-item"> | 
			
		||||
 | 
				        <span>文本颜色</span> | 
			
		||||
 | 
				        <el-popover | 
			
		||||
 | 
				          placement="top-start" | 
			
		||||
 | 
				          title="填充样式" | 
			
		||||
 | 
				          width="220" | 
			
		||||
 | 
				          trigger="click" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <sketch-picker | 
			
		||||
 | 
				            :value="style.fontColor" | 
			
		||||
 | 
				            @input="(c) => $_changeColorProperty(c, 'fontColor')" | 
			
		||||
 | 
				          /> | 
			
		||||
 | 
				          <div | 
			
		||||
 | 
				            class="border-color" | 
			
		||||
 | 
				            :style="{ backgroundColor: style.fontColor }" | 
			
		||||
 | 
				            slot="reference" | 
			
		||||
 | 
				          ></div> | 
			
		||||
 | 
				        </el-popover> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				      <div class="setting-item"> | 
			
		||||
 | 
				        <span>文本大小</span> | 
			
		||||
 | 
				        <el-input-number | 
			
		||||
 | 
				          v-model="style.fontSize" | 
			
		||||
 | 
				          controls-position="right" | 
			
		||||
 | 
				          size="mini" | 
			
		||||
 | 
				          @change="$_changeFontSize" | 
			
		||||
 | 
				          :min="12" | 
			
		||||
 | 
				          :max="30" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				        </el-input-number> | 
			
		||||
 | 
				        <span>px</span> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				      <div class="setting-item"> | 
			
		||||
 | 
				        <span>文本字体</span> | 
			
		||||
 | 
				        <el-select | 
			
		||||
 | 
				          v-model="style.fontFamily" | 
			
		||||
 | 
				          size="small" | 
			
		||||
 | 
				          @change="$_changeFontFamily" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <el-option | 
			
		||||
 | 
				            v-for="(fontFamily, index) in fontFamilies" | 
			
		||||
 | 
				            :value="fontFamily.value" | 
			
		||||
 | 
				            :key="index" | 
			
		||||
 | 
				          ></el-option> | 
			
		||||
 | 
				        </el-select> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				      <div class="setting-item"> | 
			
		||||
 | 
				        <span>行高</span> | 
			
		||||
 | 
				        <el-select | 
			
		||||
 | 
				          v-model="style.lineHeight" | 
			
		||||
 | 
				          size="small" | 
			
		||||
 | 
				          @change="$_changeLineHeight" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <el-option | 
			
		||||
 | 
				            v-for="(item, index) in lineHeightOptions" | 
			
		||||
 | 
				            :key="index" | 
			
		||||
 | 
				            :label="`${item}`" | 
			
		||||
 | 
				            :value="item" | 
			
		||||
 | 
				          ></el-option> | 
			
		||||
 | 
				        </el-select> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				      <div class="setting-item"> | 
			
		||||
 | 
				        <span>对齐</span> | 
			
		||||
 | 
				        <el-radio-group | 
			
		||||
 | 
				          v-model="style.textAlign" | 
			
		||||
 | 
				          size="small" | 
			
		||||
 | 
				          @change="$_changeTextAlign" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				          <el-radio-button label="left">左对齐</el-radio-button> | 
			
		||||
 | 
				          <el-radio-button label="center">居中</el-radio-button> | 
			
		||||
 | 
				          <el-radio-button label="right">右对齐</el-radio-button> | 
			
		||||
 | 
				        </el-radio-group> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				      <div class="setting-item"> | 
			
		||||
 | 
				        <span>文本样式</span> | 
			
		||||
 | 
				        <el-button size="small" @click="$_changeFontWeight">B</el-button> | 
			
		||||
 | 
				        <el-button size="small" @click="$_changeTextDecoration">U</el-button> | 
			
		||||
 | 
				        <el-button size="small" @click="$_changeFontStyle">I</el-button> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				      <div class="setting-item"> | 
			
		||||
 | 
				        <span>设备id</span> | 
			
		||||
 | 
				        <el-input | 
			
		||||
 | 
				          v-model="style.deviceID" | 
			
		||||
 | 
				          controls-position="right" | 
			
		||||
 | 
				          size="mini" | 
			
		||||
 | 
				          @input="$_changeDeviceID" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				        </el-input> | 
			
		||||
 | 
				        <span>监控项id</span> | 
			
		||||
 | 
				        <el-input | 
			
		||||
 | 
				          v-model="style.itemID" | 
			
		||||
 | 
				          controls-position="right" | 
			
		||||
 | 
				          size="mini" | 
			
		||||
 | 
				          @input="$_changeItemID" | 
			
		||||
 | 
				        > | 
			
		||||
 | 
				        </el-input> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <div> | 
			
		||||
 | 
				        <el-button @click="$emit('setZIndex', 'top')">置为顶部</el-button> | 
			
		||||
 | 
				        <el-button @click="$emit('setZIndex', 'bottom')">置为底部</el-button> | 
			
		||||
 | 
				      </div> | 
			
		||||
 | 
				    </div> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				import { Sketch } from "vue-color"; | 
			
		||||
 | 
				import { shortStyles, borderStyles, fontFamilies } from "./constant"; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    elementsStyle: Object, | 
			
		||||
 | 
				    onlyEdge: Boolean, // 是否是只设置边的属性,当只设置边的属性时,隐藏快捷样式和背景色设置 | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  data() { | 
			
		||||
 | 
				    return { | 
			
		||||
 | 
				      shortStyles, | 
			
		||||
 | 
				      borderStyles, | 
			
		||||
 | 
				      fontFamilies, | 
			
		||||
 | 
				      style: { | 
			
		||||
 | 
				        backgroundColor: "", // 填充色 | 
			
		||||
 | 
				        gradientColor: "", // 渐变色 | 
			
		||||
 | 
				        borderType: 0, // 线条类型 | 
			
		||||
 | 
				        borderColor: "", // 填充颜色 | 
			
		||||
 | 
				        borderWidth: 1, // 线条宽度 | 
			
		||||
 | 
				        borderStyle: "", // 线条类型 | 
			
		||||
 | 
				        fontSize: 12, // 文本大小 | 
			
		||||
 | 
				        fontColor: "", // 文本颜色 | 
			
		||||
 | 
				        fontWeight: "", // 文本加粗 | 
			
		||||
 | 
				        fontFamily: "", // 文本样式 | 
			
		||||
 | 
				        lineHeight: "", // 行高 | 
			
		||||
 | 
				        textAlign: "", // 对齐 | 
			
		||||
 | 
				        deviceID:"" // 设备id | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      borderWidthOptions: Array(11) | 
			
		||||
 | 
				        .fill() | 
			
		||||
 | 
				        .map((_, i) => i), | 
			
		||||
 | 
				      SketchPicker: Sketch, | 
			
		||||
 | 
				      fontWeight: "", // 文本加粗 | 
			
		||||
 | 
				      lineHeightOptions: Array(5) | 
			
		||||
 | 
				        .fill(1) | 
			
		||||
 | 
				        .map((_, i) => _ + i * 0.5), | 
			
		||||
 | 
				    }; | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  watch: { | 
			
		||||
 | 
				    elementsStyle: { | 
			
		||||
 | 
				      handler(val) { | 
			
		||||
 | 
				          this.style = { ...this.$options.data().style, ...val }; | 
			
		||||
 | 
				      }, | 
			
		||||
 | 
				      immediate: true, | 
			
		||||
 | 
				      deep: true, | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  methods: { | 
			
		||||
 | 
				    setStyle(item) { | 
			
		||||
 | 
				      this.$emit("setStyle", item); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_selectBorder(val) { | 
			
		||||
 | 
				      this.$emit("setStyle", { | 
			
		||||
 | 
				        borderStyle: val, | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_changeColorProperty({ rgba: { r, g, b, a } }, type) { | 
			
		||||
 | 
				      const color = `rgba(${r},${g},${b},${a})`; | 
			
		||||
 | 
				      this[type] = color; | 
			
		||||
 | 
				      this.$emit("setStyle", { | 
			
		||||
 | 
				        [type]: color, | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_changeFontSize(val) { | 
			
		||||
 | 
				      this.$emit("setStyle", { | 
			
		||||
 | 
				        fontSize: val, | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_changeBorderWidth(val) { | 
			
		||||
 | 
				      this.$emit("setStyle", { | 
			
		||||
 | 
				        borderWidth: val, | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_changeFontFamily(val) { | 
			
		||||
 | 
				      this.$emit("setStyle", { | 
			
		||||
 | 
				        fontFamily: val, | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_changeLineHeight(val) { | 
			
		||||
 | 
				      this.$emit("setStyle", { | 
			
		||||
 | 
				        lineHeight: val, | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_changeFontWeight() { | 
			
		||||
 | 
				      if (this.style.fontWeight === "bold") { | 
			
		||||
 | 
				        this.$emit("setStyle", { | 
			
		||||
 | 
				          fontWeight: "normal", | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      } else { | 
			
		||||
 | 
				        this.$emit("setStyle", { | 
			
		||||
 | 
				          fontWeight: "bold", | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_changeTextDecoration() { | 
			
		||||
 | 
				      if (this.style.textDecoration === "underline") { | 
			
		||||
 | 
				        this.$emit("setStyle", { | 
			
		||||
 | 
				          textDecoration: "none", | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      } else { | 
			
		||||
 | 
				        this.$emit("setStyle", { | 
			
		||||
 | 
				          textDecoration: "underline", | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_changeDeviceID(val){ | 
			
		||||
 | 
				      this.$emit("setStyle", { | 
			
		||||
 | 
				          deviceID: val, | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_changeItemID(val){ | 
			
		||||
 | 
				      this.$emit("setStyle", { | 
			
		||||
 | 
				          itemID: val, | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_changeFontStyle() { | 
			
		||||
 | 
				      if (this.style.fontStyle === "italic") { | 
			
		||||
 | 
				        this.$emit("setStyle", { | 
			
		||||
 | 
				          fontStyle: "normal", | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      } else { | 
			
		||||
 | 
				        this.$emit("setStyle", { | 
			
		||||
 | 
				          fontStyle: "italic", | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				      } | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				    $_changeTextAlign(val) { | 
			
		||||
 | 
				      this.$emit("setStyle", { | 
			
		||||
 | 
				        textAlign: val, | 
			
		||||
 | 
				      }); | 
			
		||||
 | 
				    }, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				  components: { | 
			
		||||
 | 
				    SketchPicker: Sketch, | 
			
		||||
 | 
				  }, | 
			
		||||
 | 
				}; | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<style scoped> | 
			
		||||
 | 
				.diagram-panel { | 
			
		||||
 | 
				  padding: 20px; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.short-styles { | 
			
		||||
 | 
				  width: 240px; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.short-styles > div { | 
			
		||||
 | 
				  width: 20px; | 
			
		||||
 | 
				  height: 20px; | 
			
		||||
 | 
				  margin: 0 10px 5px 0; | 
			
		||||
 | 
				  box-sizing: border-box; | 
			
		||||
 | 
				  float: left; | 
			
		||||
 | 
				  border: 1px solid #fff; | 
			
		||||
 | 
				  cursor: pointer; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.border-style { | 
			
		||||
 | 
				  width: 150px; | 
			
		||||
 | 
				  height: 0px; | 
			
		||||
 | 
				  margin-top: 18px; | 
			
		||||
 | 
				  border-bottom-width: 1px; | 
			
		||||
 | 
				  border-bottom-color: black; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.setting-block { | 
			
		||||
 | 
				  overflow: hidden; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.setting-item { | 
			
		||||
 | 
				  line-height: 12px; | 
			
		||||
 | 
				  font-size: 12px; | 
			
		||||
 | 
				  display: flex; | 
			
		||||
 | 
				  vertical-align: middle; | 
			
		||||
 | 
				  align-items: center; | 
			
		||||
 | 
				  margin-top: 10px; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.setting-item > span { | 
			
		||||
 | 
				  width: 50px; | 
			
		||||
 | 
				  margin-right: 10px; | 
			
		||||
 | 
				  text-align: right; | 
			
		||||
 | 
				  flex-shrink: 0; | 
			
		||||
 | 
				  flex-grow: 0; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.border-color { | 
			
		||||
 | 
				  width: 40px; | 
			
		||||
 | 
				  height: 30px; | 
			
		||||
 | 
				  display: inline-block; | 
			
		||||
 | 
				  border: 1px solid #eaeaeb; | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
@ -0,0 +1,12 @@ | 
			
		|||||
 | 
				// 元素属性右侧面板默认属性
 | 
			
		||||
 | 
				export const defatuleStyle = { | 
			
		||||
 | 
				  backgroundColor: '', // 填充色
 | 
			
		||||
 | 
				  gradientColor: '', // 渐变色
 | 
			
		||||
 | 
				  borderType: 0, // 边框类型
 | 
			
		||||
 | 
				  borderColor: '', // 填充颜色
 | 
			
		||||
 | 
				  borderWidth: 1, // 边框宽度
 | 
			
		||||
 | 
				  borderStyle: '', // 边框类型
 | 
			
		||||
 | 
				  fontSize: 12, // 文本大小
 | 
			
		||||
 | 
				  fontColor: '', // 文本颜色
 | 
			
		||||
 | 
				  fontWeight: '' // 文本加粗
 | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,38 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <svg> | 
			
		||||
 | 
				    <g transform="translate(0.5,0.5)" style="visibility: visible"> | 
			
		||||
 | 
				      <ellipse | 
			
		||||
 | 
				        cx="15.75" | 
			
		||||
 | 
				        cy="4.73" | 
			
		||||
 | 
				        rx="3.375" | 
			
		||||
 | 
				        ry="3.375" | 
			
		||||
 | 
				        fill="#ffffff" | 
			
		||||
 | 
				        stroke="#000000" | 
			
		||||
 | 
				        stroke-width="1.3" | 
			
		||||
 | 
				        pointer-events="all" | 
			
		||||
 | 
				      ></ellipse> | 
			
		||||
 | 
				      <path | 
			
		||||
 | 
				        d="M 15.75 8.1 L 15.75 19.35 M 15.75 10.35 L 9 10.35 M 15.75 10.35 L 22.5 10.35 M 15.75 19.35 L 9 28.35 M 15.75 19.35 L 22.5 28.35" | 
			
		||||
 | 
				        fill="none" | 
			
		||||
 | 
				        stroke="white" | 
			
		||||
 | 
				        stroke-width="9.3" | 
			
		||||
 | 
				        stroke-miterlimit="10" | 
			
		||||
 | 
				        pointer-events="stroke" | 
			
		||||
 | 
				        visibility="hidden" | 
			
		||||
 | 
				      ></path> | 
			
		||||
 | 
				      <path | 
			
		||||
 | 
				        d="M 15.75 8.1 L 15.75 19.35 M 15.75 10.35 L 9 10.35 M 15.75 10.35 L 22.5 10.35 M 15.75 19.35 L 9 28.35 M 15.75 19.35 L 22.5 28.35" | 
			
		||||
 | 
				        fill="none" | 
			
		||||
 | 
				        stroke="#000000" | 
			
		||||
 | 
				        stroke-width="1.3" | 
			
		||||
 | 
				        stroke-miterlimit="10" | 
			
		||||
 | 
				        pointer-events="all" | 
			
		||||
 | 
				      ></path> | 
			
		||||
 | 
				    </g> | 
			
		||||
 | 
				  </svg> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,16 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <svg class="icon" viewBox="0 0 1024 1024" :width="size" :height="size"> | 
			
		||||
 | 
				    <path d="M933.647059 0h-210.82353v90.352941h180.705883a30.117647 30.117647 0 0 1 30.117647 30.117647v180.705883h90.352941V90.352941a90.352941 90.352941 0 0 0-90.352941-90.352941zM361.411765 0h301.17647v90.352941H361.411765zM933.647059 361.411765h90.352941v301.17647h-90.352941zM361.411765 933.647059h301.17647v90.352941H361.411765zM0 361.411765h90.352941v301.17647H0zM90.352941 903.529412v-180.705883H0v210.82353a90.352941 90.352941 0 0 0 90.352941 90.352941h210.82353v-90.352941H120.470588a30.117647 30.117647 0 0 1-30.117647-30.117647zM933.647059 903.529412a30.117647 30.117647 0 0 1-30.117647 30.117647h-180.705883v90.352941h210.82353a90.352941 90.352941 0 0 0 90.352941-90.352941v-210.82353h-90.352941zM0 90.352941v210.82353h90.352941V120.470588a30.117647 30.117647 0 0 1 30.117647-30.117647h180.705883V0H90.352941a90.352941 90.352941 0 0 0-90.352941 90.352941z" p-id="1890"> | 
			
		||||
 | 
				    </path> | 
			
		||||
 | 
				  </svg> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    size: { | 
			
		||||
 | 
				      default: '24' | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,16 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <svg class="icon" viewBox="0 0 1024 1024" :width="size" :height="size"> | 
			
		||||
 | 
				    <path fill="currentColor" d="M810.666667 618.666667s-85.333333 93.866667-85.333334 149.333333c0 46.933333 38.4 85.333333 85.333334 85.333333s85.333333-38.4 85.333333-85.333333c0-55.466667-85.333333-149.333333-85.333333-149.333333M221.866667 554.666667L426.666667 349.866667l204.8 204.8m76.8-46.933334L324.266667 128 264.533333 187.733333l102.4 102.4-221.866666 217.6c-25.6 25.6-25.6 64 0 89.6l234.666666 234.666667c25.6 25.6 64 25.6 89.6 0l234.666667-234.666667c25.6-21.333333 29.866667-64 4.266667-89.6z" p-id="4284"> | 
			
		||||
 | 
				    </path> | 
			
		||||
 | 
				  </svg> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    size: { | 
			
		||||
 | 
				      default: '24' | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,15 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <svg class="icon" viewBox="0 0 1024 1024" :width="size" :height="size"> | 
			
		||||
 | 
				    <path d="M512 725.333333a128 128 0 1 1 0 256 128 128 0 0 1 0-256zM469.333333 85.333333L234.666667 682.666667h96l47.786666-128h266.666667l47.786667 128h96L554.666667 85.333333h-85.333334z m-58.88 384L512 199.253333 613.546667 469.333333H410.453333z" p-id="4479"></path> | 
			
		||||
 | 
				  </svg> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				  props: { | 
			
		||||
 | 
				    size: { | 
			
		||||
 | 
				      default: '24' | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				  } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,19 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				<!-- 加号 --> | 
			
		||||
 | 
				  <svg class="svg-node"> | 
			
		||||
 | 
				    <g transform="translate(0.5,0.5)" style="visibility: visible"> | 
			
		||||
 | 
				      <polygon | 
			
		||||
 | 
				        points="0,9 9,9 9,0 18,0 18,9 27,9 27,18 18,18 18,27 9,27 9,18 0,18" | 
			
		||||
 | 
				        fill="#ffffff" | 
			
		||||
 | 
				        stroke="#000000" | 
			
		||||
 | 
				        stroke-width="1.3" | 
			
		||||
 | 
				        pointer-events="all" | 
			
		||||
 | 
				      ></polygon> | 
			
		||||
 | 
				    </g> | 
			
		||||
 | 
				  </svg> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,27 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <svg> | 
			
		||||
 | 
				    <g transform="translate(0.5,0.5)" style="visibility: visible"> | 
			
		||||
 | 
				      <path | 
			
		||||
 | 
				        d="M 5.78 6.46 C 5.78 3.64 10.35 1.36 15.98 1.36 C 18.69 1.36 21.28 1.9 23.19 2.85 C 25.11 3.81 26.18 5.11 26.18 6.46 L 26.18 23.46 C 26.18 26.28 21.61 28.56 15.98 28.56 C 10.35 28.56 5.78 26.28 5.78 23.46 Z" | 
			
		||||
 | 
				        fill="#ffffff" | 
			
		||||
 | 
				        stroke="#000000" | 
			
		||||
 | 
				        stroke-width="1.3" | 
			
		||||
 | 
				        stroke-miterlimit="10" | 
			
		||||
 | 
				        pointer-events="all" | 
			
		||||
 | 
				      ></path> | 
			
		||||
 | 
				      <path | 
			
		||||
 | 
				        d="M 26.18 6.46 C 26.18 9.28 21.61 11.56 15.98 11.56 C 10.35 11.56 5.78 9.28 5.78 6.46" | 
			
		||||
 | 
				        fill="none" | 
			
		||||
 | 
				        stroke="#000000" | 
			
		||||
 | 
				        stroke-width="1.3" | 
			
		||||
 | 
				        stroke-miterlimit="10" | 
			
		||||
 | 
				        pointer-events="all" | 
			
		||||
 | 
				      ></path> | 
			
		||||
 | 
				    </g> | 
			
		||||
 | 
				  </svg> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,19 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <svg> | 
			
		||||
 | 
				    <g transform="translate(0.5,0.5)" style="visibility: visible"> | 
			
		||||
 | 
				      <path | 
			
		||||
 | 
				        d="M 15.98 1.36 L 29.58 14.96 L 15.98 28.56 L 2.38 14.96 Z" | 
			
		||||
 | 
				        fill="#ffffff" | 
			
		||||
 | 
				        stroke="#000000" | 
			
		||||
 | 
				        stroke-width="1.3" | 
			
		||||
 | 
				        stroke-miterlimit="10" | 
			
		||||
 | 
				        pointer-events="all" | 
			
		||||
 | 
				      ></path> | 
			
		||||
 | 
				    </g> | 
			
		||||
 | 
				  </svg> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,18 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <svg class="svg-node"> | 
			
		||||
 | 
				    <g transform="translate(0.5,0.5)" style="visibility: visible"> | 
			
		||||
 | 
				      <polygon | 
			
		||||
 | 
				        points="10,0 20,0 20,18 30,18 15,28 0,18 10,18" | 
			
		||||
 | 
				        fill="#ffffff" | 
			
		||||
 | 
				        stroke="#000000" | 
			
		||||
 | 
				        stroke-width="1.3" | 
			
		||||
 | 
				        pointer-events="all" | 
			
		||||
 | 
				      ></polygon> | 
			
		||||
 | 
				    </g> | 
			
		||||
 | 
				  </svg> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,21 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <svg class="svg-node"> | 
			
		||||
 | 
				    <g transform="translate(0.5,0.5)" style="visibility: visible"> | 
			
		||||
 | 
				      <ellipse | 
			
		||||
 | 
				        cx="15.84" | 
			
		||||
 | 
				        cy="14.88" | 
			
		||||
 | 
				        rx="14.399999999999999" | 
			
		||||
 | 
				        ry="9.6" | 
			
		||||
 | 
				        fill="#ffffff" | 
			
		||||
 | 
				        stroke="#000000" | 
			
		||||
 | 
				        stroke-width="1.3" | 
			
		||||
 | 
				        pointer-events="all" | 
			
		||||
 | 
				      ></ellipse> | 
			
		||||
 | 
				    </g> | 
			
		||||
 | 
				  </svg> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,19 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				<!-- 八边形 --> | 
			
		||||
 | 
				  <svg class="svg-node"> | 
			
		||||
 | 
				    <g transform="translate(0.5,0.5)" style="visibility: visible"> | 
			
		||||
 | 
				      <polygon | 
			
		||||
 | 
				        points="19.74,0 28,8.26 28,19.74 19.74,28 8.26,28 0,19.74 0,8.26 8.26,0" | 
			
		||||
 | 
				        fill="#ffffff" | 
			
		||||
 | 
				        stroke="#000000" | 
			
		||||
 | 
				        stroke-width="1.3" | 
			
		||||
 | 
				        pointer-events="all" | 
			
		||||
 | 
				      ></polygon> | 
			
		||||
 | 
				    </g> | 
			
		||||
 | 
				  </svg> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,18 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <svg class="svg-node"> | 
			
		||||
 | 
				    <g transform="translate(0.5,0.5)" style="visibility: visible"> | 
			
		||||
 | 
				      <polygon | 
			
		||||
 | 
				        points="0,13.6 9,2.2 9,11.2 18,11.2 18,2.2 27,13.6 18,27.2 18,18.2 9,18.2 9,27.2" | 
			
		||||
 | 
				        fill="#ffffff" | 
			
		||||
 | 
				        stroke="#000000" | 
			
		||||
 | 
				        stroke-width="1.3" | 
			
		||||
 | 
				        pointer-events="all" | 
			
		||||
 | 
				      ></polygon> | 
			
		||||
 | 
				    </g> | 
			
		||||
 | 
				  </svg> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||
@ -0,0 +1,18 @@ | 
			
		|||||
 | 
				<template> | 
			
		||||
 | 
				  <svg class="svg-node"> | 
			
		||||
 | 
				    <g transform="translate(0.5,0.5)" style="visibility: visible"> | 
			
		||||
 | 
				      <polygon | 
			
		||||
 | 
				        points="0,15 10,0 10,10 30,10 30,20 10,20 10,30" | 
			
		||||
 | 
				        fill="#ffffff" | 
			
		||||
 | 
				        stroke="#000000" | 
			
		||||
 | 
				        stroke-width="1.3" | 
			
		||||
 | 
				        pointer-events="all" | 
			
		||||
 | 
				      ></polygon> | 
			
		||||
 | 
				    </g> | 
			
		||||
 | 
				  </svg> | 
			
		||||
 | 
				</template> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				export default { | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</script> | 
			
		||||