test #47
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -20,3 +20,4 @@ selenium-debug.log
 | 
			
		||||
*.local
 | 
			
		||||
 | 
			
		||||
package-lock.json
 | 
			
		||||
echarts.js
 | 
			
		||||
@@ -50,6 +50,7 @@
 | 
			
		||||
    "code-brick-zj": "^1.0.2",
 | 
			
		||||
    "core-js": "^3.26.0",
 | 
			
		||||
    "crypto-js": "^4.0.0",
 | 
			
		||||
    "diagram-js": "^12.3.0",
 | 
			
		||||
    "echarts": "5.4.0",
 | 
			
		||||
    "element-ui": "2.15.12",
 | 
			
		||||
    "file-saver": "^2.0.5",
 | 
			
		||||
@@ -64,21 +65,25 @@
 | 
			
		||||
    "moment": "^2.29.4",
 | 
			
		||||
    "nprogress": "0.2.0",
 | 
			
		||||
    "qrcode.vue": "^1.7.0",
 | 
			
		||||
    "qs": "^6.11.2",
 | 
			
		||||
    "quill": "1.3.7",
 | 
			
		||||
    "screenfull": "5.0.2",
 | 
			
		||||
    "sortablejs": "1.10.2",
 | 
			
		||||
    "throttle-debounce": "2.1.0",
 | 
			
		||||
    "video.js": "^8.5.2",
 | 
			
		||||
    "vue": "2.7.14",
 | 
			
		||||
    "vue-count-to": "1.0.13",
 | 
			
		||||
    "vue-cropper": "0.5.8",
 | 
			
		||||
    "vue-meta": "^2.4.0",
 | 
			
		||||
    "vue-plugin-hiprint": "^0.0.54-fix",
 | 
			
		||||
    "vue-quill-editor": "^3.0.6",
 | 
			
		||||
    "vue-router": "3.4.9",
 | 
			
		||||
    "vue-video-player": "^5.0.2",
 | 
			
		||||
    "vuedraggable": "2.24.3",
 | 
			
		||||
    "vuex": "3.6.2",
 | 
			
		||||
    "xlsx": "^0.18.5",
 | 
			
		||||
    "xml-js": "1.6.11"
 | 
			
		||||
    "xml-js": "1.6.11",
 | 
			
		||||
    "yorkie": "^2.0.0"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@vue/cli-plugin-babel": "4.5.18",
 | 
			
		||||
@@ -92,7 +97,7 @@
 | 
			
		||||
    "chalk": "4.1.0",
 | 
			
		||||
    "compression-webpack-plugin": "5.0.2",
 | 
			
		||||
    "connect": "3.6.6",
 | 
			
		||||
    "eslint": "7.15.0",
 | 
			
		||||
    "eslint": "6.8.0",
 | 
			
		||||
    "eslint-config-airbnb-base": "^14.0.0",
 | 
			
		||||
    "eslint-plugin-import": "^2.26.0",
 | 
			
		||||
    "eslint-plugin-prettier": "^3.1.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,215 +1,218 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
	<head>
 | 
			
		||||
		<meta charset="utf-8" />
 | 
			
		||||
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
 | 
			
		||||
		<meta name="renderer" content="webkit" />
 | 
			
		||||
		<meta
 | 
			
		||||
			name="viewport"
 | 
			
		||||
			content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
 | 
			
		||||
		<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
 | 
			
		||||
		<title><%= webpackConfig.name %></title>
 | 
			
		||||
		<!--[if lt IE 11]>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
	<meta charset="utf-8" />
 | 
			
		||||
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
 | 
			
		||||
	<meta name="renderer" content="webkit" />
 | 
			
		||||
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
 | 
			
		||||
	<link rel="stylesheet" type="text/css" media="print" href="<%= BASE_URL %>print-lock.css">
 | 
			
		||||
	<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
 | 
			
		||||
	<title>
 | 
			
		||||
		<%= webpackConfig.name %>
 | 
			
		||||
	</title>
 | 
			
		||||
	<!--[if lt IE 11]>
 | 
			
		||||
			<script>
 | 
			
		||||
				window.location.href = 'html/ie.html';
 | 
			
		||||
			</script>
 | 
			
		||||
		<![endif]-->
 | 
			
		||||
		<style>
 | 
			
		||||
			html,
 | 
			
		||||
			body,
 | 
			
		||||
			#app {
 | 
			
		||||
				height: 100%;
 | 
			
		||||
				margin: 0px;
 | 
			
		||||
				padding: 0px;
 | 
			
		||||
	<style>
 | 
			
		||||
		html,
 | 
			
		||||
		body,
 | 
			
		||||
		#app {
 | 
			
		||||
			height: 100%;
 | 
			
		||||
			margin: 0px;
 | 
			
		||||
			padding: 0px;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.chromeframe {
 | 
			
		||||
			margin: 0.2em 0;
 | 
			
		||||
			background: #ccc;
 | 
			
		||||
			color: #000;
 | 
			
		||||
			padding: 0.2em 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		#loader-wrapper {
 | 
			
		||||
			position: fixed;
 | 
			
		||||
			top: 0;
 | 
			
		||||
			left: 0;
 | 
			
		||||
			width: 100%;
 | 
			
		||||
			height: 100%;
 | 
			
		||||
			z-index: 999999;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		#loader {
 | 
			
		||||
			display: block;
 | 
			
		||||
			position: relative;
 | 
			
		||||
			left: 50%;
 | 
			
		||||
			top: 50%;
 | 
			
		||||
			width: 150px;
 | 
			
		||||
			height: 150px;
 | 
			
		||||
			margin: -75px 0 0 -75px;
 | 
			
		||||
			border-radius: 50%;
 | 
			
		||||
			border: 3px solid transparent;
 | 
			
		||||
			border-top-color: #fff;
 | 
			
		||||
			-webkit-animation: spin 2s linear infinite;
 | 
			
		||||
			-ms-animation: spin 2s linear infinite;
 | 
			
		||||
			-moz-animation: spin 2s linear infinite;
 | 
			
		||||
			-o-animation: spin 2s linear infinite;
 | 
			
		||||
			animation: spin 2s linear infinite;
 | 
			
		||||
			z-index: 1001;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		#loader:before {
 | 
			
		||||
			content: '';
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: 5px;
 | 
			
		||||
			left: 5px;
 | 
			
		||||
			right: 5px;
 | 
			
		||||
			bottom: 5px;
 | 
			
		||||
			border-radius: 50%;
 | 
			
		||||
			border: 3px solid transparent;
 | 
			
		||||
			border-top-color: #fff;
 | 
			
		||||
			-webkit-animation: spin 3s linear infinite;
 | 
			
		||||
			-moz-animation: spin 3s linear infinite;
 | 
			
		||||
			-o-animation: spin 3s linear infinite;
 | 
			
		||||
			-ms-animation: spin 3s linear infinite;
 | 
			
		||||
			animation: spin 3s linear infinite;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		#loader:after {
 | 
			
		||||
			content: '';
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: 15px;
 | 
			
		||||
			left: 15px;
 | 
			
		||||
			right: 15px;
 | 
			
		||||
			bottom: 15px;
 | 
			
		||||
			border-radius: 50%;
 | 
			
		||||
			border: 3px solid transparent;
 | 
			
		||||
			border-top-color: #fff;
 | 
			
		||||
			-moz-animation: spin 1.5s linear infinite;
 | 
			
		||||
			-o-animation: spin 1.5s linear infinite;
 | 
			
		||||
			-ms-animation: spin 1.5s linear infinite;
 | 
			
		||||
			-webkit-animation: spin 1.5s linear infinite;
 | 
			
		||||
			animation: spin 1.5s linear infinite;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@-webkit-keyframes spin {
 | 
			
		||||
			0% {
 | 
			
		||||
				-webkit-transform: rotate(0deg);
 | 
			
		||||
				-ms-transform: rotate(0deg);
 | 
			
		||||
				transform: rotate(0deg);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			.chromeframe {
 | 
			
		||||
				margin: 0.2em 0;
 | 
			
		||||
				background: #ccc;
 | 
			
		||||
				color: #000;
 | 
			
		||||
				padding: 0.2em 0;
 | 
			
		||||
			100% {
 | 
			
		||||
				-webkit-transform: rotate(360deg);
 | 
			
		||||
				-ms-transform: rotate(360deg);
 | 
			
		||||
				transform: rotate(360deg);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@keyframes spin {
 | 
			
		||||
			0% {
 | 
			
		||||
				-webkit-transform: rotate(0deg);
 | 
			
		||||
				-ms-transform: rotate(0deg);
 | 
			
		||||
				transform: rotate(0deg);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			#loader-wrapper {
 | 
			
		||||
				position: fixed;
 | 
			
		||||
				top: 0;
 | 
			
		||||
				left: 0;
 | 
			
		||||
				width: 100%;
 | 
			
		||||
				height: 100%;
 | 
			
		||||
				z-index: 999999;
 | 
			
		||||
			100% {
 | 
			
		||||
				-webkit-transform: rotate(360deg);
 | 
			
		||||
				-ms-transform: rotate(360deg);
 | 
			
		||||
				transform: rotate(360deg);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			#loader {
 | 
			
		||||
				display: block;
 | 
			
		||||
				position: relative;
 | 
			
		||||
				left: 50%;
 | 
			
		||||
				top: 50%;
 | 
			
		||||
				width: 150px;
 | 
			
		||||
				height: 150px;
 | 
			
		||||
				margin: -75px 0 0 -75px;
 | 
			
		||||
				border-radius: 50%;
 | 
			
		||||
				border: 3px solid transparent;
 | 
			
		||||
				border-top-color: #fff;
 | 
			
		||||
				-webkit-animation: spin 2s linear infinite;
 | 
			
		||||
				-ms-animation: spin 2s linear infinite;
 | 
			
		||||
				-moz-animation: spin 2s linear infinite;
 | 
			
		||||
				-o-animation: spin 2s linear infinite;
 | 
			
		||||
				animation: spin 2s linear infinite;
 | 
			
		||||
				z-index: 1001;
 | 
			
		||||
			}
 | 
			
		||||
		#loader-wrapper .loader-section {
 | 
			
		||||
			position: fixed;
 | 
			
		||||
			top: 0;
 | 
			
		||||
			width: 51%;
 | 
			
		||||
			height: 100%;
 | 
			
		||||
			background: #7171c6;
 | 
			
		||||
			z-index: 1000;
 | 
			
		||||
			-webkit-transform: translateX(0);
 | 
			
		||||
			-ms-transform: translateX(0);
 | 
			
		||||
			transform: translateX(0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			#loader:before {
 | 
			
		||||
				content: '';
 | 
			
		||||
				position: absolute;
 | 
			
		||||
				top: 5px;
 | 
			
		||||
				left: 5px;
 | 
			
		||||
				right: 5px;
 | 
			
		||||
				bottom: 5px;
 | 
			
		||||
				border-radius: 50%;
 | 
			
		||||
				border: 3px solid transparent;
 | 
			
		||||
				border-top-color: #fff;
 | 
			
		||||
				-webkit-animation: spin 3s linear infinite;
 | 
			
		||||
				-moz-animation: spin 3s linear infinite;
 | 
			
		||||
				-o-animation: spin 3s linear infinite;
 | 
			
		||||
				-ms-animation: spin 3s linear infinite;
 | 
			
		||||
				animation: spin 3s linear infinite;
 | 
			
		||||
			}
 | 
			
		||||
		#loader-wrapper .loader-section.section-left {
 | 
			
		||||
			left: 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			#loader:after {
 | 
			
		||||
				content: '';
 | 
			
		||||
				position: absolute;
 | 
			
		||||
				top: 15px;
 | 
			
		||||
				left: 15px;
 | 
			
		||||
				right: 15px;
 | 
			
		||||
				bottom: 15px;
 | 
			
		||||
				border-radius: 50%;
 | 
			
		||||
				border: 3px solid transparent;
 | 
			
		||||
				border-top-color: #fff;
 | 
			
		||||
				-moz-animation: spin 1.5s linear infinite;
 | 
			
		||||
				-o-animation: spin 1.5s linear infinite;
 | 
			
		||||
				-ms-animation: spin 1.5s linear infinite;
 | 
			
		||||
				-webkit-animation: spin 1.5s linear infinite;
 | 
			
		||||
				animation: spin 1.5s linear infinite;
 | 
			
		||||
			}
 | 
			
		||||
		#loader-wrapper .loader-section.section-right {
 | 
			
		||||
			right: 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			@-webkit-keyframes spin {
 | 
			
		||||
				0% {
 | 
			
		||||
					-webkit-transform: rotate(0deg);
 | 
			
		||||
					-ms-transform: rotate(0deg);
 | 
			
		||||
					transform: rotate(0deg);
 | 
			
		||||
				}
 | 
			
		||||
		.loaded #loader-wrapper .loader-section.section-left {
 | 
			
		||||
			-webkit-transform: translateX(-100%);
 | 
			
		||||
			-ms-transform: translateX(-100%);
 | 
			
		||||
			transform: translateX(-100%);
 | 
			
		||||
			-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
 | 
			
		||||
			transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
				100% {
 | 
			
		||||
					-webkit-transform: rotate(360deg);
 | 
			
		||||
					-ms-transform: rotate(360deg);
 | 
			
		||||
					transform: rotate(360deg);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		.loaded #loader-wrapper .loader-section.section-right {
 | 
			
		||||
			-webkit-transform: translateX(100%);
 | 
			
		||||
			-ms-transform: translateX(100%);
 | 
			
		||||
			transform: translateX(100%);
 | 
			
		||||
			-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
 | 
			
		||||
			transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			@keyframes spin {
 | 
			
		||||
				0% {
 | 
			
		||||
					-webkit-transform: rotate(0deg);
 | 
			
		||||
					-ms-transform: rotate(0deg);
 | 
			
		||||
					transform: rotate(0deg);
 | 
			
		||||
				}
 | 
			
		||||
		.loaded #loader {
 | 
			
		||||
			opacity: 0;
 | 
			
		||||
			-webkit-transition: all 0.3s ease-out;
 | 
			
		||||
			transition: all 0.3s ease-out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
				100% {
 | 
			
		||||
					-webkit-transform: rotate(360deg);
 | 
			
		||||
					-ms-transform: rotate(360deg);
 | 
			
		||||
					transform: rotate(360deg);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		.loaded #loader-wrapper {
 | 
			
		||||
			visibility: hidden;
 | 
			
		||||
			-webkit-transform: translateY(-100%);
 | 
			
		||||
			-ms-transform: translateY(-100%);
 | 
			
		||||
			transform: translateY(-100%);
 | 
			
		||||
			-webkit-transition: all 0.3s 1s ease-out;
 | 
			
		||||
			transition: all 0.3s 1s ease-out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			#loader-wrapper .loader-section {
 | 
			
		||||
				position: fixed;
 | 
			
		||||
				top: 0;
 | 
			
		||||
				width: 51%;
 | 
			
		||||
				height: 100%;
 | 
			
		||||
				background: #7171c6;
 | 
			
		||||
				z-index: 1000;
 | 
			
		||||
				-webkit-transform: translateX(0);
 | 
			
		||||
				-ms-transform: translateX(0);
 | 
			
		||||
				transform: translateX(0);
 | 
			
		||||
			}
 | 
			
		||||
		.no-js #loader-wrapper {
 | 
			
		||||
			display: none;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			#loader-wrapper .loader-section.section-left {
 | 
			
		||||
				left: 0;
 | 
			
		||||
			}
 | 
			
		||||
		.no-js h1 {
 | 
			
		||||
			color: #222222;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			#loader-wrapper .loader-section.section-right {
 | 
			
		||||
				right: 0;
 | 
			
		||||
			}
 | 
			
		||||
		#loader-wrapper .load_title {
 | 
			
		||||
			font-family: 'Open Sans';
 | 
			
		||||
			color: #fff;
 | 
			
		||||
			font-size: 19px;
 | 
			
		||||
			width: 100%;
 | 
			
		||||
			text-align: center;
 | 
			
		||||
			z-index: 9999999999999;
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: 60%;
 | 
			
		||||
			opacity: 1;
 | 
			
		||||
			line-height: 30px;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			.loaded #loader-wrapper .loader-section.section-left {
 | 
			
		||||
				-webkit-transform: translateX(-100%);
 | 
			
		||||
				-ms-transform: translateX(-100%);
 | 
			
		||||
				transform: translateX(-100%);
 | 
			
		||||
				-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
 | 
			
		||||
				transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
 | 
			
		||||
			}
 | 
			
		||||
		#loader-wrapper .load_title span {
 | 
			
		||||
			font-weight: normal;
 | 
			
		||||
			font-style: italic;
 | 
			
		||||
			font-size: 13px;
 | 
			
		||||
			color: #fff;
 | 
			
		||||
			opacity: 0.5;
 | 
			
		||||
		}
 | 
			
		||||
	</style>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
			.loaded #loader-wrapper .loader-section.section-right {
 | 
			
		||||
				-webkit-transform: translateX(100%);
 | 
			
		||||
				-ms-transform: translateX(100%);
 | 
			
		||||
				transform: translateX(100%);
 | 
			
		||||
				-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
 | 
			
		||||
				transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			.loaded #loader {
 | 
			
		||||
				opacity: 0;
 | 
			
		||||
				-webkit-transition: all 0.3s ease-out;
 | 
			
		||||
				transition: all 0.3s ease-out;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			.loaded #loader-wrapper {
 | 
			
		||||
				visibility: hidden;
 | 
			
		||||
				-webkit-transform: translateY(-100%);
 | 
			
		||||
				-ms-transform: translateY(-100%);
 | 
			
		||||
				transform: translateY(-100%);
 | 
			
		||||
				-webkit-transition: all 0.3s 1s ease-out;
 | 
			
		||||
				transition: all 0.3s 1s ease-out;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			.no-js #loader-wrapper {
 | 
			
		||||
				display: none;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			.no-js h1 {
 | 
			
		||||
				color: #222222;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			#loader-wrapper .load_title {
 | 
			
		||||
				font-family: 'Open Sans';
 | 
			
		||||
				color: #fff;
 | 
			
		||||
				font-size: 19px;
 | 
			
		||||
				width: 100%;
 | 
			
		||||
				text-align: center;
 | 
			
		||||
				z-index: 9999999999999;
 | 
			
		||||
				position: absolute;
 | 
			
		||||
				top: 60%;
 | 
			
		||||
				opacity: 1;
 | 
			
		||||
				line-height: 30px;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			#loader-wrapper .load_title span {
 | 
			
		||||
				font-weight: normal;
 | 
			
		||||
				font-style: italic;
 | 
			
		||||
				font-size: 13px;
 | 
			
		||||
				color: #fff;
 | 
			
		||||
				opacity: 0.5;
 | 
			
		||||
			}
 | 
			
		||||
		</style>
 | 
			
		||||
	</head>
 | 
			
		||||
 | 
			
		||||
	<body>
 | 
			
		||||
		<div id="app">
 | 
			
		||||
			<div id="loader-wrapper">
 | 
			
		||||
				<div id="loader"></div>
 | 
			
		||||
				<div class="loader-section section-left"></div>
 | 
			
		||||
				<div class="loader-section section-right"></div>
 | 
			
		||||
				<div class="load_title">正在加载系统资源,请耐心等待</div>
 | 
			
		||||
			</div>
 | 
			
		||||
<body>
 | 
			
		||||
	<div id="app">
 | 
			
		||||
		<div id="loader-wrapper">
 | 
			
		||||
			<div id="loader"></div>
 | 
			
		||||
			<div class="loader-section section-left"></div>
 | 
			
		||||
			<div class="loader-section section-right"></div>
 | 
			
		||||
			<div class="load_title">正在加载系统资源,请耐心等待</div>
 | 
			
		||||
		</div>
 | 
			
		||||
	</body>
 | 
			
		||||
</html>
 | 
			
		||||
	</div>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										339
									
								
								public/print-lock.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										339
									
								
								public/print-lock.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,339 @@
 | 
			
		||||
@media print {
 | 
			
		||||
  body {
 | 
			
		||||
    margin: 0px;
 | 
			
		||||
    padding: 0px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@page {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printPaper * {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  -moz-box-sizing: border-box; /* Firefox */
 | 
			
		||||
  -webkit-box-sizing: border-box; /* Safari */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printPaper *:focus {
 | 
			
		||||
  outline: -webkit-focus-ring-color auto 0px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printPaper {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  padding: 0 0 0 0;
 | 
			
		||||
  page-break-after: always;
 | 
			
		||||
  -webkit-user-select: none; /* Chrome/Safari/Opera */
 | 
			
		||||
  -moz-user-select: none; /* Firefox */
 | 
			
		||||
  user-select: none;
 | 
			
		||||
  overflow-x: hidden;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printPaper .hiprint-printPaper-content {
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 火狐浏览器打印 第一页过后 重叠问题 */
 | 
			
		||||
@-moz-document url-prefix() {
 | 
			
		||||
  .hiprint-printPaper .hiprint-printPaper-content {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    margin-top: 20px;
 | 
			
		||||
    top: -20px
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printPaper.design {
 | 
			
		||||
  overflow: visible;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.hiprint-printTemplate .hiprint-printPanel {
 | 
			
		||||
  page-break-after: always;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printPaper, hiprint-printPanel {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  border: 0px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printPanel .hiprint-printPaper:last-child {
 | 
			
		||||
  page-break-after: avoid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printTemplate .hiprint-printPanel:last-child {
 | 
			
		||||
  page-break-after: avoid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printPaper .hideheaderLinetarget {
 | 
			
		||||
  border-top: 0px dashed rgb(201, 190, 190) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printPaper .hidefooterLinetarget {
 | 
			
		||||
  border-top: 0px dashed rgb(201, 190, 190) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printPaper.design {
 | 
			
		||||
  border: 1px dashed rgba(170, 170, 170, 0.7);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.design .hiprint-printElement-table-content, .design .hiprint-printElement-longText-content {
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.design .resize-panel {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  border: 1px dotted;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printElement-text {
 | 
			
		||||
  background-color: transparent;
 | 
			
		||||
  background-repeat: repeat;
 | 
			
		||||
  padding: 0 0 0 0;
 | 
			
		||||
  border: 0.75pt none rgb(0, 0, 0);
 | 
			
		||||
  direction: ltr;
 | 
			
		||||
  font-family: 'SimSun';
 | 
			
		||||
  font-size: 9pt;
 | 
			
		||||
  font-style: normal;
 | 
			
		||||
  font-weight: normal;
 | 
			
		||||
  padding-bottom: 0pt;
 | 
			
		||||
  padding-left: 0pt;
 | 
			
		||||
  padding-right: 0pt;
 | 
			
		||||
  padding-top: 0pt;
 | 
			
		||||
  text-align: left;
 | 
			
		||||
  text-decoration: none;
 | 
			
		||||
  line-height: 9.75pt;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  word-wrap: break-word;
 | 
			
		||||
  word-break: break-all;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.design .hiprint-printElement-text-content {
 | 
			
		||||
  border: 1px dashed rgb(206, 188, 188);
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printElement-longText {
 | 
			
		||||
  background-color: transparent;
 | 
			
		||||
  background-repeat: repeat;
 | 
			
		||||
  border: 0.75pt none rgb(0, 0, 0);
 | 
			
		||||
  direction: ltr;
 | 
			
		||||
  font-family: 'SimSun';
 | 
			
		||||
  font-size: 9pt;
 | 
			
		||||
  font-style: normal;
 | 
			
		||||
  font-weight: normal;
 | 
			
		||||
  padding-bottom: 0pt;
 | 
			
		||||
  padding-left: 0pt;
 | 
			
		||||
  padding-right: 0pt;
 | 
			
		||||
  padding-top: 0pt;
 | 
			
		||||
  text-align: left;
 | 
			
		||||
  text-decoration: none;
 | 
			
		||||
  line-height: 9.75pt;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  word-wrap: break-word;
 | 
			
		||||
  word-break: break-all;
 | 
			
		||||
  /*white-space: pre-wrap*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.hiprint-printElement-table {
 | 
			
		||||
  background-color: transparent;
 | 
			
		||||
  background-repeat: repeat;
 | 
			
		||||
  color: rgb(0, 0, 0);
 | 
			
		||||
  border-color: rgb(0, 0, 0);
 | 
			
		||||
  border-style: none;
 | 
			
		||||
  direction: ltr;
 | 
			
		||||
  font-family: 'SimSun';
 | 
			
		||||
  font-size: 9pt;
 | 
			
		||||
  font-style: normal;
 | 
			
		||||
  font-weight: normal;
 | 
			
		||||
  padding-bottom: 0pt;
 | 
			
		||||
  padding-left: 0pt;
 | 
			
		||||
  padding-right: 0pt;
 | 
			
		||||
  padding-top: 0pt;
 | 
			
		||||
  text-align: left;
 | 
			
		||||
  text-decoration: none;
 | 
			
		||||
  padding: 0 0 0 0;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  line-height: 9.75pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printElement-table thead {
 | 
			
		||||
  background: #e8e8e8;
 | 
			
		||||
  font-weight: 700;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printElement-tableTarget, .hiprint-printElement-tableTarget tr, .hiprint-printElement-tableTarget td {
 | 
			
		||||
  border-color: rgb(0, 0, 0);
 | 
			
		||||
  /*border-style: none;*/
 | 
			
		||||
  /*border: 1px solid rgb(0, 0, 0);*/
 | 
			
		||||
  font-weight: normal;
 | 
			
		||||
  direction: ltr;
 | 
			
		||||
  padding-bottom: 0pt;
 | 
			
		||||
  padding-left: 4pt;
 | 
			
		||||
  padding-right: 4pt;
 | 
			
		||||
  padding-top: 0pt;
 | 
			
		||||
  text-decoration: none;
 | 
			
		||||
  vertical-align: middle;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  word-wrap: break-word;
 | 
			
		||||
  word-break: break-all;
 | 
			
		||||
  /*line-height: 9.75pt;
 | 
			
		||||
  font-size: 9pt;*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printElement-tableTarget-border-all {
 | 
			
		||||
  border: 1px solid;
 | 
			
		||||
}
 | 
			
		||||
.hiprint-printElement-tableTarget-border-none {
 | 
			
		||||
  border: 0px solid;
 | 
			
		||||
}
 | 
			
		||||
.hiprint-printElement-tableTarget-border-lr {
 | 
			
		||||
  border-left: 1px solid;
 | 
			
		||||
  border-right: 1px solid;
 | 
			
		||||
}
 | 
			
		||||
.hiprint-printElement-tableTarget-border-left {
 | 
			
		||||
  border-left: 1px solid;
 | 
			
		||||
}
 | 
			
		||||
.hiprint-printElement-tableTarget-border-right {
 | 
			
		||||
  border-right: 1px solid;
 | 
			
		||||
}
 | 
			
		||||
.hiprint-printElement-tableTarget-border-tb {
 | 
			
		||||
  border-top: 1px solid;
 | 
			
		||||
  border-bottom: 1px solid;
 | 
			
		||||
}
 | 
			
		||||
.hiprint-printElement-tableTarget-border-top {
 | 
			
		||||
  border-top: 1px solid;
 | 
			
		||||
}
 | 
			
		||||
.hiprint-printElement-tableTarget-border-bottom {
 | 
			
		||||
  border-bottom: 1px solid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printElement-tableTarget-border-td-none td {
 | 
			
		||||
  border: 0px solid;
 | 
			
		||||
}
 | 
			
		||||
.hiprint-printElement-tableTarget-border-td-all td:not(:last-child) {
 | 
			
		||||
  border-right: 1px solid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*.hiprint-printElement-tableTarget tr,*/
 | 
			
		||||
.hiprint-printElement-tableTarget td {
 | 
			
		||||
  height: 18pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printPaper .hiprint-paperNumber {
 | 
			
		||||
  font-size: 9pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.design .hiprint-printElement-table-handle {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  height: 21pt;
 | 
			
		||||
  width: 21pt;
 | 
			
		||||
  background: red;
 | 
			
		||||
  z-index: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printPaper .hiprint-paperNumber-disabled {
 | 
			
		||||
  float: right !important;
 | 
			
		||||
  right: 0 !important;
 | 
			
		||||
  color: gainsboro !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printElement-vline, .hiprint-printElement-hline {
 | 
			
		||||
  border: 0px none rgb(0, 0, 0);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printElement-vline {
 | 
			
		||||
  border-left: 0.75pt solid #000;
 | 
			
		||||
  border-right: 0px none rgb(0, 0, 0) !important;
 | 
			
		||||
  border-bottom: 0px none rgb(0, 0, 0) !important;
 | 
			
		||||
  border-top: 0px none rgb(0, 0, 0) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printElement-hline {
 | 
			
		||||
  border-top: 0.75pt solid #000;
 | 
			
		||||
  border-right: 0px none rgb(0, 0, 0) !important;
 | 
			
		||||
  border-bottom: 0px none rgb(0, 0, 0) !important;
 | 
			
		||||
  border-left: 0px none rgb(0, 0, 0) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-printElement-oval, .hiprint-printElement-rect {
 | 
			
		||||
  border: 0.75pt solid #000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-text-content-middle {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-text-content-middle > div {
 | 
			
		||||
  display: grid;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-text-content-bottom {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-text-content-bottom > div {
 | 
			
		||||
  display: grid;
 | 
			
		||||
  align-items: flex-end;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-text-content-wrap {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-text-content-wrap .hiprint-text-content-wrap-nowrap {
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-text-content-wrap .hiprint-text-content-wrap-clip {
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  text-overflow: clip;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-text-content-wrap .hiprint-text-content-wrap-ellipsis {
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*hi-grid-row */
 | 
			
		||||
.hi-grid-row {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  height: auto;
 | 
			
		||||
  margin-right: 0;
 | 
			
		||||
  margin-left: 0;
 | 
			
		||||
  zoom: 1;
 | 
			
		||||
  display: block;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hi-grid-row::after, .hi-grid-row::before {
 | 
			
		||||
  display: table;
 | 
			
		||||
  content: '';
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hi-grid-col {
 | 
			
		||||
  display: block;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  float: left;
 | 
			
		||||
  flex: 0 0 auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.table-grid-row {
 | 
			
		||||
  margin-left: -0pt;
 | 
			
		||||
  margin-right: -0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tableGridColumnsGutterRow {
 | 
			
		||||
  padding-left: 0pt;
 | 
			
		||||
  padding-right: 0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hiprint-gridColumnsFooter {
 | 
			
		||||
  text-align: left;
 | 
			
		||||
  clear: both;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								src/assets/icons/svg/Confirm.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/assets/icons/svg/Confirm.svg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 | 
			
		||||
    <title>选择</title>
 | 
			
		||||
    <g id="设备管理" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
 | 
			
		||||
        <g id="设备监控-设备加工数量" transform="translate(-496.000000, -187.000000)" fill-rule="nonzero">
 | 
			
		||||
            <g id="选择" transform="translate(496.000000, 187.000000)">
 | 
			
		||||
                <rect id="矩形" fill="#000000" opacity="0" x="0" y="0" width="16" height="16"></rect>
 | 
			
		||||
                <path d="M13.8735116,4.65950813 C13.6725171,4.47101195 13.3555167,4.48001613 13.1670206,4.6815213 L6.49899208,11.7809972 L2.85649778,8.19199033 C2.65950812,7.99798414 2.34299153,8 2.14898534,8.19698966 C1.95497916,8.3934955 1.95747883,8.71049591 2.15449536,8.90399141 L6.16199434,12.8519823 C6.16349952,12.8534874 6.1654885,12.8539712 6.16699367,12.8554764 C6.16849884,12.8569816 6.16898266,12.8589706 6.17048783,12.8604757 C6.20198897,12.8904717 6.23999461,12.9074856 6.27649508,12.9274829 C6.29450341,12.9379922 6.3099852,12.953474 6.32898802,12.960973 C6.38798547,12.9839807 6.45047706,12.9959683 6.51248486,12.9959683 C6.57798681,12.9959683 6.64348875,12.9829593 6.70447519,12.9569682 C6.72498319,12.9484747 6.74097566,12.930977 6.75997848,12.919957 C6.79747344,12.8979438 6.83647358,12.8794517 6.86848541,12.8469561 C6.86999058,12.8454509 6.87047439,12.8429512 6.87197956,12.841446 C6.87297405,12.8399409 6.87498991,12.8394571 6.8764682,12.8379519 L13.8949604,5.36594544 C14.0849886,5.16548852 14.0745061,4.8489988 13.8735116,4.65950813 Z" id="路径" fill="#0B58FF"></path>
 | 
			
		||||
            </g>
 | 
			
		||||
        </g>
 | 
			
		||||
    </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 1.7 KiB  | 
							
								
								
									
										14
									
								
								src/assets/icons/svg/Qian.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/assets/icons/svg/Qian.svg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 | 
			
		||||
    <title>菜单</title>
 | 
			
		||||
    <g id="设备管理" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
 | 
			
		||||
        <g id="设备监控-设备加工数量" transform="translate(-284.000000, -164.000000)" fill-rule="nonzero">
 | 
			
		||||
            <g id="编组-7" transform="translate(284.000000, 162.000000)">
 | 
			
		||||
                <g id="菜单" transform="translate(0.000000, 2.000000)">
 | 
			
		||||
                    <rect id="矩形" fill="#000000" opacity="0" x="0" y="0" width="16" height="16"></rect>
 | 
			
		||||
                    <path d="M3.00057813,4.49926562 L13.0025156,4.49926562 C13.2786563,4.49926562 13.5025156,4.27540625 13.5025156,3.99926563 C13.5025156,3.723125 13.2786563,3.49926563 13.0025156,3.49926563 L3.00057813,3.49926563 C2.7244375,3.49926563 2.50057813,3.723125 2.50057813,3.99926563 C2.50057813,4.27540625 2.7244375,4.49926562 3.00057813,4.49926562 Z M3.0004375,8.48703125 L12.9786875,8.48703125 C13.2548281,8.48703125 13.4786875,8.26317187 13.4786875,7.98703125 C13.4786875,7.71089062 13.2548281,7.48703125 12.9786875,7.48703125 L3.0004375,7.48703125 C2.72429687,7.48703125 2.5004375,7.71089062 2.5004375,7.98703125 C2.5004375,8.26317187 2.72429687,8.48703125 3.0004375,8.48703125 Z M13.0025156,11.4969063 L3.00057813,11.4969063 C2.7244375,11.4969063 2.50057813,11.7207656 2.50057813,11.9969063 C2.50057813,12.2730469 2.7244375,12.4969063 3.00057813,12.4969063 L13.0025156,12.4969063 C13.2786563,12.4969063 13.5025156,12.2730469 13.5025156,11.9969063 C13.5025156,11.7207656 13.2786563,11.4969063 13.0025156,11.4969063 L13.0025156,11.4969063 Z" id="形状" fill="#373738"></path>
 | 
			
		||||
                </g>
 | 
			
		||||
            </g>
 | 
			
		||||
        </g>
 | 
			
		||||
    </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 1.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/DataBoard.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/assets/images/DataBoard.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 10 MiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/Qian.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/assets/images/Qian.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 612 B  | 
@@ -89,6 +89,8 @@ function findMaxLabelWidth(rows) {
 | 
			
		||||
	let max = 0;
 | 
			
		||||
	rows.forEach((row) => {
 | 
			
		||||
		row.forEach((opt) => {
 | 
			
		||||
			// debugger;
 | 
			
		||||
			if (!opt.label) return 0;
 | 
			
		||||
			if (opt.label.length > max) {
 | 
			
		||||
				max = opt.label.length;
 | 
			
		||||
			}
 | 
			
		||||
@@ -114,6 +116,10 @@ export default {
 | 
			
		||||
			type: Object,
 | 
			
		||||
			default: () => ({}),
 | 
			
		||||
		},
 | 
			
		||||
		disabled: {
 | 
			
		||||
			type: Boolean,
 | 
			
		||||
			default: false,
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ export default {
 | 
			
		||||
  min-height: calc(100vh - 56px);
 | 
			
		||||
  min-width: calc(100vh - 280px);
 | 
			
		||||
  position: relative;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  overflow: visible;
 | 
			
		||||
  margin: 8px 14px 0px 16px;
 | 
			
		||||
  border-radius: 8px;
 | 
			
		||||
  background-color: #fff;
 | 
			
		||||
 
 | 
			
		||||
@@ -53,6 +53,9 @@ export default {
 | 
			
		||||
				case 'delete':
 | 
			
		||||
					this.handleDelete(data);
 | 
			
		||||
					break;
 | 
			
		||||
				case 'detail':
 | 
			
		||||
					this.handleDetail(data);
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 处理搜索栏按钮
 | 
			
		||||
 
 | 
			
		||||
@@ -64,6 +64,11 @@ export const constantRoutes = [
 | 
			
		||||
    component: (resolve) => require(['@/views/error/401'], resolve),
 | 
			
		||||
    hidden: true
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: '/print-design',
 | 
			
		||||
    component: (resolve) => require(['@/views/print/design'], resolve),
 | 
			
		||||
    hidden: true
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: '/',
 | 
			
		||||
    component: Layout,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										74
									
								
								src/views/base/dataBoard/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/views/base/dataBoard/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
<!-- 
 | 
			
		||||
    filename: index.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-10-11 09:32:04
 | 
			
		||||
    description: 设备看板
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div ref="dataBoard" class=""></div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'DataBoard',
 | 
			
		||||
	components: {},
 | 
			
		||||
	props: {},
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			appMain: null, // dom
 | 
			
		||||
			parentStyle: {
 | 
			
		||||
				margin: '8px 14px 0px 16px',
 | 
			
		||||
				minHeight: 'calc(100vh - 120px - 8px)',
 | 
			
		||||
			}, // object
 | 
			
		||||
			mainFooter: null, // dom
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	mounted() {
 | 
			
		||||
		this.$nextTick(() => {
 | 
			
		||||
			this.modify();
 | 
			
		||||
		});
 | 
			
		||||
	},
 | 
			
		||||
	activated() {
 | 
			
		||||
		this.modify();
 | 
			
		||||
	},
 | 
			
		||||
	deactivated() {
 | 
			
		||||
		this.recover();
 | 
			
		||||
	},
 | 
			
		||||
	beforeDestroy() {
 | 
			
		||||
		this.recover();
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		modify() {
 | 
			
		||||
			// 在这个页面临时修改下父类的margin,结束时需还原
 | 
			
		||||
			this.appMain = document.querySelector('.app-main');
 | 
			
		||||
			// this.appMain.style.minHeight = 'calc(100vh - 90px)';
 | 
			
		||||
			this.appMain.style.margin = 0;
 | 
			
		||||
			// 在这个页面临时删除 main-footer 元素,结束时需还原
 | 
			
		||||
			// this.mainFooter = document.querySelector('.main-footer').cloneNode(true);
 | 
			
		||||
			// document.querySelector('.main-footer').remove();
 | 
			
		||||
            this.$refs.dataBoard.classList.add('data-board');
 | 
			
		||||
		},
 | 
			
		||||
		recover() {
 | 
			
		||||
            this.$refs.dataBoard.classList.remove('data-board');
 | 
			
		||||
			this.$nextTick(() => {
 | 
			
		||||
				this.appMain.style.margin = this.parentStyle.margin;
 | 
			
		||||
				// this.appMain.style.minHeight = this.parentStyle.minHeight;
 | 
			
		||||
				// this.appMain.insertAdjacentElement('afterend', this.mainFooter);
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="scss">
 | 
			
		||||
.data-board {
 | 
			
		||||
	position: absolute;
 | 
			
		||||
	top: 0;
 | 
			
		||||
	left: 0;
 | 
			
		||||
	width: 100%;
 | 
			
		||||
	height: 100%;
 | 
			
		||||
	background: url('../../../assets/images/DataBoard.png') 100% 100% / contain
 | 
			
		||||
		no-repeat;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										482
									
								
								src/views/base/equipmentBindGroup/components/BasicDrawer.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										482
									
								
								src/views/base/equipmentBindGroup/components/BasicDrawer.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,482 @@
 | 
			
		||||
<!-- 
 | 
			
		||||
    filename: EquipmentDrawer.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-08-22 14:38:56
 | 
			
		||||
    description: 
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<el-drawer
 | 
			
		||||
		:visible="visible"
 | 
			
		||||
		:show-close="false"
 | 
			
		||||
		:wrapper-closable="false"
 | 
			
		||||
		class="drawer"
 | 
			
		||||
		custom-class="mes-drawer"
 | 
			
		||||
		size="60%"
 | 
			
		||||
		@closed="$emit('destroy')">
 | 
			
		||||
		<SmallTitle slot="title">
 | 
			
		||||
			{{
 | 
			
		||||
				mode.includes('detail')
 | 
			
		||||
					? '详情'
 | 
			
		||||
					: mode.includes('edit')
 | 
			
		||||
					? '编辑'
 | 
			
		||||
					: '新增'
 | 
			
		||||
			}}
 | 
			
		||||
		</SmallTitle>
 | 
			
		||||
 | 
			
		||||
		<div class="drawer-body flex">
 | 
			
		||||
			<div class="drawer-body__content">
 | 
			
		||||
				<section v-for="(section, index) in sections" :key="section.key">
 | 
			
		||||
					<SmallTitle v-if="index != 0">{{ section.name }}</SmallTitle>
 | 
			
		||||
 | 
			
		||||
					<div class="form-part" v-if="section.key == 'base'">
 | 
			
		||||
						<el-skeleton v-if="!showForm" animated />
 | 
			
		||||
						<BaseInfoForm
 | 
			
		||||
							key="drawer-dialog-form"
 | 
			
		||||
							v-if="showForm"
 | 
			
		||||
							ref="form"
 | 
			
		||||
							:disabled="true"
 | 
			
		||||
							:dataForm="form"
 | 
			
		||||
							:rows="formRows" />
 | 
			
		||||
					</div>
 | 
			
		||||
 | 
			
		||||
					<div v-if="section.key == 'attrs'" style="margin-top: 12px">
 | 
			
		||||
						<base-table
 | 
			
		||||
							v-loading="attrListLoading"
 | 
			
		||||
							:table-props="section.props"
 | 
			
		||||
							:page="attrQuery?.params.pageNo || 1"
 | 
			
		||||
							:limit="attrQuery?.params.pageSize || 10"
 | 
			
		||||
							:table-data="list"
 | 
			
		||||
							:add-button-show="mode.includes('detail') ? null : '添加属性'"
 | 
			
		||||
							@emitButtonClick="handleAddAttr"
 | 
			
		||||
							@emitFun="handleEmitFun">
 | 
			
		||||
							<method-btn
 | 
			
		||||
								v-if="section.tableBtn"
 | 
			
		||||
								slot="handleBtn"
 | 
			
		||||
								label="操作"
 | 
			
		||||
								:method-list="tableBtn"
 | 
			
		||||
								@clickBtn="handleTableBtnClick" />
 | 
			
		||||
						</base-table>
 | 
			
		||||
 | 
			
		||||
						<!-- 分页组件 -->
 | 
			
		||||
						<pagination
 | 
			
		||||
							v-show="total > 0"
 | 
			
		||||
							:total="total"
 | 
			
		||||
							:page.sync="attrQuery.params.pageNo"
 | 
			
		||||
							:limit.sync="attrQuery.params.pageSize"
 | 
			
		||||
							@pagination="getAttrList" />
 | 
			
		||||
					</div>
 | 
			
		||||
				</section>
 | 
			
		||||
			</div>
 | 
			
		||||
 | 
			
		||||
			<div class="drawer-body__footer">
 | 
			
		||||
				<el-button style="" @click="handleCancel">取消</el-button>
 | 
			
		||||
				<el-button v-if="mode == 'detail'" type="primary" @click="toggleEdit">
 | 
			
		||||
					编辑
 | 
			
		||||
				</el-button>
 | 
			
		||||
				<el-button v-else type="primary" @click="handleCancel">确定</el-button>
 | 
			
		||||
				<!-- sections的第二项必须是 属性列表  -->
 | 
			
		||||
				<!-- <el-button
 | 
			
		||||
						v-if="sections[1].allowAdd"
 | 
			
		||||
						type="primary"
 | 
			
		||||
						@click="handleAddAttr">
 | 
			
		||||
						添加属性
 | 
			
		||||
					</el-button> -->
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
 | 
			
		||||
		<!-- 属性对话框 -->
 | 
			
		||||
		<base-dialog
 | 
			
		||||
			v-if="sections[1].allowAdd"
 | 
			
		||||
			:dialogTitle="attrTitle"
 | 
			
		||||
			:dialogVisible="attrFormVisible"
 | 
			
		||||
			width="45%"
 | 
			
		||||
			:append-to-body="true"
 | 
			
		||||
			custom-class="baseDialog"
 | 
			
		||||
			@close="closeAttrForm"
 | 
			
		||||
			@cancel="closeAttrForm"
 | 
			
		||||
			@confirm="submitAttrForm">
 | 
			
		||||
			<DialogForm
 | 
			
		||||
				v-if="attrFormVisible"
 | 
			
		||||
				ref="attrForm"
 | 
			
		||||
				:disabled="mode.includes('detail')"
 | 
			
		||||
				v-model="attrForm"
 | 
			
		||||
				:rows="attrRows" />
 | 
			
		||||
		</base-dialog>
 | 
			
		||||
	</el-drawer>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import BaseInfoForm from '@/components/DialogForm';
 | 
			
		||||
import DialogForm from './dialogForm';
 | 
			
		||||
 | 
			
		||||
const SmallTitle = {
 | 
			
		||||
	name: 'SmallTitle',
 | 
			
		||||
	props: ['size'],
 | 
			
		||||
	data() {
 | 
			
		||||
		return {};
 | 
			
		||||
	},
 | 
			
		||||
	methods: {},
 | 
			
		||||
	render: function (h) {
 | 
			
		||||
		return h(
 | 
			
		||||
			'span',
 | 
			
		||||
			{
 | 
			
		||||
				class: 'small-title',
 | 
			
		||||
				style: {
 | 
			
		||||
					fontSize: '18px',
 | 
			
		||||
					lineHeight:
 | 
			
		||||
						this.size == 'lg' ? '24px' : this.size == 'sm' ? '18px' : '20px',
 | 
			
		||||
					fontWeight: 500,
 | 
			
		||||
					fontFamily: '微软雅黑, Microsoft YaHei, Arial, Helvetica, sans-serif',
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			this.$slots.default
 | 
			
		||||
		);
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	components: { SmallTitle, DialogForm, BaseInfoForm },
 | 
			
		||||
	props: ['sections', 'defaultMode', 'dataId'], // dataId 作为一个通用的存放id的字段
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			mode: '',
 | 
			
		||||
			visible: false,
 | 
			
		||||
			showForm: false,
 | 
			
		||||
			total: 0,
 | 
			
		||||
			form: {},
 | 
			
		||||
			list: [],
 | 
			
		||||
			attrTitle: '',
 | 
			
		||||
			attrForm: {
 | 
			
		||||
				id: null,
 | 
			
		||||
				equipmentGroupId: '',
 | 
			
		||||
				code: '',
 | 
			
		||||
				type: '',
 | 
			
		||||
				grade: '',
 | 
			
		||||
				alarmCode: '',
 | 
			
		||||
				alarmContent: '',
 | 
			
		||||
				plcParamName: '',
 | 
			
		||||
			},
 | 
			
		||||
			attrFormVisible: false,
 | 
			
		||||
			attrRows: [
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '报警编码', // 自动生成
 | 
			
		||||
						prop: 'code',
 | 
			
		||||
						url: '/base/equipment-group-alarm/getCode',
 | 
			
		||||
						rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						select: true,
 | 
			
		||||
						label: '报警类型', // 固定选项
 | 
			
		||||
						prop: 'type',
 | 
			
		||||
						options: [
 | 
			
		||||
							{ label: '布尔型', value: 2 },
 | 
			
		||||
							{ label: '字符型', value: 1 },
 | 
			
		||||
						],
 | 
			
		||||
						rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						select: true,
 | 
			
		||||
						label: '报警级别', // 字典
 | 
			
		||||
						prop: 'grade',
 | 
			
		||||
						options: this.getDictDatas(this.DICT_TYPE.EQU_ALARM_LEVEL),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '设备报警编码', // 对应到设备实际的报警编码
 | 
			
		||||
						prop: 'alarmCode',
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '参数列名', // 在实时数据库的列名
 | 
			
		||||
						prop: 'plcParamName',
 | 
			
		||||
						rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '报警内容',
 | 
			
		||||
						prop: 'alarmContent',
 | 
			
		||||
						rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
			],
 | 
			
		||||
			attrQuery: {
 | 
			
		||||
				params: {
 | 
			
		||||
					pageNo: 1,
 | 
			
		||||
					pageSize: 10,
 | 
			
		||||
				},
 | 
			
		||||
			}, // 属性列表的请求
 | 
			
		||||
			infoQuery: null, // 基本信息的请求
 | 
			
		||||
			attrFormSubmitting: false,
 | 
			
		||||
			attrListLoading: false,
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	computed: {
 | 
			
		||||
		formRows() {
 | 
			
		||||
			return this.sections[0].rows.map((row) => {
 | 
			
		||||
				return row.map((col) => {
 | 
			
		||||
					return {
 | 
			
		||||
						...col,
 | 
			
		||||
						bind: {
 | 
			
		||||
							// 详情 模式下,禁用各种输入
 | 
			
		||||
							// disabled: this.mode == 'detail',
 | 
			
		||||
							disabled: true,
 | 
			
		||||
						},
 | 
			
		||||
					};
 | 
			
		||||
				});
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
		tableBtn() {
 | 
			
		||||
			return this.mode == 'detail' ? [] : this.sections[1].tableBtn;
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	mounted() {
 | 
			
		||||
		this.mode = this.defaultMode || 'detail';
 | 
			
		||||
		for (const section of this.sections) {
 | 
			
		||||
			// 请求具体信息
 | 
			
		||||
			if ('url' in section) {
 | 
			
		||||
				const query = {
 | 
			
		||||
					url: section.url,
 | 
			
		||||
					method: section.method || 'get',
 | 
			
		||||
					params: section.queryParams || null,
 | 
			
		||||
					data: section.data || null,
 | 
			
		||||
				};
 | 
			
		||||
				// debugger;
 | 
			
		||||
				this.$axios(query).then(({ data }) => {
 | 
			
		||||
					if (section.key == 'base') {
 | 
			
		||||
						this.form = data;
 | 
			
		||||
						this.showForm = true;
 | 
			
		||||
						this.infoQuery = query;
 | 
			
		||||
					} else if (section.key == 'attrs') {
 | 
			
		||||
						this.attrQuery = query;
 | 
			
		||||
						this.list = data.list;
 | 
			
		||||
						this.total = data.total;
 | 
			
		||||
					}
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		handleTableBtnClick({ type, data }) {
 | 
			
		||||
			switch (type) {
 | 
			
		||||
				case 'edit':
 | 
			
		||||
					this.handleEditAttr(data.id);
 | 
			
		||||
					break;
 | 
			
		||||
				case 'delete':
 | 
			
		||||
					this.handleDeleteAttr(data.id);
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleEmitFun(val) {
 | 
			
		||||
			console.log('handleEmitFun', val);
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		init() {
 | 
			
		||||
			this.visible = true;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		async getAttrList() {
 | 
			
		||||
			this.attrListLoading = true;
 | 
			
		||||
			const res = await this.$axios(this.attrQuery);
 | 
			
		||||
			if (res.code == 0) {
 | 
			
		||||
				this.list = res.data.list;
 | 
			
		||||
				this.total = res.data.total;
 | 
			
		||||
			}
 | 
			
		||||
			this.attrListLoading = false;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 保存表单
 | 
			
		||||
		handleSave() {
 | 
			
		||||
			this.$refs['form'][0].validate(async (valid) => {
 | 
			
		||||
				if (valid) {
 | 
			
		||||
					const isEdit = this.mode == 'edit';
 | 
			
		||||
					await this.$axios({
 | 
			
		||||
						url: this.sections[0][isEdit ? 'urlUpdate' : 'urlCreate'],
 | 
			
		||||
						method: isEdit ? 'put' : 'post',
 | 
			
		||||
						data: this.form,
 | 
			
		||||
					});
 | 
			
		||||
					this.$modal.msgSuccess(`${isEdit ? '更新' : '创建'}成功`);
 | 
			
		||||
					this.visible = false;
 | 
			
		||||
					this.$emit('refreshDataList');
 | 
			
		||||
				}
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleCancel() {
 | 
			
		||||
			this.visible = false;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 开启编辑
 | 
			
		||||
		toggleEdit() {
 | 
			
		||||
			this.mode = 'edit';
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 新增属性
 | 
			
		||||
		handleAddAttr() {
 | 
			
		||||
			if (!this.dataId) return this.$message.error('请先创建设备分组信息');
 | 
			
		||||
			this.attrForm = {
 | 
			
		||||
				id: null,
 | 
			
		||||
				equipmentGroupId: this.dataId,
 | 
			
		||||
				code: '',
 | 
			
		||||
				type: '',
 | 
			
		||||
				grade: '',
 | 
			
		||||
				alarmCode: '',
 | 
			
		||||
				alarmContent: '',
 | 
			
		||||
				plcParamName: '',
 | 
			
		||||
			};
 | 
			
		||||
			this.attrTitle = '添加设备分组报警';
 | 
			
		||||
			this.attrFormVisible = true;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 编辑属性
 | 
			
		||||
		async handleEditAttr(attrId) {
 | 
			
		||||
			const res = await this.$axios({
 | 
			
		||||
				url: this.sections[1].urlDetail,
 | 
			
		||||
				method: 'get',
 | 
			
		||||
				params: { id: attrId },
 | 
			
		||||
			});
 | 
			
		||||
			if (res.code == 0) {
 | 
			
		||||
				this.attrForm = res.data;
 | 
			
		||||
				this.attrTitle = '编辑设备分组报警';
 | 
			
		||||
				this.attrFormVisible = true;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 删除属性
 | 
			
		||||
		handleDeleteAttr(attrId) {
 | 
			
		||||
			this.$confirm('确定删除该分组报警?', '提示', {
 | 
			
		||||
				confirmButtonText: '确定',
 | 
			
		||||
				cancelButtonText: '取消',
 | 
			
		||||
				type: 'warning',
 | 
			
		||||
			})
 | 
			
		||||
				.then(async () => {
 | 
			
		||||
					const res = await this.$axios({
 | 
			
		||||
						url: this.sections[1].urlDelete,
 | 
			
		||||
						method: 'delete',
 | 
			
		||||
						params: { id: attrId },
 | 
			
		||||
					});
 | 
			
		||||
					if (res.code == 0) {
 | 
			
		||||
						this.$message({
 | 
			
		||||
							message: '删除成功',
 | 
			
		||||
							type: 'success',
 | 
			
		||||
							duration: 1500,
 | 
			
		||||
							onClose: () => {
 | 
			
		||||
								this.getAttrList();
 | 
			
		||||
							},
 | 
			
		||||
						});
 | 
			
		||||
					}
 | 
			
		||||
				})
 | 
			
		||||
				.catch(() => {});
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 提交属性表
 | 
			
		||||
		async submitAttrForm() {
 | 
			
		||||
			this.$refs['attrForm'].validate((valid) => {
 | 
			
		||||
				if (!valid) {
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
			});
 | 
			
		||||
			console.log('this.attrform', this.attrForm);
 | 
			
		||||
			const isEdit = this.attrForm.id != null;
 | 
			
		||||
			this.attrFormSubmitting = true;
 | 
			
		||||
			const res = await this.$axios({
 | 
			
		||||
				url: isEdit ? this.sections[1].urlUpdate : this.sections[1].urlCreate,
 | 
			
		||||
				method: isEdit ? 'put' : 'post',
 | 
			
		||||
				data: this.attrForm,
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
			if (res.code == 0) {
 | 
			
		||||
				this.closeAttrForm();
 | 
			
		||||
				this.$message({
 | 
			
		||||
					message: `${isEdit ? '更新' : '创建'}成功`,
 | 
			
		||||
					type: 'success',
 | 
			
		||||
					duration: 1500,
 | 
			
		||||
					onClose: () => {
 | 
			
		||||
						this.getAttrList();
 | 
			
		||||
					},
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
			this.attrFormSubmitting = false;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		closeAttrForm() {
 | 
			
		||||
			this.attrFormVisible = false;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleClick(raw) {
 | 
			
		||||
			if (raw.type === 'delete') {
 | 
			
		||||
				this.$confirm(`确定删除该报警?`, '提示', {
 | 
			
		||||
					confirmButtonText: '确定',
 | 
			
		||||
					cancelButtonText: '取消',
 | 
			
		||||
					type: 'warning',
 | 
			
		||||
				})
 | 
			
		||||
					.then(() => {
 | 
			
		||||
						deleteProductAttr(raw.data.id).then(({ data }) => {
 | 
			
		||||
							this.$message({
 | 
			
		||||
								message: '操作成功',
 | 
			
		||||
								type: 'success',
 | 
			
		||||
								duration: 1500,
 | 
			
		||||
								onClose: () => {
 | 
			
		||||
									this.getList();
 | 
			
		||||
								},
 | 
			
		||||
							});
 | 
			
		||||
						});
 | 
			
		||||
					})
 | 
			
		||||
					.catch(() => {});
 | 
			
		||||
			} else {
 | 
			
		||||
				this.addNew(raw.data.id);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.drawer >>> .el-drawer {
 | 
			
		||||
	border-radius: 8px 0 0 8px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.drawer >>> .el-drawer__header {
 | 
			
		||||
	margin: 0;
 | 
			
		||||
	padding: 32px 32px 24px;
 | 
			
		||||
	border-bottom: 1px solid #dcdfe6;
 | 
			
		||||
	margin-bottom: 0px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.small-title::before {
 | 
			
		||||
	content: '';
 | 
			
		||||
	display: inline-block;
 | 
			
		||||
	vertical-align: top;
 | 
			
		||||
	width: 4px;
 | 
			
		||||
	height: 22px;
 | 
			
		||||
	border-radius: 1px;
 | 
			
		||||
	margin-right: 8px;
 | 
			
		||||
	background-color: #0b58ff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.drawer-body {
 | 
			
		||||
	display: flex;
 | 
			
		||||
	flex-direction: column;
 | 
			
		||||
	height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.drawer-body__content {
 | 
			
		||||
	flex: 1;
 | 
			
		||||
	/* background: #eee; */
 | 
			
		||||
	padding: 20px 30px;
 | 
			
		||||
	overflow-y: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.drawer-body__footer {
 | 
			
		||||
	display: flex;
 | 
			
		||||
	justify-content: flex-end;
 | 
			
		||||
	padding: 18px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										186
									
								
								src/views/base/equipmentBindGroup/components/dialogForm.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								src/views/base/equipmentBindGroup/components/dialogForm.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,186 @@
 | 
			
		||||
<!-- 
 | 
			
		||||
    filename: dialogForm.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-09-11 15:55:13
 | 
			
		||||
    description: DialogForm for equipmentBindSection only
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<el-form
 | 
			
		||||
		ref="form"
 | 
			
		||||
		:model="dataForm"
 | 
			
		||||
		label-width="100px"
 | 
			
		||||
		v-loading="formLoading">
 | 
			
		||||
		<el-row :gutter="20">
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="报警编码"
 | 
			
		||||
					prop="code"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-input
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.code"
 | 
			
		||||
						@change="$emit('update', dataForm)"
 | 
			
		||||
						placeholder="请输入工段排序" />
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
				<!-- 				
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="报警编码"
 | 
			
		||||
					prop="code"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-select
 | 
			
		||||
						v-model="dataForm.code"
 | 
			
		||||
						placeholder="请选择产线"
 | 
			
		||||
						@change="handleProductlineChange">
 | 
			
		||||
						<el-option
 | 
			
		||||
							v-for="opt in productionLineList"
 | 
			
		||||
							:key="opt.value"
 | 
			
		||||
							:label="opt.label"
 | 
			
		||||
							:value="opt.value" />
 | 
			
		||||
					</el-select>
 | 
			
		||||
				</el-form-item> -->
 | 
			
		||||
			</el-col>
 | 
			
		||||
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="报警类型"
 | 
			
		||||
					prop="type"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-select
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.type"
 | 
			
		||||
						placeholder="请选择报警类型"
 | 
			
		||||
						@change="handleTypeChange">
 | 
			
		||||
						<el-option
 | 
			
		||||
							v-for="opt in [
 | 
			
		||||
								{ label: '布尔型', value: 2 },
 | 
			
		||||
								{ label: '字符型', value: 1 },
 | 
			
		||||
							]"
 | 
			
		||||
							:key="opt.value"
 | 
			
		||||
							:label="opt.label"
 | 
			
		||||
							:value="opt.value" />
 | 
			
		||||
					</el-select>
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
			</el-col>
 | 
			
		||||
		</el-row>
 | 
			
		||||
		<el-row :gutter="20">
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="报警级别"
 | 
			
		||||
					prop="grade"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-select
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.grade"
 | 
			
		||||
						placeholder="请选择报警级别"
 | 
			
		||||
						@change="$emit('update', dataForm)">
 | 
			
		||||
						<el-option
 | 
			
		||||
							v-for="opt in getDictDatas(DICT_TYPE.EQU_ALARM_LEVEL)"
 | 
			
		||||
							:key="opt.value"
 | 
			
		||||
							:label="opt.label"
 | 
			
		||||
							:value="opt.value" />
 | 
			
		||||
					</el-select>
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
			</el-col>
 | 
			
		||||
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					v-if="+dataForm.type == 1"
 | 
			
		||||
					label="设备报警编码"
 | 
			
		||||
					prop="alarmCode">
 | 
			
		||||
					<el-input
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.alarmCode"
 | 
			
		||||
						@change="$emit('update', dataForm)"
 | 
			
		||||
						placeholder="请输入设备报警编码" />
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
			</el-col>
 | 
			
		||||
		</el-row>
 | 
			
		||||
		<el-row :gutter="20">
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="参数列名"
 | 
			
		||||
					prop="plcParamName"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-input
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.plcParamName"
 | 
			
		||||
						placeholder="请输入参数列名"
 | 
			
		||||
						@change="$emit('update', dataForm)"></el-input>
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
			</el-col>
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="报警内容"
 | 
			
		||||
					prop="alarmContent"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-input
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.alarmContent"
 | 
			
		||||
						placeholder="请输入报警内容"
 | 
			
		||||
						@change="$emit('update', dataForm)"></el-input>
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
			</el-col>
 | 
			
		||||
		</el-row>
 | 
			
		||||
	</el-form>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'DialogForm',
 | 
			
		||||
	model: {
 | 
			
		||||
		prop: 'dataForm',
 | 
			
		||||
		event: 'update',
 | 
			
		||||
	},
 | 
			
		||||
	emits: ['update'],
 | 
			
		||||
	components: {},
 | 
			
		||||
	props: {
 | 
			
		||||
		dataForm: {
 | 
			
		||||
			type: Object,
 | 
			
		||||
			default: () => ({}),
 | 
			
		||||
		},
 | 
			
		||||
		disabled: {
 | 
			
		||||
			type: Boolean,
 | 
			
		||||
			default: false,
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			formLoading: true,
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	mounted() {
 | 
			
		||||
		this.getCode('/base/equipment-group-alarm/getCode').then((code) => {
 | 
			
		||||
			this.formLoading = false;
 | 
			
		||||
			this.$emit('update', {
 | 
			
		||||
				...this.dataForm,
 | 
			
		||||
				code,
 | 
			
		||||
			});
 | 
			
		||||
		});
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		/** 模拟透传 ref  */
 | 
			
		||||
		validate(cb) {
 | 
			
		||||
			return this.$refs.form.validate(cb);
 | 
			
		||||
		},
 | 
			
		||||
		resetFields(args) {
 | 
			
		||||
			return this.$refs.form.resetFields(args);
 | 
			
		||||
		},
 | 
			
		||||
		async handleTypeChange(id) {
 | 
			
		||||
			this.dataForm.alarmCode = '';
 | 
			
		||||
			this.$emit('update', this.dataForm);
 | 
			
		||||
		},
 | 
			
		||||
		async getCode(url) {
 | 
			
		||||
			const response = await this.$axios(url);
 | 
			
		||||
			return response.data;
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="scss">
 | 
			
		||||
.el-date-editor,
 | 
			
		||||
.el-select {
 | 
			
		||||
	width: 100%;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -40,6 +40,57 @@
 | 
			
		||||
			@confirm="submitForm">
 | 
			
		||||
			<DialogForm v-if="open" ref="form" :dataForm="form" :rows="rows" />
 | 
			
		||||
		</base-dialog>
 | 
			
		||||
 | 
			
		||||
		<!-- 抽屉 详情 -->
 | 
			
		||||
		<BasicDrawer
 | 
			
		||||
			v-if="editVisible"
 | 
			
		||||
			ref="drawer"
 | 
			
		||||
			:default-mode="editMode"
 | 
			
		||||
			:data-id="alarmForm.id"
 | 
			
		||||
			:sections="[
 | 
			
		||||
				{
 | 
			
		||||
					name: '基本信息',
 | 
			
		||||
					key: 'base',
 | 
			
		||||
					rows: drawerBaseInfoRows,
 | 
			
		||||
					url: '/base/equipment-group/get',
 | 
			
		||||
					urlUpdate: '/base/equipment-group/update',
 | 
			
		||||
					urlCreate: '/base/equipment-group/create',
 | 
			
		||||
					queryParams: { id: alarmForm.id },
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					name: '属性列表',
 | 
			
		||||
					key: 'attrs',
 | 
			
		||||
					props: drawerListProps,
 | 
			
		||||
					url: '/base/equipment-group-alarm/page',
 | 
			
		||||
					urlCreate: '/base/equipment-group-alarm/create',
 | 
			
		||||
					urlUpdate: '/base/equipment-group-alarm/update',
 | 
			
		||||
					urlDelete: '/base/equipment-group-alarm/delete',
 | 
			
		||||
					urlDetail: '/base/equipment-group-alarm/get',
 | 
			
		||||
					queryParams: {
 | 
			
		||||
						equipmentGroupId: alarmForm.id,
 | 
			
		||||
						pageNo: 1,
 | 
			
		||||
						pageSize: 10,
 | 
			
		||||
					},
 | 
			
		||||
					tableBtn: [
 | 
			
		||||
						this.$auth.hasPermi('base:equipment-group:update')
 | 
			
		||||
							? {
 | 
			
		||||
									type: 'edit',
 | 
			
		||||
									btnName: '修改',
 | 
			
		||||
							  }
 | 
			
		||||
							: undefined,
 | 
			
		||||
						this.$auth.hasPermi('base:equipment-group:delete')
 | 
			
		||||
							? {
 | 
			
		||||
									type: 'delete',
 | 
			
		||||
									btnName: '删除',
 | 
			
		||||
							  }
 | 
			
		||||
							: undefined,
 | 
			
		||||
					].filter((v) => v),
 | 
			
		||||
					allowAdd: true,
 | 
			
		||||
				},
 | 
			
		||||
			]"
 | 
			
		||||
			@refreshDataList="getList"
 | 
			
		||||
			@cancel="editVisible = false"
 | 
			
		||||
			@destroy="editVisible = false" />
 | 
			
		||||
	</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -55,16 +106,24 @@ import {
 | 
			
		||||
 | 
			
		||||
import { getEquipmentGroupPage } from '@/api/base/equipmentGroup';
 | 
			
		||||
import moment from 'moment';
 | 
			
		||||
import { publicFormatter } from '@/utils/dict';
 | 
			
		||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
 | 
			
		||||
import BasicDrawer from './components/BasicDrawer.vue';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'EquipmentBindGroup',
 | 
			
		||||
	components: {},
 | 
			
		||||
	components: { BasicDrawer },
 | 
			
		||||
	mixins: [basicPageMixin],
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			searchBarKeys: ['groupId', 'equipmentName'],
 | 
			
		||||
			tableBtn: [
 | 
			
		||||
				this.$auth.hasPermi('base:equipment-bind-group:update')
 | 
			
		||||
					? {
 | 
			
		||||
							type: 'detail',
 | 
			
		||||
							btnName: '查看报警',
 | 
			
		||||
					  }
 | 
			
		||||
					: undefined,
 | 
			
		||||
				this.$auth.hasPermi('base:equipment-bind-group:update')
 | 
			
		||||
					? {
 | 
			
		||||
							type: 'edit',
 | 
			
		||||
@@ -88,32 +147,32 @@ export default {
 | 
			
		||||
				},
 | 
			
		||||
				{ prop: 'equipmentName', label: '设备' },
 | 
			
		||||
				{ prop: 'groupName', label: '分组' },
 | 
			
		||||
				{
 | 
			
		||||
					_action: 'equipment-bind-group-show-alert',
 | 
			
		||||
					label: '分组报警',
 | 
			
		||||
					subcomponent: {
 | 
			
		||||
						props: ['injectData'],
 | 
			
		||||
						render: function (h) {
 | 
			
		||||
							const _this = this;
 | 
			
		||||
							return h(
 | 
			
		||||
								'el-button',
 | 
			
		||||
								{
 | 
			
		||||
									props: { type: 'text' },
 | 
			
		||||
									on: {
 | 
			
		||||
										click: function () {
 | 
			
		||||
											console.log('inejctdata', _this.injectData);
 | 
			
		||||
											_this.$emit('emitData', {
 | 
			
		||||
												action: _this.injectData._action,
 | 
			
		||||
												value: _this.injectData,
 | 
			
		||||
											});
 | 
			
		||||
										},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
								'查看报警'
 | 
			
		||||
							);
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				// {
 | 
			
		||||
				// 	_action: 'equipment-bind-group-show-alert',
 | 
			
		||||
				// 	label: '分组报警',
 | 
			
		||||
				// 	subcomponent: {
 | 
			
		||||
				// 		props: ['injectData'],
 | 
			
		||||
				// 		render: function (h) {
 | 
			
		||||
				// 			const _this = this;
 | 
			
		||||
				// 			return h(
 | 
			
		||||
				// 				'el-button',
 | 
			
		||||
				// 				{
 | 
			
		||||
				// 					props: { type: 'text' },
 | 
			
		||||
				// 					on: {
 | 
			
		||||
				// 						click: function () {
 | 
			
		||||
				// 							console.log('inejctdata', _this.injectData);
 | 
			
		||||
				// 							_this.$emit('emitData', {
 | 
			
		||||
				// 								action: _this.injectData._action,
 | 
			
		||||
				// 								value: _this.injectData,
 | 
			
		||||
				// 							});
 | 
			
		||||
				// 						},
 | 
			
		||||
				// 					},
 | 
			
		||||
				// 				},
 | 
			
		||||
				// 				'查看报警'
 | 
			
		||||
				// 			);
 | 
			
		||||
				// 		},
 | 
			
		||||
				// 	},
 | 
			
		||||
				// },
 | 
			
		||||
			],
 | 
			
		||||
			searchBarFormConfig: [
 | 
			
		||||
				{
 | 
			
		||||
@@ -196,6 +255,59 @@ export default {
 | 
			
		||||
			form: {},
 | 
			
		||||
			// 表单校验
 | 
			
		||||
			rules: {},
 | 
			
		||||
			//
 | 
			
		||||
			alarmForm: {
 | 
			
		||||
				id: undefined,
 | 
			
		||||
				equipmentGroupCode: undefined,
 | 
			
		||||
				equipmentGroupName: undefined,
 | 
			
		||||
			},
 | 
			
		||||
			editVisible: false,
 | 
			
		||||
			editMode: '',
 | 
			
		||||
			drawerBaseInfoRows: [
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '设备分组名称',
 | 
			
		||||
						prop: 'name',
 | 
			
		||||
						rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
						// bind: {
 | 
			
		||||
						// 	disabled: this.editMode == 'detail', // some condition, like detail mode...
 | 
			
		||||
						// }
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '设备分组编码',
 | 
			
		||||
						prop: 'code',
 | 
			
		||||
						// url: '/base/equipment/getCode',
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
			],
 | 
			
		||||
			drawerListProps: [
 | 
			
		||||
				{
 | 
			
		||||
					prop: 'createTime',
 | 
			
		||||
					label: '添加时间',
 | 
			
		||||
					fixed: true,
 | 
			
		||||
					width: 180,
 | 
			
		||||
					filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
 | 
			
		||||
				},
 | 
			
		||||
				{ width: 240, prop: 'code', label: '报警编码' },
 | 
			
		||||
				{
 | 
			
		||||
					width: 100,
 | 
			
		||||
					prop: 'type',
 | 
			
		||||
					label: '报警类型',
 | 
			
		||||
					filter: (val) =>
 | 
			
		||||
						val != null ? ['-', '字符型', '布尔型', '-'][val] : '-',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					width: 90,
 | 
			
		||||
					prop: 'grade',
 | 
			
		||||
					label: '报警级别',
 | 
			
		||||
					filter: publicFormatter(this.DICT_TYPE.EQU_ALARM_LEVEL),
 | 
			
		||||
				},
 | 
			
		||||
				{ width: 180, prop: 'alarmCode', label: '设备报警编码' },
 | 
			
		||||
				{ width: 128, prop: 'plcParamName', label: '参数列名' },
 | 
			
		||||
				{ width: 128, prop: 'alarmContent', label: '报警内容' },
 | 
			
		||||
			],
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	created() {
 | 
			
		||||
@@ -229,7 +341,6 @@ export default {
 | 
			
		||||
		/** 查询列表 */
 | 
			
		||||
		getList() {
 | 
			
		||||
			this.loading = true;
 | 
			
		||||
			_; // 执行查询
 | 
			
		||||
			getEquipmentBindGroupPage(this.queryParams).then((response) => {
 | 
			
		||||
				this.list = response.data.list;
 | 
			
		||||
				this.total = response.data.total;
 | 
			
		||||
@@ -299,6 +410,20 @@ export default {
 | 
			
		||||
				});
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
		// 查看报警
 | 
			
		||||
		handleDetail(row) {
 | 
			
		||||
			const { equipmentId, equipmentName, groupCode, groupId, groupName, id } =
 | 
			
		||||
				row;
 | 
			
		||||
			// 打开抽屉
 | 
			
		||||
			this.editMode = 'detail';
 | 
			
		||||
			this.alarmForm.id = groupId;
 | 
			
		||||
			this.alarmForm.equipmentGroupCode = groupCode;
 | 
			
		||||
			this.alarmForm.equipmentGroupName = groupName;
 | 
			
		||||
			this.editVisible = true;
 | 
			
		||||
			this.$nextTick(() => {
 | 
			
		||||
				this.$refs['drawer'].init();
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
		/** 删除按钮操作 */
 | 
			
		||||
		handleDelete(row) {
 | 
			
		||||
			const id = row.id;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										481
									
								
								src/views/base/equipmentGroup/components/BasicDrawer.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										481
									
								
								src/views/base/equipmentGroup/components/BasicDrawer.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,481 @@
 | 
			
		||||
<!-- 
 | 
			
		||||
    filename: EquipmentDrawer.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-08-22 14:38:56
 | 
			
		||||
    description: 
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<el-drawer
 | 
			
		||||
		:visible="visible"
 | 
			
		||||
		:show-close="false"
 | 
			
		||||
		:wrapper-closable="false"
 | 
			
		||||
		class="drawer"
 | 
			
		||||
		custom-class="mes-drawer"
 | 
			
		||||
		size="60%"
 | 
			
		||||
		@closed="$emit('destroy')">
 | 
			
		||||
		<SmallTitle slot="title">
 | 
			
		||||
			{{
 | 
			
		||||
				mode.includes('detail')
 | 
			
		||||
					? '详情'
 | 
			
		||||
					: mode.includes('edit')
 | 
			
		||||
					? '编辑'
 | 
			
		||||
					: '新增'
 | 
			
		||||
			}}
 | 
			
		||||
		</SmallTitle>
 | 
			
		||||
 | 
			
		||||
		<div class="drawer-body flex">
 | 
			
		||||
			<div class="drawer-body__content">
 | 
			
		||||
				<section v-for="(section, index) in sections" :key="section.key">
 | 
			
		||||
					<SmallTitle v-if="index != 0">{{ section.name }}</SmallTitle>
 | 
			
		||||
 | 
			
		||||
					<div class="form-part" v-if="section.key == 'base'">
 | 
			
		||||
						<el-skeleton v-if="!showForm" animated />
 | 
			
		||||
						<BaseInfoForm
 | 
			
		||||
							key="drawer-dialog-form"
 | 
			
		||||
							v-if="showForm"
 | 
			
		||||
							ref="form"
 | 
			
		||||
							:disabled="mode.includes('detail')"
 | 
			
		||||
							:dataForm="form"
 | 
			
		||||
							:rows="formRows" />
 | 
			
		||||
					</div>
 | 
			
		||||
 | 
			
		||||
					<div v-if="section.key == 'attrs'" style="margin-top: 12px">
 | 
			
		||||
						<base-table
 | 
			
		||||
							v-loading="attrListLoading"
 | 
			
		||||
							:table-props="section.props"
 | 
			
		||||
							:page="attrQuery?.params.pageNo || 1"
 | 
			
		||||
							:limit="attrQuery?.params.pageSize || 10"
 | 
			
		||||
							:table-data="list"
 | 
			
		||||
							:add-button-show="mode.includes('detail') ? null : '添加属性'"
 | 
			
		||||
							@emitButtonClick="handleAddAttr"
 | 
			
		||||
							@emitFun="handleEmitFun">
 | 
			
		||||
							<method-btn
 | 
			
		||||
								v-if="section.tableBtn"
 | 
			
		||||
								slot="handleBtn"
 | 
			
		||||
								label="操作"
 | 
			
		||||
								:method-list="tableBtn"
 | 
			
		||||
								@clickBtn="handleTableBtnClick" />
 | 
			
		||||
						</base-table>
 | 
			
		||||
 | 
			
		||||
						<!-- 分页组件 -->
 | 
			
		||||
						<pagination
 | 
			
		||||
							v-show="total > 0"
 | 
			
		||||
							:total="total"
 | 
			
		||||
							:page.sync="attrQuery.params.pageNo"
 | 
			
		||||
							:limit.sync="attrQuery.params.pageSize"
 | 
			
		||||
							@pagination="getAttrList" />
 | 
			
		||||
					</div>
 | 
			
		||||
				</section>
 | 
			
		||||
			</div>
 | 
			
		||||
 | 
			
		||||
			<div class="drawer-body__footer">
 | 
			
		||||
				<el-button style="" @click="handleCancel">取消</el-button>
 | 
			
		||||
				<el-button v-if="mode == 'detail'" type="primary" @click="toggleEdit">
 | 
			
		||||
					编辑
 | 
			
		||||
				</el-button>
 | 
			
		||||
				<el-button v-else type="primary" @click="handleCancel">确定</el-button>
 | 
			
		||||
				<!-- sections的第二项必须是 属性列表  -->
 | 
			
		||||
				<!-- <el-button
 | 
			
		||||
						v-if="sections[1].allowAdd"
 | 
			
		||||
						type="primary"
 | 
			
		||||
						@click="handleAddAttr">
 | 
			
		||||
						添加属性
 | 
			
		||||
					</el-button> -->
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
 | 
			
		||||
		<!-- 属性对话框 -->
 | 
			
		||||
		<base-dialog
 | 
			
		||||
			v-if="sections[1].allowAdd"
 | 
			
		||||
			:dialogTitle="attrTitle"
 | 
			
		||||
			:dialogVisible="attrFormVisible"
 | 
			
		||||
			width="45%"
 | 
			
		||||
			:append-to-body="true"
 | 
			
		||||
			custom-class="baseDialog"
 | 
			
		||||
			@close="closeAttrForm"
 | 
			
		||||
			@cancel="closeAttrForm"
 | 
			
		||||
			@confirm="submitAttrForm">
 | 
			
		||||
			<DialogForm
 | 
			
		||||
				v-if="attrFormVisible"
 | 
			
		||||
				ref="attrForm"
 | 
			
		||||
				:disabled="mode.includes('detail')"
 | 
			
		||||
				v-model="attrForm"
 | 
			
		||||
				:rows="attrRows" />
 | 
			
		||||
		</base-dialog>
 | 
			
		||||
	</el-drawer>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import BaseInfoForm from '@/components/DialogForm';
 | 
			
		||||
import DialogForm from './dialogForm';
 | 
			
		||||
 | 
			
		||||
const SmallTitle = {
 | 
			
		||||
	name: 'SmallTitle',
 | 
			
		||||
	props: ['size'],
 | 
			
		||||
	data() {
 | 
			
		||||
		return {};
 | 
			
		||||
	},
 | 
			
		||||
	methods: {},
 | 
			
		||||
	render: function (h) {
 | 
			
		||||
		return h(
 | 
			
		||||
			'span',
 | 
			
		||||
			{
 | 
			
		||||
				class: 'small-title',
 | 
			
		||||
				style: {
 | 
			
		||||
					fontSize: '18px',
 | 
			
		||||
					lineHeight:
 | 
			
		||||
						this.size == 'lg' ? '24px' : this.size == 'sm' ? '18px' : '20px',
 | 
			
		||||
					fontWeight: 500,
 | 
			
		||||
					fontFamily: '微软雅黑, Microsoft YaHei, Arial, Helvetica, sans-serif',
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			this.$slots.default
 | 
			
		||||
		);
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	components: { SmallTitle, DialogForm, BaseInfoForm },
 | 
			
		||||
	props: ['sections', 'defaultMode', 'dataId'], // dataId 作为一个通用的存放id的字段
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			mode: '',
 | 
			
		||||
			visible: false,
 | 
			
		||||
			showForm: false,
 | 
			
		||||
			total: 0,
 | 
			
		||||
			form: {},
 | 
			
		||||
			list: [],
 | 
			
		||||
			attrTitle: '',
 | 
			
		||||
			attrForm: {
 | 
			
		||||
				id: null,
 | 
			
		||||
				equipmentGroupId: '',
 | 
			
		||||
				code: '',
 | 
			
		||||
				type: '',
 | 
			
		||||
				grade: '',
 | 
			
		||||
				alarmCode: '',
 | 
			
		||||
				alarmContent: '',
 | 
			
		||||
				plcParamName: '',
 | 
			
		||||
			},
 | 
			
		||||
			attrFormVisible: false,
 | 
			
		||||
			attrRows: [
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '报警编码', // 自动生成
 | 
			
		||||
						prop: 'code',
 | 
			
		||||
						url: '/base/equipment-group-alarm/getCode',
 | 
			
		||||
						rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						select: true,
 | 
			
		||||
						label: '报警类型', // 固定选项
 | 
			
		||||
						prop: 'type',
 | 
			
		||||
						options: [
 | 
			
		||||
							{ label: '布尔型', value: 2 },
 | 
			
		||||
							{ label: '字符型', value: 1 },
 | 
			
		||||
						],
 | 
			
		||||
						rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						select: true,
 | 
			
		||||
						label: '报警级别', // 字典
 | 
			
		||||
						prop: 'grade',
 | 
			
		||||
						options: this.getDictDatas(this.DICT_TYPE.EQU_ALARM_LEVEL),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '设备报警编码', // 对应到设备实际的报警编码
 | 
			
		||||
						prop: 'alarmCode',
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '参数列名', // 在实时数据库的列名
 | 
			
		||||
						prop: 'plcParamName',
 | 
			
		||||
						rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '报警内容',
 | 
			
		||||
						prop: 'alarmContent',
 | 
			
		||||
						rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
			],
 | 
			
		||||
			attrQuery: {
 | 
			
		||||
				params: {
 | 
			
		||||
					pageNo: 1,
 | 
			
		||||
					pageSize: 10,
 | 
			
		||||
				},
 | 
			
		||||
			}, // 属性列表的请求
 | 
			
		||||
			infoQuery: null, // 基本信息的请求
 | 
			
		||||
			attrFormSubmitting: false,
 | 
			
		||||
			attrListLoading: false,
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	computed: {
 | 
			
		||||
		formRows() {
 | 
			
		||||
			return this.sections[0].rows.map((row) => {
 | 
			
		||||
				return row.map((col) => {
 | 
			
		||||
					return {
 | 
			
		||||
						...col,
 | 
			
		||||
						bind: {
 | 
			
		||||
							// 详情 模式下,禁用各种输入
 | 
			
		||||
							// disabled: this.mode == 'detail',
 | 
			
		||||
							disabled: true
 | 
			
		||||
						},
 | 
			
		||||
					};
 | 
			
		||||
				});
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
		tableBtn() {
 | 
			
		||||
			return this.mode == 'detail' ? [] : this.sections[1].tableBtn;
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	mounted() {
 | 
			
		||||
		this.mode = this.defaultMode || 'detail';
 | 
			
		||||
		for (const section of this.sections) {
 | 
			
		||||
			// 请求具体信息
 | 
			
		||||
			if ('url' in section) {
 | 
			
		||||
				const query = {
 | 
			
		||||
					url: section.url,
 | 
			
		||||
					method: section.method || 'get',
 | 
			
		||||
					params: section.queryParams || null,
 | 
			
		||||
					data: section.data || null,
 | 
			
		||||
				};
 | 
			
		||||
				// debugger;
 | 
			
		||||
				this.$axios(query).then(({ data }) => {
 | 
			
		||||
					if (section.key == 'base') {
 | 
			
		||||
						this.form = data;
 | 
			
		||||
						this.showForm = true;
 | 
			
		||||
						this.infoQuery = query;
 | 
			
		||||
					} else if (section.key == 'attrs') {
 | 
			
		||||
						this.attrQuery = query;
 | 
			
		||||
						this.list = data.list;
 | 
			
		||||
						this.total = data.total;
 | 
			
		||||
					}
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		handleTableBtnClick({ type, data }) {
 | 
			
		||||
			switch (type) {
 | 
			
		||||
				case 'edit':
 | 
			
		||||
					this.handleEditAttr(data.id);
 | 
			
		||||
					break;
 | 
			
		||||
				case 'delete':
 | 
			
		||||
					this.handleDeleteAttr(data.id);
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleEmitFun(val) {
 | 
			
		||||
			console.log('handleEmitFun', val);
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		init() {
 | 
			
		||||
			this.visible = true;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		async getAttrList() {
 | 
			
		||||
			this.attrListLoading = true;
 | 
			
		||||
			const res = await this.$axios(this.attrQuery);
 | 
			
		||||
			if (res.code == 0) {
 | 
			
		||||
				this.list = res.data.list;
 | 
			
		||||
				this.total = res.data.total;
 | 
			
		||||
			}
 | 
			
		||||
			this.attrListLoading = false;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 保存表单
 | 
			
		||||
		handleSave() {
 | 
			
		||||
			this.$refs['form'][0].validate(async (valid) => {
 | 
			
		||||
				if (valid) {
 | 
			
		||||
					const isEdit = this.mode == 'edit';
 | 
			
		||||
					await this.$axios({
 | 
			
		||||
						url: this.sections[0][isEdit ? 'urlUpdate' : 'urlCreate'],
 | 
			
		||||
						method: isEdit ? 'put' : 'post',
 | 
			
		||||
						data: this.form,
 | 
			
		||||
					});
 | 
			
		||||
					this.$modal.msgSuccess(`${isEdit ? '更新' : '创建'}成功`);
 | 
			
		||||
					this.visible = false;
 | 
			
		||||
					this.$emit('refreshDataList');
 | 
			
		||||
				}
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleCancel() {
 | 
			
		||||
			this.visible = false;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 开启编辑
 | 
			
		||||
		toggleEdit() {
 | 
			
		||||
			this.mode = 'edit';
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 新增属性
 | 
			
		||||
		handleAddAttr() {
 | 
			
		||||
			if (!this.dataId) return this.$message.error('请先创建设备分组信息');
 | 
			
		||||
			this.attrForm = {
 | 
			
		||||
				id: null,
 | 
			
		||||
				equipmentGroupId: this.dataId,
 | 
			
		||||
				code: '',
 | 
			
		||||
				type: '',
 | 
			
		||||
				grade: '',
 | 
			
		||||
				alarmCode: '',
 | 
			
		||||
				alarmContent: '',
 | 
			
		||||
				plcParamName: '',
 | 
			
		||||
			};
 | 
			
		||||
			this.attrTitle = '添加设备分组报警';
 | 
			
		||||
			this.attrFormVisible = true;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 编辑属性
 | 
			
		||||
		async handleEditAttr(attrId) {
 | 
			
		||||
			const res = await this.$axios({
 | 
			
		||||
				url: this.sections[1].urlDetail,
 | 
			
		||||
				method: 'get',
 | 
			
		||||
				params: { id: attrId },
 | 
			
		||||
			});
 | 
			
		||||
			if (res.code == 0) {
 | 
			
		||||
				this.attrForm = res.data;
 | 
			
		||||
				this.attrTitle = '编辑设备分组报警';
 | 
			
		||||
				this.attrFormVisible = true;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 删除属性
 | 
			
		||||
		handleDeleteAttr(attrId) {
 | 
			
		||||
			this.$confirm('确定删除该分组报警?', '提示', {
 | 
			
		||||
				confirmButtonText: '确定',
 | 
			
		||||
				cancelButtonText: '取消',
 | 
			
		||||
				type: 'warning',
 | 
			
		||||
			})
 | 
			
		||||
				.then(async () => {
 | 
			
		||||
					const res = await this.$axios({
 | 
			
		||||
						url: this.sections[1].urlDelete,
 | 
			
		||||
						method: 'delete',
 | 
			
		||||
						params: { id: attrId },
 | 
			
		||||
					});
 | 
			
		||||
					if (res.code == 0) {
 | 
			
		||||
						this.$message({
 | 
			
		||||
							message: '删除成功',
 | 
			
		||||
							type: 'success',
 | 
			
		||||
							duration: 1500,
 | 
			
		||||
							onClose: () => {
 | 
			
		||||
								this.getAttrList();
 | 
			
		||||
							},
 | 
			
		||||
						});
 | 
			
		||||
					}
 | 
			
		||||
				})
 | 
			
		||||
				.catch(() => {});
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 提交属性表
 | 
			
		||||
		async submitAttrForm() {
 | 
			
		||||
			this.$refs['attrForm'].validate((valid) => {
 | 
			
		||||
				if (!valid) {
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
			});
 | 
			
		||||
			const isEdit = this.attrForm.id != null;
 | 
			
		||||
			this.attrFormSubmitting = true;
 | 
			
		||||
			const res = await this.$axios({
 | 
			
		||||
				url: isEdit ? this.sections[1].urlUpdate : this.sections[1].urlCreate,
 | 
			
		||||
				method: isEdit ? 'put' : 'post',
 | 
			
		||||
				data: this.attrForm,
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
			if (res.code == 0) {
 | 
			
		||||
				this.closeAttrForm();
 | 
			
		||||
				this.$message({
 | 
			
		||||
					message: `${isEdit ? '更新' : '创建'}成功`,
 | 
			
		||||
					type: 'success',
 | 
			
		||||
					duration: 1500,
 | 
			
		||||
					onClose: () => {
 | 
			
		||||
						this.getAttrList();
 | 
			
		||||
					},
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
			this.attrFormSubmitting = false;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		closeAttrForm() {
 | 
			
		||||
			this.attrFormVisible = false;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleClick(raw) {
 | 
			
		||||
			if (raw.type === 'delete') {
 | 
			
		||||
				this.$confirm(`确定删除该报警?`, '提示', {
 | 
			
		||||
					confirmButtonText: '确定',
 | 
			
		||||
					cancelButtonText: '取消',
 | 
			
		||||
					type: 'warning',
 | 
			
		||||
				})
 | 
			
		||||
					.then(() => {
 | 
			
		||||
						deleteProductAttr(raw.data.id).then(({ data }) => {
 | 
			
		||||
							this.$message({
 | 
			
		||||
								message: '操作成功',
 | 
			
		||||
								type: 'success',
 | 
			
		||||
								duration: 1500,
 | 
			
		||||
								onClose: () => {
 | 
			
		||||
									this.getList();
 | 
			
		||||
								},
 | 
			
		||||
							});
 | 
			
		||||
						});
 | 
			
		||||
					})
 | 
			
		||||
					.catch(() => {});
 | 
			
		||||
			} else {
 | 
			
		||||
				this.addNew(raw.data.id);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.drawer >>> .el-drawer {
 | 
			
		||||
	border-radius: 8px 0 0 8px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.drawer >>> .el-drawer__header {
 | 
			
		||||
	margin: 0;
 | 
			
		||||
	padding: 32px 32px 24px;
 | 
			
		||||
	border-bottom: 1px solid #dcdfe6;
 | 
			
		||||
	margin-bottom: 0px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.small-title::before {
 | 
			
		||||
	content: '';
 | 
			
		||||
	display: inline-block;
 | 
			
		||||
	vertical-align: top;
 | 
			
		||||
	width: 4px;
 | 
			
		||||
	height: 22px;
 | 
			
		||||
	border-radius: 1px;
 | 
			
		||||
	margin-right: 8px;
 | 
			
		||||
	background-color: #0b58ff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.drawer-body {
 | 
			
		||||
	display: flex;
 | 
			
		||||
	flex-direction: column;
 | 
			
		||||
	height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.drawer-body__content {
 | 
			
		||||
	flex: 1;
 | 
			
		||||
	/* background: #eee; */
 | 
			
		||||
	padding: 20px 30px;
 | 
			
		||||
	overflow-y: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.drawer-body__footer {
 | 
			
		||||
	display: flex;
 | 
			
		||||
	justify-content: flex-end;
 | 
			
		||||
	padding: 18px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										187
									
								
								src/views/base/equipmentGroup/components/dialogForm.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								src/views/base/equipmentGroup/components/dialogForm.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,187 @@
 | 
			
		||||
<!-- 
 | 
			
		||||
    filename: dialogForm.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-09-11 15:55:13
 | 
			
		||||
    description: DialogForm for equipmentBindSection only
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<el-form
 | 
			
		||||
		ref="form"
 | 
			
		||||
		:model="dataForm"
 | 
			
		||||
		label-width="100px"
 | 
			
		||||
		v-loading="formLoading">
 | 
			
		||||
		<el-row :gutter="20">
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="报警编码"
 | 
			
		||||
					prop="code"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-input
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.code"
 | 
			
		||||
						@change="$emit('update', dataForm)"
 | 
			
		||||
						placeholder="请输入工段排序" />
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
				<!-- 				
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="报警编码"
 | 
			
		||||
					prop="code"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-select
 | 
			
		||||
						v-model="dataForm.code"
 | 
			
		||||
						placeholder="请选择产线"
 | 
			
		||||
						@change="handleProductlineChange">
 | 
			
		||||
						<el-option
 | 
			
		||||
							v-for="opt in productionLineList"
 | 
			
		||||
							:key="opt.value"
 | 
			
		||||
							:label="opt.label"
 | 
			
		||||
							:value="opt.value" />
 | 
			
		||||
					</el-select>
 | 
			
		||||
				</el-form-item> -->
 | 
			
		||||
			</el-col>
 | 
			
		||||
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="报警类型"
 | 
			
		||||
					prop="type"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-select
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.type"
 | 
			
		||||
						placeholder="请选择报警类型"
 | 
			
		||||
						@change="handleTypeChange">
 | 
			
		||||
						<el-option
 | 
			
		||||
							v-for="opt in [
 | 
			
		||||
								{ label: '布尔型', value: 2 },
 | 
			
		||||
								{ label: '字符型', value: 1 },
 | 
			
		||||
							]"
 | 
			
		||||
							:key="opt.value"
 | 
			
		||||
							:label="opt.label"
 | 
			
		||||
							:value="opt.value" />
 | 
			
		||||
					</el-select>
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
			</el-col>
 | 
			
		||||
		</el-row>
 | 
			
		||||
		<el-row :gutter="20">
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="报警级别"
 | 
			
		||||
					prop="grade"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-select
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.grade"
 | 
			
		||||
						placeholder="请选择报警级别"
 | 
			
		||||
						@change="$emit('update', dataForm)">
 | 
			
		||||
						<el-option
 | 
			
		||||
							v-for="opt in getDictDatas(DICT_TYPE.EQU_ALARM_LEVEL)"
 | 
			
		||||
							:key="opt.value"
 | 
			
		||||
							:label="opt.label"
 | 
			
		||||
							:value="opt.value" />
 | 
			
		||||
					</el-select>
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
			</el-col>
 | 
			
		||||
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					v-if="+dataForm.type == 1"
 | 
			
		||||
					label="设备报警编码"
 | 
			
		||||
					prop="alarmCode">
 | 
			
		||||
					<el-input
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.alarmCode"
 | 
			
		||||
						@change="$emit('update', dataForm)"
 | 
			
		||||
						placeholder="请输入设备报警编码" />
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
			</el-col>
 | 
			
		||||
		</el-row>
 | 
			
		||||
		<el-row :gutter="20">
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="参数列名"
 | 
			
		||||
					prop="plcParamName"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-input
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.plcParamName"
 | 
			
		||||
						placeholder="请输入参数列名"
 | 
			
		||||
						@change="$emit('update', dataForm)"></el-input>
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
			</el-col>
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="报警内容"
 | 
			
		||||
					prop="alarmContent"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-input
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.alarmContent"
 | 
			
		||||
						placeholder="请输入报警内容"
 | 
			
		||||
						@change="$emit('update', dataForm)"></el-input>
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
			</el-col>
 | 
			
		||||
		</el-row>
 | 
			
		||||
	</el-form>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'DialogForm',
 | 
			
		||||
	model: {
 | 
			
		||||
		prop: 'dataForm',
 | 
			
		||||
		event: 'update',
 | 
			
		||||
	},
 | 
			
		||||
	emits: ['update'],
 | 
			
		||||
	components: {},
 | 
			
		||||
	props: {
 | 
			
		||||
		dataForm: {
 | 
			
		||||
			type: Object,
 | 
			
		||||
			default: () => ({}),
 | 
			
		||||
		},
 | 
			
		||||
		disabled: {
 | 
			
		||||
			type: Boolean,
 | 
			
		||||
			default: false,
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			formLoading: true,
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	mounted() {
 | 
			
		||||
		this.getCode('/base/equipment-group-alarm/getCode').then((code) => {
 | 
			
		||||
			this.formLoading = false;
 | 
			
		||||
			this.$emit('update', {
 | 
			
		||||
				...this.dataForm,
 | 
			
		||||
				code,
 | 
			
		||||
			});
 | 
			
		||||
		});
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		/** 模拟透传 ref  */
 | 
			
		||||
		validate(cb) {
 | 
			
		||||
			return this.$refs.form.validate(cb);
 | 
			
		||||
		},
 | 
			
		||||
		resetFields(args) {
 | 
			
		||||
			return this.$refs.form.resetFields(args);
 | 
			
		||||
		},
 | 
			
		||||
		async handleTypeChange(id) {
 | 
			
		||||
			// debugger;
 | 
			
		||||
			this.dataForm.alarmCode = '';
 | 
			
		||||
			this.$emit('update', this.dataForm);
 | 
			
		||||
		},
 | 
			
		||||
		async getCode(url) {
 | 
			
		||||
			const response = await this.$axios(url);
 | 
			
		||||
			return response.data;
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="scss">
 | 
			
		||||
.el-date-editor,
 | 
			
		||||
.el-select {
 | 
			
		||||
	width: 100%;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -40,6 +40,57 @@
 | 
			
		||||
			@confirm="submitForm">
 | 
			
		||||
			<DialogForm v-if="open" ref="form" :dataForm="form" :rows="rows" />
 | 
			
		||||
		</base-dialog>
 | 
			
		||||
 | 
			
		||||
		<!-- 抽屉 详情 -->
 | 
			
		||||
		<BasicDrawer
 | 
			
		||||
			v-if="editVisible"
 | 
			
		||||
			ref="drawer"
 | 
			
		||||
			:default-mode="editMode"
 | 
			
		||||
			:data-id="alarmForm.id"
 | 
			
		||||
			:sections="[
 | 
			
		||||
				{
 | 
			
		||||
					name: '基本信息',
 | 
			
		||||
					key: 'base',
 | 
			
		||||
					rows: drawerBaseInfoRows,
 | 
			
		||||
					url: '/base/equipment-group/get',
 | 
			
		||||
					urlUpdate: '/base/equipment-group/update',
 | 
			
		||||
					urlCreate: '/base/equipment-group/create',
 | 
			
		||||
					queryParams: { id: alarmForm.id },
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					name: '属性列表',
 | 
			
		||||
					key: 'attrs',
 | 
			
		||||
					props: drawerListProps,
 | 
			
		||||
					url: '/base/equipment-group-alarm/page',
 | 
			
		||||
					urlCreate: '/base/equipment-group-alarm/create',
 | 
			
		||||
					urlUpdate: '/base/equipment-group-alarm/update',
 | 
			
		||||
					urlDelete: '/base/equipment-group-alarm/delete',
 | 
			
		||||
					urlDetail: '/base/equipment-group-alarm/get',
 | 
			
		||||
					queryParams: {
 | 
			
		||||
						equipmentGroupId: alarmForm.id,
 | 
			
		||||
						pageNo: 1,
 | 
			
		||||
						pageSize: 10,
 | 
			
		||||
					},
 | 
			
		||||
					tableBtn: [
 | 
			
		||||
						this.$auth.hasPermi('base:equipment-group:update')
 | 
			
		||||
							? {
 | 
			
		||||
									type: 'edit',
 | 
			
		||||
									btnName: '修改',
 | 
			
		||||
							  }
 | 
			
		||||
							: undefined,
 | 
			
		||||
						this.$auth.hasPermi('base:equipment-group:delete')
 | 
			
		||||
							? {
 | 
			
		||||
									type: 'delete',
 | 
			
		||||
									btnName: '删除',
 | 
			
		||||
							  }
 | 
			
		||||
							: undefined,
 | 
			
		||||
					].filter((v) => v),
 | 
			
		||||
					allowAdd: true,
 | 
			
		||||
				},
 | 
			
		||||
			]"
 | 
			
		||||
			@refreshDataList="getList"
 | 
			
		||||
			@cancel="editVisible = false"
 | 
			
		||||
			@destroy="editVisible = false" />
 | 
			
		||||
	</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -53,17 +104,27 @@ import {
 | 
			
		||||
	exportEquipmentGroupExcel,
 | 
			
		||||
} from '@/api/base/equipmentGroup';
 | 
			
		||||
import moment from 'moment';
 | 
			
		||||
import { publicFormatter } from '@/utils/dict';
 | 
			
		||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
 | 
			
		||||
import { getAccessToken } from '@/utils/auth';
 | 
			
		||||
// import { getAccessToken } from '@/utils/auth';
 | 
			
		||||
import BasicDrawer from './components/BasicDrawer.vue';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'EquipmentGroup',
 | 
			
		||||
	mixins: [basicPageMixin],
 | 
			
		||||
	components: {},
 | 
			
		||||
	components: { BasicDrawer },
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			editVisible: false,
 | 
			
		||||
			editMode: '',
 | 
			
		||||
			searchBarKeys: ['name', 'code'],
 | 
			
		||||
			tableBtn: [
 | 
			
		||||
				this.$auth.hasPermi('base:equipment-group:update')
 | 
			
		||||
					? {
 | 
			
		||||
							type: 'detail',
 | 
			
		||||
							btnName: '查看报警',
 | 
			
		||||
					  }
 | 
			
		||||
					: undefined,
 | 
			
		||||
				this.$auth.hasPermi('base:equipment-group:update')
 | 
			
		||||
					? {
 | 
			
		||||
							type: 'edit',
 | 
			
		||||
@@ -88,34 +149,84 @@ export default {
 | 
			
		||||
				{ prop: 'name', label: '设备分组名称' },
 | 
			
		||||
				{ prop: 'code', label: '设备分组编码' },
 | 
			
		||||
				{ prop: 'remark', label: '备注' },
 | 
			
		||||
				{
 | 
			
		||||
					_action: 'equipment-group-show-alert',
 | 
			
		||||
					label: '报警',
 | 
			
		||||
					subcomponent: {
 | 
			
		||||
						props: ['injectData'],
 | 
			
		||||
						render: function (h) {
 | 
			
		||||
							const _this = this;
 | 
			
		||||
							return h(
 | 
			
		||||
								'el-button',
 | 
			
		||||
								{
 | 
			
		||||
									props: { type: 'text' },
 | 
			
		||||
									on: {
 | 
			
		||||
										click: function () {
 | 
			
		||||
											console.log('inejctdata', _this.injectData);
 | 
			
		||||
											_this.$emit('emitData', {
 | 
			
		||||
												action: _this.injectData._action,
 | 
			
		||||
												// value: _this.injectData.id,
 | 
			
		||||
												value: _this.injectData,
 | 
			
		||||
											});
 | 
			
		||||
										},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
								'查看报警'
 | 
			
		||||
							);
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				// {
 | 
			
		||||
				// 	_action: 'equipment-group-show-alert',
 | 
			
		||||
				// 	label: '报警',
 | 
			
		||||
				// 	subcomponent: {
 | 
			
		||||
				// 		props: ['injectData'],
 | 
			
		||||
				// 		render: function (h) {
 | 
			
		||||
				// 			const _this = this;
 | 
			
		||||
				// 			return h(
 | 
			
		||||
				// 				'el-button',
 | 
			
		||||
				// 				{
 | 
			
		||||
				// 					props: { type: 'text' },
 | 
			
		||||
				// 					on: {
 | 
			
		||||
				// 						click: function () {
 | 
			
		||||
				// 							console.log('inejctdata', _this.injectData);
 | 
			
		||||
				// 							_this.$emit('emitData', {
 | 
			
		||||
				// 								action: _this.injectData._action,
 | 
			
		||||
				// 								// value: _this.injectData.id,
 | 
			
		||||
				// 								value: _this.injectData,
 | 
			
		||||
				// 							});
 | 
			
		||||
				// 						},
 | 
			
		||||
				// 					},
 | 
			
		||||
				// 				},
 | 
			
		||||
				// 				'查看报警'
 | 
			
		||||
				// 			);
 | 
			
		||||
				// 		},
 | 
			
		||||
				// 	},
 | 
			
		||||
				// },
 | 
			
		||||
			],
 | 
			
		||||
			drawerBaseInfoRows: [
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '设备分组名称',
 | 
			
		||||
						prop: 'name',
 | 
			
		||||
						rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
						// bind: {
 | 
			
		||||
						// 	disabled: this.editMode == 'detail', // some condition, like detail mode...
 | 
			
		||||
						// }
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '设备分组编码',
 | 
			
		||||
						prop: 'code',
 | 
			
		||||
						// url: '/base/equipment/getCode',
 | 
			
		||||
					}
 | 
			
		||||
				]
 | 
			
		||||
			],
 | 
			
		||||
			drawerListProps: [
 | 
			
		||||
				{
 | 
			
		||||
					prop: 'createTime',
 | 
			
		||||
					label: '添加时间',
 | 
			
		||||
					fixed: true,
 | 
			
		||||
					width: 180,
 | 
			
		||||
					filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
 | 
			
		||||
				},
 | 
			
		||||
				{ width: 240, prop: 'code', label: '报警编码' },
 | 
			
		||||
				{
 | 
			
		||||
					width: 100,
 | 
			
		||||
					prop: 'type',
 | 
			
		||||
					label: '报警类型',
 | 
			
		||||
					filter: (val) =>
 | 
			
		||||
						val != null ? ['-', '字符型', '布尔型', '-'][val] : '-',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					width: 90,
 | 
			
		||||
					prop: 'grade',
 | 
			
		||||
					label: '报警级别',
 | 
			
		||||
					filter: publicFormatter(this.DICT_TYPE.EQU_ALARM_LEVEL),
 | 
			
		||||
				},
 | 
			
		||||
				{ width: 180, prop: 'alarmCode', label: '设备报警编码' },
 | 
			
		||||
				{ width: 128, prop: 'plcParamName', label: '参数列名' },
 | 
			
		||||
				{ width: 128, prop: 'alarmContent', label: '报警内容' },
 | 
			
		||||
			],
 | 
			
		||||
			alarmForm: {
 | 
			
		||||
				id: undefined,
 | 
			
		||||
				equipmentGroupCode: undefined,
 | 
			
		||||
				equipmentGroupName: undefined,
 | 
			
		||||
			},
 | 
			
		||||
			searchBarFormConfig: [
 | 
			
		||||
				{
 | 
			
		||||
					type: 'input',
 | 
			
		||||
@@ -299,6 +410,20 @@ export default {
 | 
			
		||||
				});
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
		// 查看报警
 | 
			
		||||
		handleDetail(row) {
 | 
			
		||||
			// debugger;
 | 
			
		||||
			const { id, code, name, createTime } = row;
 | 
			
		||||
			// 打开抽屉
 | 
			
		||||
			this.editMode = 'detail';
 | 
			
		||||
			this.alarmForm.id = id;
 | 
			
		||||
			this.alarmForm.equipmentGroupCode = code;
 | 
			
		||||
			this.alarmForm.equipmentGroupName = name;
 | 
			
		||||
			this.editVisible = true;
 | 
			
		||||
			this.$nextTick(() => {
 | 
			
		||||
				this.$refs['drawer'].init();
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
		/** 删除按钮操作 */
 | 
			
		||||
		handleDelete(row) {
 | 
			
		||||
			const id = row.id;
 | 
			
		||||
 
 | 
			
		||||
@@ -18,24 +18,25 @@
 | 
			
		||||
					prop="code"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-input
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.code"
 | 
			
		||||
						@change="$emit('update', dataForm)"
 | 
			
		||||
						placeholder="请输入工段排序" />
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
				<!-- 				
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="报警编码"
 | 
			
		||||
					prop="code"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-select
 | 
			
		||||
						<el-form-item
 | 
			
		||||
						label="报警编码"
 | 
			
		||||
						prop="code"
 | 
			
		||||
						:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
						<el-select
 | 
			
		||||
						v-model="dataForm.code"
 | 
			
		||||
						placeholder="请选择产线"
 | 
			
		||||
						@change="handleProductlineChange">
 | 
			
		||||
						<el-option
 | 
			
		||||
							v-for="opt in productionLineList"
 | 
			
		||||
							:key="opt.value"
 | 
			
		||||
							:label="opt.label"
 | 
			
		||||
							:value="opt.value" />
 | 
			
		||||
						v-for="opt in productionLineList"
 | 
			
		||||
						:key="opt.value"
 | 
			
		||||
						:label="opt.label"
 | 
			
		||||
						:value="opt.value" />
 | 
			
		||||
					</el-select>
 | 
			
		||||
				</el-form-item> -->
 | 
			
		||||
			</el-col>
 | 
			
		||||
@@ -47,6 +48,7 @@
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-select
 | 
			
		||||
						v-model="dataForm.type"
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						placeholder="请选择报警类型"
 | 
			
		||||
						@change="$emit('update', dataForm)">
 | 
			
		||||
						<el-option
 | 
			
		||||
@@ -68,6 +70,7 @@
 | 
			
		||||
					prop="grade"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-select
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.grade"
 | 
			
		||||
						placeholder="请选择报警级别"
 | 
			
		||||
						@change="$emit('update', dataForm)">
 | 
			
		||||
@@ -86,6 +89,7 @@
 | 
			
		||||
					label="设备报警编码"
 | 
			
		||||
					prop="alarmCode">
 | 
			
		||||
					<el-input
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.alarmCode"
 | 
			
		||||
						@change="$emit('update', dataForm)"
 | 
			
		||||
						placeholder="请输入设备报警编码" />
 | 
			
		||||
@@ -99,6 +103,7 @@
 | 
			
		||||
					prop="plcParamName"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-input
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.plcParamName"
 | 
			
		||||
						placeholder="请输入参数列名"
 | 
			
		||||
						@change="$emit('update', dataForm)"></el-input>
 | 
			
		||||
@@ -110,6 +115,7 @@
 | 
			
		||||
					prop="alarmContent"
 | 
			
		||||
					:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
 | 
			
		||||
					<el-input
 | 
			
		||||
						:disabled="disabled"
 | 
			
		||||
						v-model="dataForm.alarmContent"
 | 
			
		||||
						placeholder="请输入报警内容"
 | 
			
		||||
						@change="$emit('update', dataForm)"></el-input>
 | 
			
		||||
@@ -133,6 +139,10 @@ export default {
 | 
			
		||||
			type: Object,
 | 
			
		||||
			default: () => ({}),
 | 
			
		||||
		},
 | 
			
		||||
		disabled: {
 | 
			
		||||
			type: Boolean,
 | 
			
		||||
			default: false,
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										531
									
								
								src/views/base/equipmentPlcConnect/components/BasicDrawer.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										531
									
								
								src/views/base/equipmentPlcConnect/components/BasicDrawer.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,531 @@
 | 
			
		||||
<!-- 
 | 
			
		||||
    filename: EquipmentDrawer.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-08-22 14:38:56
 | 
			
		||||
    description: 
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<el-drawer
 | 
			
		||||
		:visible="visible"
 | 
			
		||||
		:show-close="false"
 | 
			
		||||
		:wrapper-closable="false"
 | 
			
		||||
		class="drawer"
 | 
			
		||||
		custom-class="mes-drawer"
 | 
			
		||||
		size="60%"
 | 
			
		||||
		@closed="$emit('destroy')">
 | 
			
		||||
		<SmallTitle slot="title">
 | 
			
		||||
			{{
 | 
			
		||||
				mode.includes('detail')
 | 
			
		||||
					? '详情'
 | 
			
		||||
					: mode.includes('edit')
 | 
			
		||||
					? '编辑'
 | 
			
		||||
					: '新增'
 | 
			
		||||
			}}
 | 
			
		||||
		</SmallTitle>
 | 
			
		||||
 | 
			
		||||
		<div class="drawer-body flex">
 | 
			
		||||
			<div class="drawer-body__content">
 | 
			
		||||
				<section v-for="(section, index) in sections" :key="section.key">
 | 
			
		||||
					<SmallTitle v-if="index != 0">{{ section.name }}</SmallTitle>
 | 
			
		||||
 | 
			
		||||
					<div class="form-part" v-if="section.key == 'base'">
 | 
			
		||||
						<el-skeleton v-if="!showForm" animated />
 | 
			
		||||
						<BaseInfoForm
 | 
			
		||||
							key="drawer-dialog-form"
 | 
			
		||||
							v-if="showForm"
 | 
			
		||||
							ref="form"
 | 
			
		||||
							:disabled="mode.includes('detail')"
 | 
			
		||||
							:dataForm="form"
 | 
			
		||||
							:rows="formRows" />
 | 
			
		||||
					</div>
 | 
			
		||||
 | 
			
		||||
					<div v-if="section.key == 'attrs'" style="margin-top: 12px">
 | 
			
		||||
						<base-table
 | 
			
		||||
							v-loading="attrListLoading"
 | 
			
		||||
							:table-props="section.props"
 | 
			
		||||
							:page="attrQuery?.params.pageNo || 1"
 | 
			
		||||
							:limit="attrQuery?.params.pageSize || 10"
 | 
			
		||||
							:table-data="list"
 | 
			
		||||
							:add-button-show="mode.includes('detail') ? null : '添加属性'"
 | 
			
		||||
							@emitButtonClick="handleAddAttr"
 | 
			
		||||
							@emitFun="handleEmitFun">
 | 
			
		||||
							<method-btn
 | 
			
		||||
								v-if="section.tableBtn"
 | 
			
		||||
								slot="handleBtn"
 | 
			
		||||
								label="操作"
 | 
			
		||||
								:method-list="tableBtn"
 | 
			
		||||
								@clickBtn="handleTableBtnClick" />
 | 
			
		||||
						</base-table>
 | 
			
		||||
 | 
			
		||||
						<!-- 分页组件 -->
 | 
			
		||||
						<pagination
 | 
			
		||||
							v-show="total > 0"
 | 
			
		||||
							:total="total"
 | 
			
		||||
							:page.sync="attrQuery.params.pageNo"
 | 
			
		||||
							:limit.sync="attrQuery.params.pageSize"
 | 
			
		||||
							@pagination="getAttrList" />
 | 
			
		||||
					</div>
 | 
			
		||||
				</section>
 | 
			
		||||
			</div>
 | 
			
		||||
 | 
			
		||||
			<div class="drawer-body__footer">
 | 
			
		||||
				<el-button style="" @click="handleCancel">取消</el-button>
 | 
			
		||||
				<el-button v-if="mode == 'detail'" type="primary" @click="toggleEdit">
 | 
			
		||||
					编辑
 | 
			
		||||
				</el-button>
 | 
			
		||||
				<el-button v-else type="primary" @click="handleCancel">确定</el-button>
 | 
			
		||||
				<!-- sections的第二项必须是 属性列表  -->
 | 
			
		||||
				<!-- <el-button
 | 
			
		||||
						v-if="sections[1].allowAdd"
 | 
			
		||||
						type="primary"
 | 
			
		||||
						@click="handleAddAttr">
 | 
			
		||||
						添加属性
 | 
			
		||||
					</el-button> -->
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
 | 
			
		||||
		<!-- 属性对话框 -->
 | 
			
		||||
		<base-dialog
 | 
			
		||||
			v-if="sections[1].allowAdd"
 | 
			
		||||
			:dialogTitle="attrTitle"
 | 
			
		||||
			:dialogVisible="attrFormVisible"
 | 
			
		||||
			width="45%"
 | 
			
		||||
			:append-to-body="true"
 | 
			
		||||
			custom-class="baseDialog"
 | 
			
		||||
			@close="closeAttrForm"
 | 
			
		||||
			@cancel="closeAttrForm"
 | 
			
		||||
			@confirm="submitAttrForm">
 | 
			
		||||
			<DialogForm
 | 
			
		||||
				v-if="attrFormVisible"
 | 
			
		||||
				ref="attrForm"
 | 
			
		||||
				:disabled="mode.includes('detail')"
 | 
			
		||||
				v-model="attrForm"
 | 
			
		||||
				:rows="attrRows" />
 | 
			
		||||
		</base-dialog>
 | 
			
		||||
	</el-drawer>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import BaseInfoForm from '@/components/DialogForm';
 | 
			
		||||
 | 
			
		||||
const SmallTitle = {
 | 
			
		||||
	name: 'SmallTitle',
 | 
			
		||||
	props: ['size'],
 | 
			
		||||
	data() {
 | 
			
		||||
		return {};
 | 
			
		||||
	},
 | 
			
		||||
	methods: {},
 | 
			
		||||
	render: function (h) {
 | 
			
		||||
		return h(
 | 
			
		||||
			'span',
 | 
			
		||||
			{
 | 
			
		||||
				class: 'small-title',
 | 
			
		||||
				style: {
 | 
			
		||||
					fontSize: '18px',
 | 
			
		||||
					lineHeight:
 | 
			
		||||
						this.size == 'lg' ? '24px' : this.size == 'sm' ? '18px' : '20px',
 | 
			
		||||
					fontWeight: 500,
 | 
			
		||||
					fontFamily: '微软雅黑, Microsoft YaHei, Arial, Helvetica, sans-serif',
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			this.$slots.default
 | 
			
		||||
		);
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	components: { SmallTitle, DialogForm: BaseInfoForm, BaseInfoForm },
 | 
			
		||||
	props: ['sections', 'defaultMode', 'infoData'],
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			mode: '',
 | 
			
		||||
			visible: false,
 | 
			
		||||
			showForm: false,
 | 
			
		||||
			total: 0,
 | 
			
		||||
			form: {},
 | 
			
		||||
			list: [],
 | 
			
		||||
			attrTitle: '',
 | 
			
		||||
			attrForm: {
 | 
			
		||||
				id: null,
 | 
			
		||||
				name: '',
 | 
			
		||||
				plcParamName: '',
 | 
			
		||||
				unit: '',
 | 
			
		||||
				collection: '',
 | 
			
		||||
				minValue: '',
 | 
			
		||||
				maxValue: '',
 | 
			
		||||
				defaultValue: '',
 | 
			
		||||
				description: '',
 | 
			
		||||
				remark: '',
 | 
			
		||||
				alarmContent: '',
 | 
			
		||||
			},
 | 
			
		||||
			attrFormVisible: false,
 | 
			
		||||
			attrRows: [
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '参数列名',
 | 
			
		||||
						prop: 'plcParamName',
 | 
			
		||||
						rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '参数名称',
 | 
			
		||||
						prop: 'name',
 | 
			
		||||
						rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						select: true,
 | 
			
		||||
						label: '单位',
 | 
			
		||||
						prop: 'unit',
 | 
			
		||||
						options: this.getDictDatas(this.DICT_TYPE.UNIT_DICT),
 | 
			
		||||
						// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						switch: true,
 | 
			
		||||
						label: '是否采集',
 | 
			
		||||
						prop: 'collection',
 | 
			
		||||
						bind: {
 | 
			
		||||
							'active-value': 1,
 | 
			
		||||
							'inactive-value': 0,
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '最小值',
 | 
			
		||||
						prop: 'minValue',
 | 
			
		||||
						rules: [
 | 
			
		||||
							{
 | 
			
		||||
								type: 'number',
 | 
			
		||||
								message: '请输入正确的数字',
 | 
			
		||||
								trigger: 'change',
 | 
			
		||||
								transform: (val) => Number(val),
 | 
			
		||||
							},
 | 
			
		||||
						],
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '最大值',
 | 
			
		||||
						prop: 'maxValue',
 | 
			
		||||
						rules: [
 | 
			
		||||
							{
 | 
			
		||||
								required: false,
 | 
			
		||||
							},
 | 
			
		||||
							{
 | 
			
		||||
								type: 'number',
 | 
			
		||||
								message: '请输入正确的数字',
 | 
			
		||||
								trigger: 'change',
 | 
			
		||||
								transform: (val) => Number(val),
 | 
			
		||||
							},
 | 
			
		||||
						],
 | 
			
		||||
						// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '标准值',
 | 
			
		||||
						prop: 'defaultValue',
 | 
			
		||||
						// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '描述',
 | 
			
		||||
						prop: 'description',
 | 
			
		||||
						// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '备注',
 | 
			
		||||
						prop: 'remark',
 | 
			
		||||
						// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
			],
 | 
			
		||||
			attrQuery: {
 | 
			
		||||
				params: {
 | 
			
		||||
					pageNo: 1,
 | 
			
		||||
					pageSize: 10,
 | 
			
		||||
				},
 | 
			
		||||
			}, // 属性列表的请求
 | 
			
		||||
			infoQuery: null, // 基本信息的请求
 | 
			
		||||
			attrFormSubmitting: false,
 | 
			
		||||
			attrListLoading: false,
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	computed: {
 | 
			
		||||
		formRows() {
 | 
			
		||||
			return this.sections[0].rows.map((row) => {
 | 
			
		||||
				return row.map((col) => {
 | 
			
		||||
					return {
 | 
			
		||||
						...col,
 | 
			
		||||
						bind: {
 | 
			
		||||
							// 详情 模式下,禁用各种输入
 | 
			
		||||
							// disabled: this.mode == 'detail',
 | 
			
		||||
							disabled: true,
 | 
			
		||||
						},
 | 
			
		||||
					};
 | 
			
		||||
				});
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
		tableBtn() {
 | 
			
		||||
			return this.mode == 'detail' ? [] : this.sections[1].tableBtn;
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	mounted() {
 | 
			
		||||
		this.mode = this.defaultMode || 'detail';
 | 
			
		||||
		for (const section of this.sections) {
 | 
			
		||||
			// 请求具体信息
 | 
			
		||||
			if ('url' in section) {
 | 
			
		||||
				const query = {
 | 
			
		||||
					url: section.url,
 | 
			
		||||
					method: section.method || 'get',
 | 
			
		||||
					params: section.queryParams || null,
 | 
			
		||||
					data: section.data || null,
 | 
			
		||||
				};
 | 
			
		||||
				// debugger;
 | 
			
		||||
				this.$axios(query).then(({ data }) => {
 | 
			
		||||
					if (section.key == 'base') {
 | 
			
		||||
						this.form = data;
 | 
			
		||||
						this.showForm = true;
 | 
			
		||||
						this.infoQuery = query;
 | 
			
		||||
					} else if (section.key == 'attrs') {
 | 
			
		||||
						this.attrQuery = query;
 | 
			
		||||
						this.list = data.list;
 | 
			
		||||
						this.total = data.total;
 | 
			
		||||
					}
 | 
			
		||||
				});
 | 
			
		||||
			} else if (section.key == 'base') {
 | 
			
		||||
				this.form = this.infoData;
 | 
			
		||||
				this.showForm = true;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		handleTableBtnClick({ type, data }) {
 | 
			
		||||
			switch (type) {
 | 
			
		||||
				case 'edit':
 | 
			
		||||
					this.handleEditAttr(data.id);
 | 
			
		||||
					break;
 | 
			
		||||
				case 'delete':
 | 
			
		||||
					this.handleDeleteAttr(data.id);
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleEmitFun(val) {
 | 
			
		||||
			console.log('handleEmitFun', val);
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		init() {
 | 
			
		||||
			this.visible = true;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		async getAttrList() {
 | 
			
		||||
			this.attrListLoading = true;
 | 
			
		||||
			const res = await this.$axios(this.attrQuery);
 | 
			
		||||
			if (res.code == 0) {
 | 
			
		||||
				this.list = res.data.list;
 | 
			
		||||
				this.total = res.data.total;
 | 
			
		||||
			}
 | 
			
		||||
			this.attrListLoading = false;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 保存表单
 | 
			
		||||
		handleSave() {
 | 
			
		||||
			this.$refs['form'][0].validate(async (valid) => {
 | 
			
		||||
				if (valid) {
 | 
			
		||||
					const isEdit = this.mode == 'edit';
 | 
			
		||||
					await this.$axios({
 | 
			
		||||
						url: this.sections[0][isEdit ? 'urlUpdate' : 'urlCreate'],
 | 
			
		||||
						method: isEdit ? 'put' : 'post',
 | 
			
		||||
						data: this.form,
 | 
			
		||||
					});
 | 
			
		||||
					this.$modal.msgSuccess(`${isEdit ? '更新' : '创建'}成功`);
 | 
			
		||||
					this.visible = false;
 | 
			
		||||
					this.$emit('refreshDataList');
 | 
			
		||||
				}
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleCancel() {
 | 
			
		||||
			this.visible = false;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 开启编辑
 | 
			
		||||
		toggleEdit() {
 | 
			
		||||
			this.mode = 'edit';
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 新增属性
 | 
			
		||||
		handleAddAttr() {
 | 
			
		||||
			this.attrForm = {
 | 
			
		||||
				id: null,
 | 
			
		||||
				name: '',
 | 
			
		||||
				plcParamName: '',
 | 
			
		||||
				unit: '',
 | 
			
		||||
				collection: '',
 | 
			
		||||
				minValue: '',
 | 
			
		||||
				maxValue: '',
 | 
			
		||||
				defaultValue: '',
 | 
			
		||||
				description: '',
 | 
			
		||||
				remark: '',
 | 
			
		||||
				alarmContent: '',
 | 
			
		||||
			};
 | 
			
		||||
			this.attrTitle = '添加设备绑定信息';
 | 
			
		||||
			this.attrFormVisible = true;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 编辑属性
 | 
			
		||||
		async handleEditAttr(attrId) {
 | 
			
		||||
			const res = await this.$axios({
 | 
			
		||||
				url: this.sections[1].urlDetail,
 | 
			
		||||
				method: 'get',
 | 
			
		||||
				params: { id: attrId },
 | 
			
		||||
			});
 | 
			
		||||
			if (res.code == 0) {
 | 
			
		||||
				this.attrForm = res.data;
 | 
			
		||||
				this.attrTitle = '编辑设备绑定信息';
 | 
			
		||||
				this.attrFormVisible = true;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 删除属性
 | 
			
		||||
		handleDeleteAttr(attrId) {
 | 
			
		||||
			this.$confirm('确定删除该分组报警?', '提示', {
 | 
			
		||||
				confirmButtonText: '确定',
 | 
			
		||||
				cancelButtonText: '取消',
 | 
			
		||||
				type: 'warning',
 | 
			
		||||
			})
 | 
			
		||||
				.then(async () => {
 | 
			
		||||
					const res = await this.$axios({
 | 
			
		||||
						url: this.sections[1].urlDelete,
 | 
			
		||||
						method: 'delete',
 | 
			
		||||
						params: { id: attrId },
 | 
			
		||||
					});
 | 
			
		||||
					if (res.code == 0) {
 | 
			
		||||
						this.$message({
 | 
			
		||||
							message: '删除成功',
 | 
			
		||||
							type: 'success',
 | 
			
		||||
							duration: 1500,
 | 
			
		||||
							onClose: () => {
 | 
			
		||||
								this.getAttrList();
 | 
			
		||||
							},
 | 
			
		||||
						});
 | 
			
		||||
					}
 | 
			
		||||
				})
 | 
			
		||||
				.catch(() => {});
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 提交属性表
 | 
			
		||||
		async submitAttrForm() {
 | 
			
		||||
			this.$refs['attrForm'].validate((valid) => {
 | 
			
		||||
				if (!valid) {
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
			});
 | 
			
		||||
			const isEdit = this.attrForm.id != null;
 | 
			
		||||
			this.attrFormSubmitting = true;
 | 
			
		||||
			const res = await this.$axios({
 | 
			
		||||
				url: isEdit ? this.sections[1].urlUpdate : this.sections[1].urlCreate,
 | 
			
		||||
				method: isEdit ? 'put' : 'post',
 | 
			
		||||
				data: {
 | 
			
		||||
					...this.attrForm,
 | 
			
		||||
					connectId: this.infoData.id
 | 
			
		||||
				},
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
			if (res.code == 0) {
 | 
			
		||||
				this.closeAttrForm();
 | 
			
		||||
				this.$message({
 | 
			
		||||
					message: `${isEdit ? '更新' : '创建'}成功`,
 | 
			
		||||
					type: 'success',
 | 
			
		||||
					duration: 1500,
 | 
			
		||||
					onClose: () => {
 | 
			
		||||
						this.getAttrList();
 | 
			
		||||
					},
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
			this.attrFormSubmitting = false;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		closeAttrForm() {
 | 
			
		||||
			this.attrFormVisible = false;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleClick(raw) {
 | 
			
		||||
			if (raw.type === 'delete') {
 | 
			
		||||
				this.$confirm(`确定删除该报警?`, '提示', {
 | 
			
		||||
					confirmButtonText: '确定',
 | 
			
		||||
					cancelButtonText: '取消',
 | 
			
		||||
					type: 'warning',
 | 
			
		||||
				})
 | 
			
		||||
					.then(() => {
 | 
			
		||||
						deleteProductAttr(raw.data.id).then(({ data }) => {
 | 
			
		||||
							this.$message({
 | 
			
		||||
								message: '操作成功',
 | 
			
		||||
								type: 'success',
 | 
			
		||||
								duration: 1500,
 | 
			
		||||
								onClose: () => {
 | 
			
		||||
									this.getList();
 | 
			
		||||
								},
 | 
			
		||||
							});
 | 
			
		||||
						});
 | 
			
		||||
					})
 | 
			
		||||
					.catch(() => {});
 | 
			
		||||
			} else {
 | 
			
		||||
				this.addNew(raw.data.id);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.drawer >>> .el-drawer {
 | 
			
		||||
	border-radius: 8px 0 0 8px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.drawer >>> .el-drawer__header {
 | 
			
		||||
	margin: 0;
 | 
			
		||||
	padding: 32px 32px 24px;
 | 
			
		||||
	border-bottom: 1px solid #dcdfe6;
 | 
			
		||||
	margin-bottom: 0px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.small-title::before {
 | 
			
		||||
	content: '';
 | 
			
		||||
	display: inline-block;
 | 
			
		||||
	vertical-align: top;
 | 
			
		||||
	width: 4px;
 | 
			
		||||
	height: 22px;
 | 
			
		||||
	border-radius: 1px;
 | 
			
		||||
	margin-right: 8px;
 | 
			
		||||
	background-color: #0b58ff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.drawer-body {
 | 
			
		||||
	display: flex;
 | 
			
		||||
	flex-direction: column;
 | 
			
		||||
	height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.drawer-body__content {
 | 
			
		||||
	flex: 1;
 | 
			
		||||
	/* background: #eee; */
 | 
			
		||||
	padding: 20px 30px;
 | 
			
		||||
	overflow-y: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.drawer-body__footer {
 | 
			
		||||
	display: flex;
 | 
			
		||||
	justify-content: flex-end;
 | 
			
		||||
	padding: 18px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -40,6 +40,53 @@
 | 
			
		||||
			@confirm="submitForm">
 | 
			
		||||
			<DialogForm v-if="open" ref="form" :dataForm="form" :rows="rows" />
 | 
			
		||||
		</base-dialog>
 | 
			
		||||
 | 
			
		||||
		<!-- 抽屉 详情 -->
 | 
			
		||||
		<BasicDrawer
 | 
			
		||||
			v-if="editVisible"
 | 
			
		||||
			ref="drawer"
 | 
			
		||||
			:default-mode="editMode"
 | 
			
		||||
			:info-data="alarmForm"
 | 
			
		||||
			:sections="[
 | 
			
		||||
				{
 | 
			
		||||
					name: '基本信息',
 | 
			
		||||
					key: 'base',
 | 
			
		||||
					rows: drawerBaseInfoRows,
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					name: '属性列表',
 | 
			
		||||
					key: 'attrs',
 | 
			
		||||
					props: drawerListProps,
 | 
			
		||||
					url: '/base/equipment-plc-param/page',
 | 
			
		||||
					urlCreate: '/base/equipment-plc-param/create',
 | 
			
		||||
					urlUpdate: '/base/equipment-plc-param/update',
 | 
			
		||||
					urlDelete: '/base/equipment-plc-param/delete',
 | 
			
		||||
					urlDetail: '/base/equipment-plc-param/get',
 | 
			
		||||
					queryParams: {
 | 
			
		||||
						connectId: alarmForm.id,
 | 
			
		||||
						pageNo: 1,
 | 
			
		||||
						pageSize: 10,
 | 
			
		||||
					},
 | 
			
		||||
					tableBtn: [
 | 
			
		||||
						this.$auth.hasPermi('base:equipment-plc-param:update')
 | 
			
		||||
							? {
 | 
			
		||||
									type: 'edit',
 | 
			
		||||
									btnName: '修改',
 | 
			
		||||
							  }
 | 
			
		||||
							: undefined,
 | 
			
		||||
						this.$auth.hasPermi('base:equipment-plc-param:delete')
 | 
			
		||||
							? {
 | 
			
		||||
									type: 'delete',
 | 
			
		||||
									btnName: '删除',
 | 
			
		||||
							  }
 | 
			
		||||
							: undefined,
 | 
			
		||||
					].filter((v) => v),
 | 
			
		||||
					allowAdd: true,
 | 
			
		||||
				},
 | 
			
		||||
			]"
 | 
			
		||||
			@refreshDataList="getList"
 | 
			
		||||
			@cancel="editVisible = false"
 | 
			
		||||
			@destroy="editVisible = false" />
 | 
			
		||||
	</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -55,11 +102,13 @@ import {
 | 
			
		||||
import moment from 'moment';
 | 
			
		||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
 | 
			
		||||
// import './http';
 | 
			
		||||
import BasicDrawer from './components/BasicDrawer.vue';
 | 
			
		||||
import { publicFormatter } from '@/utils/dict';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'EquipmentPlcConnect',
 | 
			
		||||
	mixins: [basicPageMixin],
 | 
			
		||||
	components: {},
 | 
			
		||||
	components: { BasicDrawer },
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			searchBarKeys: ['equipmentId', 'plcId'],
 | 
			
		||||
@@ -78,6 +127,10 @@ export default {
 | 
			
		||||
			// 		: undefined,
 | 
			
		||||
			// ].filter((v) => v),
 | 
			
		||||
			tableBtn: [
 | 
			
		||||
				{
 | 
			
		||||
					type: 'detail',
 | 
			
		||||
					btnName: '参数绑定',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'edit',
 | 
			
		||||
					btnName: '修改',
 | 
			
		||||
@@ -107,32 +160,32 @@ export default {
 | 
			
		||||
				{ prop: 'plcTableName', label: '关联表名' },
 | 
			
		||||
				{ prop: 'plcName', label: '标识名称' },
 | 
			
		||||
				{ prop: 'bindingParameters', label: '绑定参数数量' },
 | 
			
		||||
				{
 | 
			
		||||
					_action: 'params-bind',
 | 
			
		||||
					label: '查看绑定',
 | 
			
		||||
					subcomponent: {
 | 
			
		||||
						props: ['injectData'],
 | 
			
		||||
						render: function (h) {
 | 
			
		||||
							const _this = this;
 | 
			
		||||
							return h(
 | 
			
		||||
								'el-button',
 | 
			
		||||
								{
 | 
			
		||||
									props: { type: 'text' },
 | 
			
		||||
									on: {
 | 
			
		||||
										click: function () {
 | 
			
		||||
											console.log('inejctdata', _this.injectData);
 | 
			
		||||
											_this.$emit('emitData', {
 | 
			
		||||
												action: _this.injectData._action,
 | 
			
		||||
												payload: _this.injectData,
 | 
			
		||||
											});
 | 
			
		||||
										},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
								'查看绑定'
 | 
			
		||||
							);
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				// {
 | 
			
		||||
				// 	_action: 'params-bind',
 | 
			
		||||
				// 	label: '查看绑定',
 | 
			
		||||
				// 	subcomponent: {
 | 
			
		||||
				// 		props: ['injectData'],
 | 
			
		||||
				// 		render: function (h) {
 | 
			
		||||
				// 			const _this = this;
 | 
			
		||||
				// 			return h(
 | 
			
		||||
				// 				'el-button',
 | 
			
		||||
				// 				{
 | 
			
		||||
				// 					props: { type: 'text' },
 | 
			
		||||
				// 					on: {
 | 
			
		||||
				// 						click: function () {
 | 
			
		||||
				// 							console.log('inejctdata', _this.injectData);
 | 
			
		||||
				// 							_this.$emit('emitData', {
 | 
			
		||||
				// 								action: _this.injectData._action,
 | 
			
		||||
				// 								payload: _this.injectData,
 | 
			
		||||
				// 							});
 | 
			
		||||
				// 						},
 | 
			
		||||
				// 					},
 | 
			
		||||
				// 				},
 | 
			
		||||
				// 				'查看绑定'
 | 
			
		||||
				// 			);
 | 
			
		||||
				// 		},
 | 
			
		||||
				// 	},
 | 
			
		||||
				// },
 | 
			
		||||
			],
 | 
			
		||||
			searchBarFormConfig: [
 | 
			
		||||
				{
 | 
			
		||||
@@ -185,8 +238,8 @@ export default {
 | 
			
		||||
						url: '/base/equipment-plc/listAll',
 | 
			
		||||
						rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
						bind: {
 | 
			
		||||
							filterable: true
 | 
			
		||||
						}
 | 
			
		||||
							filterable: true,
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				[
 | 
			
		||||
@@ -197,8 +250,8 @@ export default {
 | 
			
		||||
						url: '/base/equipment/page?pageNo=1&pageSize=99',
 | 
			
		||||
						rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
						bind: {
 | 
			
		||||
							filterable: true
 | 
			
		||||
						}
 | 
			
		||||
							filterable: true,
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
			],
 | 
			
		||||
@@ -212,6 +265,52 @@ export default {
 | 
			
		||||
			},
 | 
			
		||||
			// 表单参数
 | 
			
		||||
			form: {},
 | 
			
		||||
			// 查看绑定配置
 | 
			
		||||
			editVisible: false,
 | 
			
		||||
			editMode: '',
 | 
			
		||||
			drawerBaseInfoRows: [
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '设备名',
 | 
			
		||||
						prop: 'equipmentName',
 | 
			
		||||
						rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
 | 
			
		||||
						// bind: {
 | 
			
		||||
						// 	disabled: this.editMode == 'detail', // some condition, like detail mode...
 | 
			
		||||
						// }
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
						label: '关联表名',
 | 
			
		||||
						prop: 'plcTableName',
 | 
			
		||||
						// url: '/base/equipment/getCode',
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
			],
 | 
			
		||||
			drawerListProps: [
 | 
			
		||||
				{ prop: 'plcParamName', label: '参数列名' },
 | 
			
		||||
				{ prop: 'name', label: '参数名称' },
 | 
			
		||||
				{
 | 
			
		||||
					prop: 'unit',
 | 
			
		||||
					label: '单位',
 | 
			
		||||
					filter: publicFormatter('unit_dict'),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					prop: 'collection',
 | 
			
		||||
					label: '是否采集',
 | 
			
		||||
					filter: (val) => (val != null ? ['否', '是'][val] : '-'),
 | 
			
		||||
				},
 | 
			
		||||
				{ prop: 'minValue', label: '最小值' },
 | 
			
		||||
				{ prop: 'maxValue', label: '最大值' },
 | 
			
		||||
				{ prop: 'defaultValue', label: '标准值' },
 | 
			
		||||
				{ prop: 'description', label: '描述' },
 | 
			
		||||
				{ prop: 'remark', label: '备注' },
 | 
			
		||||
			],
 | 
			
		||||
			alarmForm: {
 | 
			
		||||
				id: undefined,
 | 
			
		||||
				equipmentName: undefined,
 | 
			
		||||
				plcTableName: undefined,
 | 
			
		||||
			},
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	created() {
 | 
			
		||||
@@ -353,6 +452,34 @@ export default {
 | 
			
		||||
				});
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 查看报警
 | 
			
		||||
		handleDetail(row) {
 | 
			
		||||
			// debugger;
 | 
			
		||||
			const {
 | 
			
		||||
				id,
 | 
			
		||||
				bindingParameters,
 | 
			
		||||
				equipmentCode,
 | 
			
		||||
				equipmentId,
 | 
			
		||||
				equipmentName,
 | 
			
		||||
				plcCode,
 | 
			
		||||
				plcId,
 | 
			
		||||
				plcName,
 | 
			
		||||
				plcTableName,
 | 
			
		||||
				productionLine,
 | 
			
		||||
				workshopSection,
 | 
			
		||||
			} = row;
 | 
			
		||||
			// 打开抽屉
 | 
			
		||||
			this.editMode = 'detail';
 | 
			
		||||
			this.alarmForm.id = id;
 | 
			
		||||
			this.alarmForm.plcTableName = plcTableName; // 关联表名
 | 
			
		||||
			this.alarmForm.equipmentName = equipmentName;
 | 
			
		||||
			this.editVisible = true;
 | 
			
		||||
			this.$nextTick(() => {
 | 
			
		||||
				this.$refs['drawer'].init();
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 删除按钮操作 */
 | 
			
		||||
		handleDelete(row) {
 | 
			
		||||
			const id = row.id;
 | 
			
		||||
@@ -367,6 +494,7 @@ export default {
 | 
			
		||||
				})
 | 
			
		||||
				.catch(() => {});
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 导出按钮操作 */
 | 
			
		||||
		handleExport() {
 | 
			
		||||
			// 处理查询参数
 | 
			
		||||
 
 | 
			
		||||
@@ -139,6 +139,12 @@ export default {
 | 
			
		||||
							btnName: '删除',
 | 
			
		||||
					  }
 | 
			
		||||
					: undefined,
 | 
			
		||||
				this.$auth.hasPermi(`base:equipment:update`)
 | 
			
		||||
					? {
 | 
			
		||||
							type: 'detail',
 | 
			
		||||
							btnName: '详情',
 | 
			
		||||
					  }
 | 
			
		||||
					: undefined,
 | 
			
		||||
			].filter((v) => v),
 | 
			
		||||
			tableProps: [
 | 
			
		||||
				{
 | 
			
		||||
@@ -153,32 +159,32 @@ export default {
 | 
			
		||||
				{ prop: 'equipmentType', label: '设备类型' },
 | 
			
		||||
				{ prop: 'enName', label: '英文名称' },
 | 
			
		||||
				{ prop: 'abbr', label: '缩写' },
 | 
			
		||||
				{
 | 
			
		||||
					action: 'show-detail',
 | 
			
		||||
					label: '详情',
 | 
			
		||||
					subcomponent: {
 | 
			
		||||
						props: ['injectData'],
 | 
			
		||||
						render: function (h) {
 | 
			
		||||
							const _this = this;
 | 
			
		||||
							return h(
 | 
			
		||||
								'el-button',
 | 
			
		||||
								{
 | 
			
		||||
									props: { type: 'text', size: 'mini' },
 | 
			
		||||
									on: {
 | 
			
		||||
										click: function () {
 | 
			
		||||
											console.log('inejctdata', _this.injectData);
 | 
			
		||||
											_this.$emit('emitData', {
 | 
			
		||||
												action: _this.injectData.action,
 | 
			
		||||
												value: _this.injectData.id,
 | 
			
		||||
											});
 | 
			
		||||
										},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
								'查看详情'
 | 
			
		||||
							);
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				// {
 | 
			
		||||
				// 	action: 'show-detail',
 | 
			
		||||
				// 	label: '详情',
 | 
			
		||||
				// 	subcomponent: {
 | 
			
		||||
				// 		props: ['injectData'],
 | 
			
		||||
				// 		render: function (h) {
 | 
			
		||||
				// 			const _this = this;
 | 
			
		||||
				// 			return h(
 | 
			
		||||
				// 				'el-button',
 | 
			
		||||
				// 				{
 | 
			
		||||
				// 					props: { type: 'text', size: 'mini' },
 | 
			
		||||
				// 					on: {
 | 
			
		||||
				// 						click: function () {
 | 
			
		||||
				// 							console.log('inejctdata', _this.injectData);
 | 
			
		||||
				// 							_this.$emit('emitData', {
 | 
			
		||||
				// 								action: _this.injectData.action,
 | 
			
		||||
				// 								value: _this.injectData.id,
 | 
			
		||||
				// 							});
 | 
			
		||||
				// 						},
 | 
			
		||||
				// 					},
 | 
			
		||||
				// 				},
 | 
			
		||||
				// 				'查看详情'
 | 
			
		||||
				// 			);
 | 
			
		||||
				// 		},
 | 
			
		||||
				// 	},
 | 
			
		||||
				// },
 | 
			
		||||
			],
 | 
			
		||||
			searchBarFormConfig: [
 | 
			
		||||
				{
 | 
			
		||||
@@ -532,6 +538,10 @@ export default {
 | 
			
		||||
				case 'delete':
 | 
			
		||||
					this.handleDelete(data);
 | 
			
		||||
					break;
 | 
			
		||||
				case 'detail':
 | 
			
		||||
					const { id } = data;
 | 
			
		||||
					this.viewDetail(id);
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
 
 | 
			
		||||
@@ -6,10 +6,11 @@
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="chart-grid-item" style="">
 | 
			
		||||
	<div class="chart-grid-item" style="overflow: inherit">
 | 
			
		||||
		<div
 | 
			
		||||
			class="pie-chart"
 | 
			
		||||
			ref="pieChart"
 | 
			
		||||
			style="overflow: inherit;"
 | 
			
		||||
			:data-eqname="value.equipmentName || 'Default'"></div>
 | 
			
		||||
		<div class="data-view">
 | 
			
		||||
			<div class="data-view__item">
 | 
			
		||||
@@ -93,7 +94,7 @@ export default {
 | 
			
		||||
						name: '',
 | 
			
		||||
						type: 'pie',
 | 
			
		||||
						radius: ['75%', '90%'],
 | 
			
		||||
						center: ['50%', '45%'],
 | 
			
		||||
						center: ['50%', '48%'],
 | 
			
		||||
						label: {
 | 
			
		||||
							show: false,
 | 
			
		||||
						},
 | 
			
		||||
@@ -108,7 +109,7 @@ export default {
 | 
			
		||||
						// 内环
 | 
			
		||||
						name: '',
 | 
			
		||||
						type: 'pie',
 | 
			
		||||
						center: ['50%', '45%'],
 | 
			
		||||
						center: ['50%', '48%'],
 | 
			
		||||
						radius: ['60%', '75%'],
 | 
			
		||||
						itemStyle: {
 | 
			
		||||
							borderRadius: 10,
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="app-container">
 | 
			
		||||
	<div class="app-container allow-overflow">
 | 
			
		||||
		<!-- 搜索工作栏 -->
 | 
			
		||||
		<SearchBar
 | 
			
		||||
			:formConfigs="searchBarFormConfig"
 | 
			
		||||
@@ -29,11 +29,19 @@
 | 
			
		||||
							:table-data="list"
 | 
			
		||||
							@emitFun="handleEmitFun"></base-table>
 | 
			
		||||
					</el-tab-pane>
 | 
			
		||||
					<el-tab-pane :label="'\u3000可视化\u3000'" name="graph">
 | 
			
		||||
					<el-tab-pane
 | 
			
		||||
						:label="'\u3000可视化\u3000'"
 | 
			
		||||
						name="graph"
 | 
			
		||||
						style="overflow: inherit">
 | 
			
		||||
						<div
 | 
			
		||||
							v-if="activeName == 'graph'"
 | 
			
		||||
							class="graph"
 | 
			
		||||
							style="display: flex; flex-direction: column; position: relative">
 | 
			
		||||
							style="
 | 
			
		||||
								overflow: inherit;
 | 
			
		||||
								display: flex;
 | 
			
		||||
								flex-direction: column;
 | 
			
		||||
								position: relative;
 | 
			
		||||
							">
 | 
			
		||||
							<div class="blue-title">各设备加工数量</div>
 | 
			
		||||
							<div class="legend">
 | 
			
		||||
								<div class="legend-item">
 | 
			
		||||
@@ -429,6 +437,10 @@ export default {
 | 
			
		||||
		transform: translateY(-12px);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	.el-tabs__content {
 | 
			
		||||
		overflow: visible;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	.el-tabs__item {
 | 
			
		||||
		padding-left: 0 !important;
 | 
			
		||||
		padding-right: 0 !important;
 | 
			
		||||
@@ -462,6 +474,7 @@ export default {
 | 
			
		||||
	border-radius: 12px;
 | 
			
		||||
	border: 1px solid #ccc;
 | 
			
		||||
	// background: #0003;
 | 
			
		||||
	overflow: inherit;
 | 
			
		||||
}
 | 
			
		||||
.bg-grid {
 | 
			
		||||
	display: grid;
 | 
			
		||||
@@ -469,7 +482,7 @@ export default {
 | 
			
		||||
	grid-template-columns: repeat(4, minmax(280px, 1fr));
 | 
			
		||||
	grid-auto-columns: 280px;
 | 
			
		||||
	grid-auto-rows: 290px;
 | 
			
		||||
	overflow: hidden;
 | 
			
		||||
	overflow: inherit;
 | 
			
		||||
	position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,7 @@ export default {
 | 
			
		||||
										(item, index) => `
 | 
			
		||||
											<li style="list-style: none; display: flex; justify-content: space-between; align-items: center;">
 | 
			
		||||
												<div>
 | 
			
		||||
													<span style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background-color: ${item.color}; margin-right: 5px;"></span>
 | 
			
		||||
													<span style="display: inline-block; width: 10px; height: 10px; border-radius: 2px; background-color: ${item.color}; margin-right: 5px;"></span>
 | 
			
		||||
													${item.seriesName}
 | 
			
		||||
												</div>
 | 
			
		||||
												${item.value}
 | 
			
		||||
@@ -121,6 +121,7 @@ export default {
 | 
			
		||||
				},
 | 
			
		||||
				series: [
 | 
			
		||||
					{
 | 
			
		||||
						animation: false,
 | 
			
		||||
						name: '合格数量',
 | 
			
		||||
						type: 'bar',
 | 
			
		||||
						barWidth: 20,
 | 
			
		||||
@@ -128,6 +129,7 @@ export default {
 | 
			
		||||
						data: opt.map((item) => item[1]),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						animation: false,
 | 
			
		||||
						name: '不合格数量',
 | 
			
		||||
						type: 'bar',
 | 
			
		||||
						barWidth: 20,
 | 
			
		||||
 
 | 
			
		||||
@@ -302,7 +302,7 @@ export default {
 | 
			
		||||
			});
 | 
			
		||||
			this.list = data.map((item) => ({
 | 
			
		||||
				...item,
 | 
			
		||||
				products: item.products.join(','),
 | 
			
		||||
				products: item.products?.join(','),
 | 
			
		||||
			}));
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
@@ -312,7 +312,7 @@ export default {
 | 
			
		||||
				case 'search':
 | 
			
		||||
					this.queryParams.lineId = btn.lineId;
 | 
			
		||||
					this.queryParams.productId = btn.productId;
 | 
			
		||||
					this.queryParams.recordTime = btn.recordTime;
 | 
			
		||||
					this.queryParams.recordTime = btn.recordTime ? btn.recordTime.map(time => moment(new Date(time)).format('YYYY-MM-DD HH:mm:ss')) : null;
 | 
			
		||||
					this.$nextTick(() => {
 | 
			
		||||
						this.getList();
 | 
			
		||||
					});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										328
									
								
								src/views/equipment/timing-diagram/status/chart.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										328
									
								
								src/views/equipment/timing-diagram/status/chart.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,328 @@
 | 
			
		||||
import * as echarts from 'echarts'
 | 
			
		||||
 | 
			
		||||
function getStartTime(timestamp) {
 | 
			
		||||
    return new Date(new Date(timestamp).toLocaleDateString()).getTime();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function renderItem(params, api) {
 | 
			
		||||
    var categoryIndex = api.value(0);
 | 
			
		||||
    var start = api.coord([api.value(1), categoryIndex]);
 | 
			
		||||
    var end = api.coord([api.value(2), categoryIndex]);
 | 
			
		||||
 | 
			
		||||
    var height = api.size([0, 1])[1] * 2;
 | 
			
		||||
    var rectShape = echarts.graphic.clipRectByRect(
 | 
			
		||||
        {
 | 
			
		||||
            x: start[0],
 | 
			
		||||
            y: start[1] - height / 2,
 | 
			
		||||
            width: end[0] - start[0],
 | 
			
		||||
            height: height,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            x: params.coordSys.x,
 | 
			
		||||
            y: params.coordSys.y - 16,
 | 
			
		||||
            width: params.coordSys.width,
 | 
			
		||||
            height: params.coordSys.height,
 | 
			
		||||
        }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        rectShape && {
 | 
			
		||||
            type: 'rect',
 | 
			
		||||
            transition: ['shape'],
 | 
			
		||||
            shape: rectShape,
 | 
			
		||||
            style: api.style(),
 | 
			
		||||
        }
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// unused
 | 
			
		||||
function getXaxisRange(startTime) {
 | 
			
		||||
    return Array(24)
 | 
			
		||||
        .fill(startTime)
 | 
			
		||||
        .map((item, index) => {
 | 
			
		||||
            return new Date(item + index * 3600 * 1000)
 | 
			
		||||
                .toLocaleTimeString()
 | 
			
		||||
                .split(':')
 | 
			
		||||
                .slice(0, 2)
 | 
			
		||||
                .join(':');
 | 
			
		||||
        });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getTodayStart(today) {
 | 
			
		||||
    const [y, m, d] = [
 | 
			
		||||
        today.getFullYear(),
 | 
			
		||||
        today.getMonth(),
 | 
			
		||||
        today.getDate(),
 | 
			
		||||
    ];
 | 
			
		||||
    // debugger;
 | 
			
		||||
    return new Date(y, m, d).getTime();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** 颜色配置 */
 | 
			
		||||
const types = [
 | 
			
		||||
    { name: '运行', color: '#288AFF' },
 | 
			
		||||
    { name: '故障', color: '#FC9C91' },
 | 
			
		||||
    { name: '计划停机', color: '#FFDC94' },
 | 
			
		||||
    { name: '空白', color: '#F2F4F9' },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export default class GanttGraph {
 | 
			
		||||
    // tooltip - 基本是固定的
 | 
			
		||||
    tooltip = {
 | 
			
		||||
        trigger: 'item',
 | 
			
		||||
        axisPointer: {
 | 
			
		||||
            type: 'none',
 | 
			
		||||
        },
 | 
			
		||||
        formatter: (params) => {
 | 
			
		||||
            // debugger;
 | 
			
		||||
            return `
 | 
			
		||||
            <div style="display: flex; flex-direction: column;">
 | 
			
		||||
                <span>${new Date(params.value[1]).toLocaleTimeString()} ~ ${new Date(params.value[2]).toLocaleTimeString()}</span>
 | 
			
		||||
                <div style="display: flex; align-items: center; justify-content: space-between;">
 | 
			
		||||
                    <div style="display: flex; align-items: center;">
 | 
			
		||||
                        <span class="icon" style="width: 8px; height: 8px; border-radius: 2px; background: ${params.color}"></span>
 | 
			
		||||
                        <span class="eq-name" style="margin-left: 4px;">${params.seriesName}</span>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <span class="run-status" style="margin-left: 8px; opacity: 0.6">${params.name}</span>
 | 
			
		||||
            </div>            
 | 
			
		||||
            `
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    grid = []
 | 
			
		||||
    xAxis = []
 | 
			
		||||
    yAxis = []
 | 
			
		||||
    series = []
 | 
			
		||||
 | 
			
		||||
    constructor(el, startTime) {
 | 
			
		||||
        this.el = el;
 | 
			
		||||
        this.gridIndex = -1;
 | 
			
		||||
        this.currentGraphIndex = -2;
 | 
			
		||||
        this.startTime = new Date(startTime);
 | 
			
		||||
        // this.startTime = new Date(new Date('2023/10/8').toLocaleDateString());
 | 
			
		||||
        // console.log('<> Gantt Created', this.startTime);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 构造一个新的 grid
 | 
			
		||||
    makeGrid() {
 | 
			
		||||
        this.gridIndex++;
 | 
			
		||||
        return {
 | 
			
		||||
            id: 'GRID_' + this.gridIndex,
 | 
			
		||||
            // top: 12 + 128 * this.gridIndex,
 | 
			
		||||
            top: 12 + 104 * this.gridIndex,
 | 
			
		||||
            right: 48,
 | 
			
		||||
            left: 88,
 | 
			
		||||
            height: 56
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 构造一个 xAxis
 | 
			
		||||
    makeXaxis() {
 | 
			
		||||
        const [id1, id2] = ['' + Math.random(), '' + Math.random()]
 | 
			
		||||
        return [
 | 
			
		||||
            {
 | 
			
		||||
                id: id1,
 | 
			
		||||
                gridIndex: this.gridIndex,
 | 
			
		||||
                axisTick: {
 | 
			
		||||
                    alignWithLabel: true,
 | 
			
		||||
                    inside: true,
 | 
			
		||||
                },
 | 
			
		||||
                type: 'time',
 | 
			
		||||
                min: getTodayStart(this.startTime),
 | 
			
		||||
                max: getStartTime(this.startTime.getTime() + 3600 * 24 * 1000),
 | 
			
		||||
                splitNumber: 10,
 | 
			
		||||
                axisLabel: {
 | 
			
		||||
                    margin: 12,
 | 
			
		||||
                    formatter: function (val) {
 | 
			
		||||
                        return new Date(val)
 | 
			
		||||
                            .toLocaleTimeString()
 | 
			
		||||
                            .split(':')
 | 
			
		||||
                            .slice(0, 2)
 | 
			
		||||
                            .join(':');
 | 
			
		||||
                    },
 | 
			
		||||
                },
 | 
			
		||||
                axisLine: {
 | 
			
		||||
                    lineStyle: {
 | 
			
		||||
                        color: '#0005',
 | 
			
		||||
                    },
 | 
			
		||||
                },
 | 
			
		||||
                boundaryGap: false,
 | 
			
		||||
                // data: getXaxisRange(getTodayStart(new Date())),
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                id: id2,
 | 
			
		||||
                gridIndex: this.gridIndex,
 | 
			
		||||
                axisLabel: { show: false },
 | 
			
		||||
                axisLine: { show: false },
 | 
			
		||||
            },
 | 
			
		||||
        ]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // 构造一个 yAxis
 | 
			
		||||
    makeYaxis(equipmentName) {
 | 
			
		||||
        const [id1, id2] = ['' + Math.random(), '' + Math.random()]
 | 
			
		||||
        return [
 | 
			
		||||
            // 主y轴
 | 
			
		||||
            {
 | 
			
		||||
                id: id1,
 | 
			
		||||
                gridIndex: this.gridIndex,
 | 
			
		||||
                type: 'value',
 | 
			
		||||
                splitLine: { show: false },
 | 
			
		||||
                name: equipmentName,
 | 
			
		||||
                nameLocation: 'center',
 | 
			
		||||
                nameGap: 14,
 | 
			
		||||
                nameRotate: 0,
 | 
			
		||||
                nameTextStyle: {
 | 
			
		||||
                    fontSize: 16,
 | 
			
		||||
                    color: '#000A'
 | 
			
		||||
                },
 | 
			
		||||
                axisLine: {
 | 
			
		||||
                    show: true,
 | 
			
		||||
                    lineStyle: {
 | 
			
		||||
                        color: '#0005',
 | 
			
		||||
                    },
 | 
			
		||||
                },
 | 
			
		||||
                axisLabel: { show: false },
 | 
			
		||||
                axisTick: { show: false },
 | 
			
		||||
            },
 | 
			
		||||
            // 辅y轴
 | 
			
		||||
            {
 | 
			
		||||
                id: id2,
 | 
			
		||||
                gridIndex: this.gridIndex,
 | 
			
		||||
                type: 'value',
 | 
			
		||||
                splitLine: { show: false },
 | 
			
		||||
                axisLine: {
 | 
			
		||||
                    show: true,
 | 
			
		||||
                    lineStyle: {
 | 
			
		||||
                        color: '#0005',
 | 
			
		||||
                    },
 | 
			
		||||
                },
 | 
			
		||||
                axisLabel: { show: false },
 | 
			
		||||
                axisTick: { show: false },
 | 
			
		||||
            },
 | 
			
		||||
        ]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 构造一个 series
 | 
			
		||||
    makeSeries({ equipmentName, arr }) {
 | 
			
		||||
        this.currentGraphIndex += 2;
 | 
			
		||||
        const bgStartTime = this.startTime.getTime();
 | 
			
		||||
        const bgEndTime = bgStartTime + 3600 * 24 * 1000;
 | 
			
		||||
        return [
 | 
			
		||||
            // 沉默的背景
 | 
			
		||||
            {
 | 
			
		||||
                xAxisIndex: this.currentGraphIndex,
 | 
			
		||||
                yAxisIndex: this.currentGraphIndex,
 | 
			
		||||
                type: 'custom',
 | 
			
		||||
                renderItem: renderItem,
 | 
			
		||||
                silent: true,
 | 
			
		||||
                itemStyle: {
 | 
			
		||||
                    opacity: 0.8,
 | 
			
		||||
                },
 | 
			
		||||
                encode: {
 | 
			
		||||
                    x: [1, 2],
 | 
			
		||||
                    y: 0,
 | 
			
		||||
                },
 | 
			
		||||
                data: [
 | 
			
		||||
                    {
 | 
			
		||||
                        name: '无数据',
 | 
			
		||||
                        value: [0, bgStartTime, bgEndTime, 0],
 | 
			
		||||
                        tooltip: { show: false },
 | 
			
		||||
                        itemStyle: {
 | 
			
		||||
                            color: '#F2F4F9',
 | 
			
		||||
                            opacity: 0.3,
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                ]
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                name: equipmentName,
 | 
			
		||||
                xAxisIndex: this.currentGraphIndex,
 | 
			
		||||
                yAxisIndex: this.currentGraphIndex,
 | 
			
		||||
                type: 'custom',
 | 
			
		||||
                renderItem: renderItem,
 | 
			
		||||
                itemStyle: {
 | 
			
		||||
                    opacity: 0.8,
 | 
			
		||||
                },
 | 
			
		||||
                encode: {
 | 
			
		||||
                    x: [1, 2],
 | 
			
		||||
                    y: 0,
 | 
			
		||||
                },
 | 
			
		||||
                data: arr.map(item => ({
 | 
			
		||||
                    name: ['运行', '故障', '计划停机'][item.status],
 | 
			
		||||
                    value: [0, item.startTime, item.startTime + item.duration * 60 * 1000, 0],
 | 
			
		||||
                    itemStyle: {
 | 
			
		||||
                        color: types[item.status].color,
 | 
			
		||||
                    }
 | 
			
		||||
                })),
 | 
			
		||||
            },
 | 
			
		||||
        ]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    init(data) {
 | 
			
		||||
        if (!this.el) throw new Error('没有可供echarts初始化的容器')
 | 
			
		||||
        if (typeof this.el == 'string') {
 | 
			
		||||
            this.el = document.querySelector(this.el);
 | 
			
		||||
        }
 | 
			
		||||
        this.chart = echarts.init(this.el);
 | 
			
		||||
        this.handleProps(data);
 | 
			
		||||
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
            // debugger;
 | 
			
		||||
            this.chart.setOption(this.option);
 | 
			
		||||
        }, 200);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    update(data) {
 | 
			
		||||
        this.clear();
 | 
			
		||||
        this.init(data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    resize() {
 | 
			
		||||
        this.chart.resize();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get option() {
 | 
			
		||||
        return {
 | 
			
		||||
            tooltip: this.tooltip,
 | 
			
		||||
            grid: this.grid,
 | 
			
		||||
            xAxis: this.xAxis,
 | 
			
		||||
            yAxis: this.yAxis,
 | 
			
		||||
            series: this.series,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 每次 graphList 刷新都会重新渲染整个所有图表
 | 
			
		||||
    // 可以改进的地方:添加一个 handleAdd() 方法,一次添加一个新的
 | 
			
		||||
    handleProps(props) {
 | 
			
		||||
        // props 是父组件的 graphList
 | 
			
		||||
        console.log('props: ', props);
 | 
			
		||||
        props.forEach(eqArr => {
 | 
			
		||||
            this.grid.push(this.makeGrid());
 | 
			
		||||
            this.xAxis.push(...this.makeXaxis());
 | 
			
		||||
            this.yAxis.push(...this.makeYaxis(eqArr.key));
 | 
			
		||||
            this.series.push(...this.makeSeries({ equipmentName: eqArr.key, arr: eqArr }))
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // handleAdd
 | 
			
		||||
    handleAdd() { }
 | 
			
		||||
 | 
			
		||||
    clear() {
 | 
			
		||||
        this.grid = [];
 | 
			
		||||
        this.xAxis = [];
 | 
			
		||||
        this.yAxis = [];
 | 
			
		||||
        this.series = [];
 | 
			
		||||
        this.currentGraphIndex = -2;
 | 
			
		||||
        this.gridIndex = -1;
 | 
			
		||||
        this.chart.dispose();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // print option
 | 
			
		||||
    print() {
 | 
			
		||||
        console.log(JSON.stringify(this.option, null, 2));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,26 +1,26 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
	<head>
 | 
			
		||||
		<meta charset="UTF-8" />
 | 
			
		||||
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
 | 
			
		||||
		<title>Document</title>
 | 
			
		||||
	</head>
 | 
			
		||||
	<body>
 | 
			
		||||
		<div
 | 
			
		||||
			id="app"
 | 
			
		||||
			style="width: 100vw; height: 80vh; background: #ccc3; margin: 24px"></div>
 | 
			
		||||
 | 
			
		||||
		<script src="./echarts.js"></script>
 | 
			
		||||
		<script>
 | 
			
		||||
			function getStartTime(timestamp) {
 | 
			
		||||
				return new Date(new Date(timestamp).toLocaleDateString()).getTime();
 | 
			
		||||
			}
 | 
			
		||||
<head>
 | 
			
		||||
	<meta charset="UTF-8" />
 | 
			
		||||
	<meta name="viewport" content="width=device-width, initial-scale=1.0" />
 | 
			
		||||
	<title>Document</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
			function renderItem(params, api) {
 | 
			
		||||
				var categoryIndex = api.value(0);
 | 
			
		||||
				var start = api.coord([api.value(1), categoryIndex]);
 | 
			
		||||
				var end = api.coord([api.value(2), categoryIndex]);
 | 
			
		||||
				console.log(`
 | 
			
		||||
<body>
 | 
			
		||||
	<div id="app" style="width: 100vw; height: 80vh; background: #fff; margin: 24px"></div>
 | 
			
		||||
 | 
			
		||||
	<script src="./echarts.js"></script>
 | 
			
		||||
	<script>
 | 
			
		||||
		function getStartTime(timestamp) {
 | 
			
		||||
			return new Date(new Date(timestamp).toLocaleDateString()).getTime();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		function renderItem(params, api) {
 | 
			
		||||
			var categoryIndex = api.value(0);
 | 
			
		||||
			var start = api.coord([api.value(1), categoryIndex]);
 | 
			
		||||
			var end = api.coord([api.value(2), categoryIndex]);
 | 
			
		||||
			console.log(`
 | 
			
		||||
                    categoryIndex: ${categoryIndex},
 | 
			
		||||
                    start: ${start},
 | 
			
		||||
                    end: ${end},
 | 
			
		||||
@@ -32,249 +32,466 @@
 | 
			
		||||
                    api.style(): ${JSON.stringify(api.style())}
 | 
			
		||||
                `);
 | 
			
		||||
 | 
			
		||||
				var height = api.size([0, 1])[1] * 2;
 | 
			
		||||
				// 用一个矩形去截取另一个矩形
 | 
			
		||||
				var rectShape = echarts.graphic.clipRectByRect(
 | 
			
		||||
					// 被截取矩形
 | 
			
		||||
					{
 | 
			
		||||
						x: start[0],
 | 
			
		||||
						y: start[1] - height / 2,
 | 
			
		||||
						width: end[0] - start[0],
 | 
			
		||||
						height: height,
 | 
			
		||||
					},
 | 
			
		||||
					// 截取矩形
 | 
			
		||||
					{
 | 
			
		||||
						// 截取掉grid以外的部分,实质是计算方块的偏移量
 | 
			
		||||
						x: params.coordSys.x, // {number} grid rect 的 x
 | 
			
		||||
						// y: params.coordSys.y, // {number} grid rect 的 y
 | 
			
		||||
						y: params.coordSys.y - 16, // {number} grid rect 的 y,并多减掉 16 个单位
 | 
			
		||||
						width: params.coordSys.width, // {number} grid rect 的 width
 | 
			
		||||
						height: params.coordSys.height, // {number} grid rect 的 height
 | 
			
		||||
					}
 | 
			
		||||
				);
 | 
			
		||||
                console.log(`------------- ${JSON.stringify(rectShape)} -------------- `)
 | 
			
		||||
				return (
 | 
			
		||||
					rectShape && {
 | 
			
		||||
						type: 'rect',
 | 
			
		||||
						transition: ['shape'],
 | 
			
		||||
						shape: rectShape,
 | 
			
		||||
						style: api.style(),
 | 
			
		||||
					}
 | 
			
		||||
				);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			function getXaxisRange(startTime) {
 | 
			
		||||
				return Array(24)
 | 
			
		||||
					.fill(startTime)
 | 
			
		||||
					.map((item, index) => {
 | 
			
		||||
						return new Date(item + index * 3600 * 1000)
 | 
			
		||||
							.toLocaleTimeString()
 | 
			
		||||
							.split(':')
 | 
			
		||||
							.slice(0, 2)
 | 
			
		||||
							.join(':');
 | 
			
		||||
					});
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			function getTodayStart(today) {
 | 
			
		||||
				const [y, m, d] = [
 | 
			
		||||
					today.getFullYear(),
 | 
			
		||||
					today.getMonth(),
 | 
			
		||||
					today.getDate(),
 | 
			
		||||
				];
 | 
			
		||||
				return new Date(y, m, d).getTime();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/** 颜色配置 */
 | 
			
		||||
			const types = [
 | 
			
		||||
				{ name: '运行', color: '#288AFF' },
 | 
			
		||||
				{ name: '故障', color: '#FC9C91' },
 | 
			
		||||
				{ name: '计划停机', color: '#FFDC94' },
 | 
			
		||||
				{ name: '空白', color: '#F2F4F9' },
 | 
			
		||||
			];
 | 
			
		||||
 | 
			
		||||
			const option = {
 | 
			
		||||
				tooltip: {
 | 
			
		||||
					trigger: 'axis',
 | 
			
		||||
					axisPointer: {
 | 
			
		||||
						type: 'none',
 | 
			
		||||
						// label: {
 | 
			
		||||
						// 	backgroundColor: '#6a7985',
 | 
			
		||||
						// },
 | 
			
		||||
					},
 | 
			
		||||
                    formatter: (params) => {
 | 
			
		||||
                        // console.log('formatter', params)
 | 
			
		||||
                        // return `
 | 
			
		||||
                        // <div>${new Date(params[0].value[1]).toLocaleString()} ~ ${new Date(params[0].value[2]).toLocaleString()}</div>
 | 
			
		||||
                        // <div style="display: flex; justify-content: space-between; min-width: 128px; align-items: center;">
 | 
			
		||||
                        //     <span>${params[0].seriesName}</span>
 | 
			
		||||
                        //     <span>${params[0].name}</span>
 | 
			
		||||
                        // </div>
 | 
			
		||||
                        // `
 | 
			
		||||
                        return `
 | 
			
		||||
                        <h1 style="font-size: 18px; font-weight: 600; letter-spacing: 1px;">${params[0].name} <span style="display: inline-block; margin-left: 8px; width: 12px; height: 12px; border-radius: 50%; background: ${params[0].color} "></span></h1>
 | 
			
		||||
                        <div>${new Date(params[0].value[1]).toLocaleString()} ~ ${new Date(params[0].value[2]).toLocaleString()}</div>
 | 
			
		||||
                        `
 | 
			
		||||
                    }
 | 
			
		||||
			var height = api.size([0, 1])[1] * 2;
 | 
			
		||||
			// 用一个矩形去截取另一个矩形
 | 
			
		||||
			var rectShape = echarts.graphic.clipRectByRect(
 | 
			
		||||
				// 被截取矩形
 | 
			
		||||
				{
 | 
			
		||||
					x: start[0],
 | 
			
		||||
					y: start[1] - height / 2,
 | 
			
		||||
					width: end[0] - start[0],
 | 
			
		||||
					height: height,
 | 
			
		||||
				},
 | 
			
		||||
				grid: [
 | 
			
		||||
					{
 | 
			
		||||
						id: 0,
 | 
			
		||||
						top: 10,
 | 
			
		||||
                        left: 128,
 | 
			
		||||
                        right: 64,
 | 
			
		||||
						height: 56, 
 | 
			
		||||
					},
 | 
			
		||||
					// {
 | 
			
		||||
					// 	id: 1,
 | 
			
		||||
					// 	top: 80,
 | 
			
		||||
					// 	height: 56,
 | 
			
		||||
				// {x: 0, y: 0, width: 2000, height: 60 } // <== 也行...
 | 
			
		||||
				// 截取矩形
 | 
			
		||||
				{
 | 
			
		||||
					// 截取掉grid以外的部分,实质是计算方块的偏移量
 | 
			
		||||
					x: params.coordSys.x, // {number} grid rect 的 x
 | 
			
		||||
					// y: params.coordSys.y, // {number} grid rect 的 y
 | 
			
		||||
					y: params.coordSys.y - 16, // {number} grid rect 的 y,并多减掉 16 个单位
 | 
			
		||||
					// width: end[0] - start[0],
 | 
			
		||||
					width: params.coordSys.width, // {number} grid rect 的 width
 | 
			
		||||
					height: params.coordSys.height, // {number} grid rect 的 height
 | 
			
		||||
				}
 | 
			
		||||
			);
 | 
			
		||||
			console.log(`------------- ${JSON.stringify(rectShape)} -------------- `)
 | 
			
		||||
			return (
 | 
			
		||||
				rectShape && {
 | 
			
		||||
					type: 'rect',
 | 
			
		||||
					transition: ['shape'],
 | 
			
		||||
					shape: rectShape,
 | 
			
		||||
					style: api.style(),
 | 
			
		||||
				}
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		function getXaxisRange(startTime) {
 | 
			
		||||
			return Array(24)
 | 
			
		||||
				.fill(startTime)
 | 
			
		||||
				.map((item, index) => {
 | 
			
		||||
					return new Date(item + index * 3600 * 1000)
 | 
			
		||||
						.toLocaleTimeString()
 | 
			
		||||
						.split(':')
 | 
			
		||||
						.slice(0, 2)
 | 
			
		||||
						.join(':');
 | 
			
		||||
				});
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		function getTodayStart(today) {
 | 
			
		||||
			const [y, m, d] = [
 | 
			
		||||
				today.getFullYear(),
 | 
			
		||||
				today.getMonth(),
 | 
			
		||||
				today.getDate(),
 | 
			
		||||
			];
 | 
			
		||||
			return new Date(y, m, d).getTime();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/** 颜色配置 */
 | 
			
		||||
		const types = [
 | 
			
		||||
			{ name: '运行', color: '#288AFF' },
 | 
			
		||||
			{ name: '故障', color: '#FC9C91' },
 | 
			
		||||
			{ name: '计划停机', color: '#FFDC94' },
 | 
			
		||||
			{ name: '空白', color: '#F2F4F9' },
 | 
			
		||||
		];
 | 
			
		||||
 | 
			
		||||
		const option = {
 | 
			
		||||
			tooltip: {
 | 
			
		||||
				trigger: 'item',
 | 
			
		||||
				axisPointer: {
 | 
			
		||||
					type: 'none',
 | 
			
		||||
					// label: {
 | 
			
		||||
					// 	backgroundColor: '#6a7985',
 | 
			
		||||
					// },
 | 
			
		||||
				],
 | 
			
		||||
				xAxis: [
 | 
			
		||||
					{
 | 
			
		||||
						id: 0,
 | 
			
		||||
						gridIndex: 0,
 | 
			
		||||
						axisTick: {
 | 
			
		||||
							alignWithLabel: true,
 | 
			
		||||
							inside: true,
 | 
			
		||||
						},
 | 
			
		||||
						type: 'time',
 | 
			
		||||
						min: getTodayStart(new Date()), // <===
 | 
			
		||||
						max: getStartTime(new Date().getTime() + 3600 * 24 * 1000), // <===
 | 
			
		||||
						splitNumber: 10,
 | 
			
		||||
						axisLabel: {
 | 
			
		||||
							margin: 12,
 | 
			
		||||
							// rotate: -15,
 | 
			
		||||
							formatter: function (val) {
 | 
			
		||||
								return new Date(val)
 | 
			
		||||
									.toLocaleTimeString()
 | 
			
		||||
									.split(':')
 | 
			
		||||
									.slice(0, 2)
 | 
			
		||||
									.join(':');
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						boundaryGap: false,
 | 
			
		||||
						// data: getXaxisRange(getTodayStart(new Date())),
 | 
			
		||||
				},
 | 
			
		||||
				formatter: (params) => {
 | 
			
		||||
					// console.log('formatter', params)
 | 
			
		||||
					// return `
 | 
			
		||||
					// <div>${new Date(params[0].value[1]).toLocaleString()} ~ ${new Date(params[0].value[2]).toLocaleString()}</div>
 | 
			
		||||
					// <div style="display: flex; justify-content: space-between; min-width: 128px; align-items: center;">
 | 
			
		||||
					//     <span>${params[0].seriesName}</span>
 | 
			
		||||
					//     <span>${params[0].name}</span>
 | 
			
		||||
					// </div>
 | 
			
		||||
					// `
 | 
			
		||||
					return `
 | 
			
		||||
						<div style="display: flex; align-items: center; justify-content: space-between">
 | 
			
		||||
						<h1 style="font-size: 18px; font-weight: 600;">${params.seriesName}</h1>
 | 
			
		||||
                        <h2 style="font-size: 18px; font-weight: 400; letter-spacing: 1px;">${params.name} <span style="display: inline-block; margin-left: 8px; width: 12px; height: 12px; border-radius: 50%; background: ${params.color} "></span></h2>
 | 
			
		||||
                        </div>
 | 
			
		||||
						<div>${new Date(params.value[1]).toLocaleString()} ~ ${new Date(params.value[2]).toLocaleString()}</div>
 | 
			
		||||
                        `
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
			grid: [
 | 
			
		||||
				{
 | 
			
		||||
					id: 0,
 | 
			
		||||
					top: 10,
 | 
			
		||||
					left: 128,
 | 
			
		||||
					right: 64,
 | 
			
		||||
					height: 56,
 | 
			
		||||
				},
 | 
			
		||||
				// {
 | 
			
		||||
				// 	id: 1,
 | 
			
		||||
				// 	top: 80,
 | 
			
		||||
				// 	height: 56,
 | 
			
		||||
				// },
 | 
			
		||||
				// ***************** 添加第二个grid *****************
 | 
			
		||||
				{
 | 
			
		||||
					id: 1,
 | 
			
		||||
					top: 180,
 | 
			
		||||
					left: 128,
 | 
			
		||||
					right: 64,
 | 
			
		||||
					height: 56
 | 
			
		||||
				}
 | 
			
		||||
			],
 | 
			
		||||
			xAxis: [
 | 
			
		||||
				{
 | 
			
		||||
					id: 'asdf',
 | 
			
		||||
					gridIndex: 0,
 | 
			
		||||
					axisTick: {
 | 
			
		||||
						alignWithLabel: true,
 | 
			
		||||
						inside: true,
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						id: 1,
 | 
			
		||||
						gridIndex: 0,
 | 
			
		||||
						axisLabel: { show: false },
 | 
			
		||||
						axisLine: { show: false },
 | 
			
		||||
					type: 'time',
 | 
			
		||||
					min: getTodayStart(new Date()), // <===
 | 
			
		||||
					max: getStartTime(new Date().getTime() + 3600 * 24 * 1000), // <===
 | 
			
		||||
					splitNumber: 10,
 | 
			
		||||
					axisLabel: {
 | 
			
		||||
						margin: 12,
 | 
			
		||||
						// rotate: -15,
 | 
			
		||||
						formatter: function (val) {
 | 
			
		||||
							return new Date(val)
 | 
			
		||||
								.toLocaleTimeString()
 | 
			
		||||
								.split(':')
 | 
			
		||||
								.slice(0, 2)
 | 
			
		||||
								.join(':');
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				yAxis: [
 | 
			
		||||
					// 主y轴
 | 
			
		||||
					{
 | 
			
		||||
						id: 0,
 | 
			
		||||
						gridIndex: 0,
 | 
			
		||||
						type: 'value',
 | 
			
		||||
						splitLine: { show: false },
 | 
			
		||||
						name: '设备1',
 | 
			
		||||
						nameLocation: 'center',
 | 
			
		||||
						nameGap: 56,
 | 
			
		||||
						nameRotate: 0,
 | 
			
		||||
						nameTextStyle: {
 | 
			
		||||
							fontSize: 18,
 | 
			
		||||
						},
 | 
			
		||||
						axisLine: {
 | 
			
		||||
							show: true,
 | 
			
		||||
							lineStyle: {},
 | 
			
		||||
						},
 | 
			
		||||
						axisLabel: { show: false },
 | 
			
		||||
						axisTick: { show: false },
 | 
			
		||||
					boundaryGap: false,
 | 
			
		||||
					// data: getXaxisRange(getTodayStart(new Date())),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					id: 'asdff',
 | 
			
		||||
					gridIndex: 0,
 | 
			
		||||
					axisLabel: { show: false },
 | 
			
		||||
					axisLine: { show: false },
 | 
			
		||||
				},
 | 
			
		||||
				// ***************** 添加第二个 xAxis *****************
 | 
			
		||||
				{
 | 
			
		||||
					id: 'asdfjk',
 | 
			
		||||
					gridIndex: 1,
 | 
			
		||||
					axisTick: {
 | 
			
		||||
						alignWithLabel: true,
 | 
			
		||||
						inside: true,
 | 
			
		||||
					},
 | 
			
		||||
					// 辅y轴
 | 
			
		||||
					{
 | 
			
		||||
						id: 1,
 | 
			
		||||
						gridIndex: 0,
 | 
			
		||||
						type: 'value',
 | 
			
		||||
						splitLine: { show: false },
 | 
			
		||||
						axisLabel: { show: false },
 | 
			
		||||
						axisTick: { show: false },
 | 
			
		||||
					type: 'time',
 | 
			
		||||
					min: getTodayStart(new Date()), // <===
 | 
			
		||||
					max: getStartTime(new Date().getTime() + 3600 * 24 * 1000), // <===
 | 
			
		||||
					splitNumber: 10,
 | 
			
		||||
					axisLabel: {
 | 
			
		||||
						margin: 12,
 | 
			
		||||
						// rotate: -15,
 | 
			
		||||
						formatter: function (val) {
 | 
			
		||||
							return new Date(val)
 | 
			
		||||
								.toLocaleTimeString()
 | 
			
		||||
								.split(':')
 | 
			
		||||
								.slice(0, 2)
 | 
			
		||||
								.join(':');
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				series: [
 | 
			
		||||
					{
 | 
			
		||||
                        name: '设备1',
 | 
			
		||||
						xAxisIndex: 0,
 | 
			
		||||
						yAxisIndex: 0,
 | 
			
		||||
						type: 'custom',
 | 
			
		||||
						renderItem: renderItem,
 | 
			
		||||
						itemStyle: {
 | 
			
		||||
							opacity: 0.8,
 | 
			
		||||
						},
 | 
			
		||||
						encode: {
 | 
			
		||||
							x: [1, 2],
 | 
			
		||||
							y: 0,
 | 
			
		||||
						},
 | 
			
		||||
						//function getTimestamp(point) {
 | 
			
		||||
						// const t = new Date();
 | 
			
		||||
						// const [y,m,d] = [t.getFullYear(),t.getMonth(),t.getDate()]
 | 
			
		||||
						// const [h,M] = point.split(':')
 | 
			
		||||
						// return new Date(y,m,d,h,M,0,0).getTime()
 | 
			
		||||
						//}
 | 
			
		||||
						data: [
 | 
			
		||||
							{
 | 
			
		||||
								// 01:00 ~ 05:00
 | 
			
		||||
								name: '运行',
 | 
			
		||||
								value: [0, 1695747600000, 1695762000000, 0],
 | 
			
		||||
								itemStyle: {
 | 
			
		||||
									normal: {
 | 
			
		||||
										color: types[0].color,
 | 
			
		||||
									},
 | 
			
		||||
					boundaryGap: false,
 | 
			
		||||
					// data: getXaxisRange(getTodayStart(new Date())),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					id: 'fjkd',
 | 
			
		||||
					gridIndex: 1,
 | 
			
		||||
					axisLabel: { show: false },
 | 
			
		||||
					axisLine: { show: false },
 | 
			
		||||
				},
 | 
			
		||||
			],
 | 
			
		||||
			yAxis: [
 | 
			
		||||
				// 主y轴
 | 
			
		||||
				{
 | 
			
		||||
					id: 0,
 | 
			
		||||
					gridIndex: 0,
 | 
			
		||||
					type: 'value',
 | 
			
		||||
					splitLine: { show: false },
 | 
			
		||||
					name: '设备1',
 | 
			
		||||
					nameLocation: 'center',
 | 
			
		||||
					nameGap: 56,
 | 
			
		||||
					nameRotate: 0,
 | 
			
		||||
					nameTextStyle: {
 | 
			
		||||
						fontSize: 18,
 | 
			
		||||
					},
 | 
			
		||||
					axisLine: {
 | 
			
		||||
						show: true,
 | 
			
		||||
						lineStyle: {},
 | 
			
		||||
					},
 | 
			
		||||
					axisLabel: { show: false },
 | 
			
		||||
					axisTick: { show: false },
 | 
			
		||||
				},
 | 
			
		||||
				// 辅y轴
 | 
			
		||||
				{
 | 
			
		||||
					id: 1,
 | 
			
		||||
					gridIndex: 0,
 | 
			
		||||
					type: 'value',
 | 
			
		||||
					splitLine: { show: false },
 | 
			
		||||
					axisLabel: { show: false },
 | 
			
		||||
					axisTick: { show: false },
 | 
			
		||||
				},
 | 
			
		||||
				// ***************** 添加第二个 yAxis *****************
 | 
			
		||||
				{
 | 
			
		||||
					id: 2,
 | 
			
		||||
					gridIndex: 1,
 | 
			
		||||
					type: 'value',
 | 
			
		||||
					splitLine: { show: false },
 | 
			
		||||
					name: '设备1',
 | 
			
		||||
					nameLocation: 'center',
 | 
			
		||||
					nameGap: 56,
 | 
			
		||||
					nameRotate: 0,
 | 
			
		||||
					nameTextStyle: {
 | 
			
		||||
						fontSize: 18,
 | 
			
		||||
					},
 | 
			
		||||
					axisLine: {
 | 
			
		||||
						show: true,
 | 
			
		||||
						lineStyle: {},
 | 
			
		||||
					},
 | 
			
		||||
					axisLabel: { show: false },
 | 
			
		||||
					axisTick: { show: false },
 | 
			
		||||
				},
 | 
			
		||||
				// 辅y轴
 | 
			
		||||
				{
 | 
			
		||||
					id: 3,
 | 
			
		||||
					gridIndex: 1,
 | 
			
		||||
					type: 'value',
 | 
			
		||||
					splitLine: { show: false },
 | 
			
		||||
					axisLabel: { show: false },
 | 
			
		||||
					axisTick: { show: false },
 | 
			
		||||
				},
 | 
			
		||||
			],
 | 
			
		||||
			series: [
 | 
			
		||||
				{
 | 
			
		||||
					// 沉默的背景
 | 
			
		||||
					xAxisIndex: 0,
 | 
			
		||||
					yAxisIndex: 0,
 | 
			
		||||
					type: 'custom',
 | 
			
		||||
					renderItem: renderItem,
 | 
			
		||||
					silent: true,
 | 
			
		||||
					itemStyle: {
 | 
			
		||||
						opacity: 0.8,
 | 
			
		||||
					},
 | 
			
		||||
					encode: {
 | 
			
		||||
						x: [1, 2],
 | 
			
		||||
						y: 0,
 | 
			
		||||
					},
 | 
			
		||||
					data: [
 | 
			
		||||
						{
 | 
			
		||||
							name: '无数据',
 | 
			
		||||
							value: [0, 1696694400000, 1696780800000, 0],
 | 
			
		||||
							tooltip: { show: false },
 | 
			
		||||
							// silent: true,
 | 
			
		||||
							// animation: false,
 | 
			
		||||
							// universalTransition: { enable: false },
 | 
			
		||||
							// hoverAnimation: false,
 | 
			
		||||
							// selectMode: true,
 | 
			
		||||
							// select: { disabled: true },
 | 
			
		||||
							// emphasis: { disabled: false, focus: 'none', itemStyle: { opacity: 0 } },
 | 
			
		||||
							// z: 0,
 | 
			
		||||
							// zlevel: 0,
 | 
			
		||||
							// emphasis: { disabled: true },
 | 
			
		||||
							itemStyle: {
 | 
			
		||||
								color: '#ccc',
 | 
			
		||||
								opacity: 0.3,
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					]
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					name: '设备1',
 | 
			
		||||
					xAxisIndex: 0,
 | 
			
		||||
					yAxisIndex: 0,
 | 
			
		||||
					type: 'custom',
 | 
			
		||||
					renderItem: renderItem,
 | 
			
		||||
					itemStyle: {
 | 
			
		||||
						opacity: 0.8,
 | 
			
		||||
					},
 | 
			
		||||
					encode: {
 | 
			
		||||
						x: [1, 2],
 | 
			
		||||
						y: 0,
 | 
			
		||||
					},
 | 
			
		||||
					data: [
 | 
			
		||||
						{
 | 
			
		||||
							name: '运行',
 | 
			
		||||
							value: [0, 1696694400000, 1696699400000, 0],
 | 
			
		||||
							itemStyle: {
 | 
			
		||||
								normal: {
 | 
			
		||||
									color: types[0].color,
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							{
 | 
			
		||||
								// 5:00 ~ 8:00
 | 
			
		||||
								name: '故障',
 | 
			
		||||
								value: [0, 1695762000000, 1695772800000, 0],
 | 
			
		||||
								itemStyle: {
 | 
			
		||||
									normal: {
 | 
			
		||||
										color: types[1].color,
 | 
			
		||||
									},
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							name: '运行',
 | 
			
		||||
							value: [0, 1696730000000, 1696734040450, 0],
 | 
			
		||||
							itemStyle: {
 | 
			
		||||
								normal: {
 | 
			
		||||
									color: types[0].color,
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							{
 | 
			
		||||
								// 8:00 ~ 8:39
 | 
			
		||||
								name: '计划停机',
 | 
			
		||||
								value: [0, 1695772800000, 1695775140000, 0],
 | 
			
		||||
								itemStyle: {
 | 
			
		||||
									normal: {
 | 
			
		||||
										color: types[2].color,
 | 
			
		||||
									},
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							name: '故障',
 | 
			
		||||
							value: [0, 1696737040000, 1696754040450, 0],
 | 
			
		||||
							itemStyle: {
 | 
			
		||||
								normal: {
 | 
			
		||||
									color: types[1].color,
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							{
 | 
			
		||||
								// 08:39 ~ 18:00
 | 
			
		||||
								name: '运行',
 | 
			
		||||
								value: [0, 1695775140000, 1695808800000, 0],
 | 
			
		||||
								itemStyle: {
 | 
			
		||||
									normal: {
 | 
			
		||||
										color: types[0].color,
 | 
			
		||||
									},
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							name: '计划停机',
 | 
			
		||||
							value: [0, 1696755000000, 1696759000000, 0],
 | 
			
		||||
							itemStyle: {
 | 
			
		||||
								normal: {
 | 
			
		||||
									color: types[2].color,
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							{
 | 
			
		||||
								// 18:00 ~ 23:30
 | 
			
		||||
								name: '计划停机',
 | 
			
		||||
								value: [0, 1695808800000, 1695828600000, 0],
 | 
			
		||||
								itemStyle: {
 | 
			
		||||
									normal: {
 | 
			
		||||
										color: types[2].color,
 | 
			
		||||
									},
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							name: '运行',
 | 
			
		||||
							value: [0, 1696759000000, 1696769000000, 0],
 | 
			
		||||
							itemStyle: {
 | 
			
		||||
								normal: {
 | 
			
		||||
									color: types[0].color,
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						],
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							name: '计划停机',
 | 
			
		||||
							value: [0, 1696769400000, 1696779000000, 0],
 | 
			
		||||
							itemStyle: {
 | 
			
		||||
								normal: {
 | 
			
		||||
									color: types[2].color,
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					],
 | 
			
		||||
				},
 | 
			
		||||
				// ***************** 添加第二个设备 *****************
 | 
			
		||||
				{
 | 
			
		||||
					// 沉默的背景
 | 
			
		||||
					xAxisIndex: 2,
 | 
			
		||||
					yAxisIndex: 2,
 | 
			
		||||
					type: 'custom',
 | 
			
		||||
					renderItem: renderItem,
 | 
			
		||||
					silent: true,
 | 
			
		||||
					itemStyle: {
 | 
			
		||||
						opacity: 0.8,
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
			};
 | 
			
		||||
					encode: {
 | 
			
		||||
						x: [1, 2],
 | 
			
		||||
						y: 0,
 | 
			
		||||
					},
 | 
			
		||||
					data: [
 | 
			
		||||
						{
 | 
			
		||||
							name: '无数据',
 | 
			
		||||
							value: [0, 1696694400000, 1696780800000, 0],
 | 
			
		||||
							tooltip: { show: false },
 | 
			
		||||
							// silent: true,
 | 
			
		||||
							// animation: false,
 | 
			
		||||
							// universalTransition: { enable: false },
 | 
			
		||||
							// hoverAnimation: false,
 | 
			
		||||
							// selectMode: true,
 | 
			
		||||
							// select: { disabled: true },
 | 
			
		||||
							// emphasis: { disabled: false, focus: 'none', itemStyle: { opacity: 0 } },
 | 
			
		||||
							// z: 0,
 | 
			
		||||
							// zlevel: 0,
 | 
			
		||||
							// emphasis: { disabled: true },
 | 
			
		||||
							itemStyle: {
 | 
			
		||||
								color: '#ccc',
 | 
			
		||||
								opacity: 0.3,
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					]
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					name: '设备2',
 | 
			
		||||
					xAxisIndex: 2,
 | 
			
		||||
					yAxisIndex: 2,
 | 
			
		||||
					type: 'custom',
 | 
			
		||||
					renderItem: renderItem,
 | 
			
		||||
					itemStyle: {
 | 
			
		||||
						opacity: 0.8,
 | 
			
		||||
					},
 | 
			
		||||
					encode: {
 | 
			
		||||
						x: [1, 2],
 | 
			
		||||
						y: 0,
 | 
			
		||||
					},
 | 
			
		||||
					data: [
 | 
			
		||||
						{
 | 
			
		||||
							name: '运行',
 | 
			
		||||
							value: [0, 1696694400000, 1696699400000, 0],
 | 
			
		||||
							itemStyle: {
 | 
			
		||||
								normal: {
 | 
			
		||||
									color: types[0].color,
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							// showBackground: true,
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							name: '运行',
 | 
			
		||||
							value: [0, 1696730000000, 1696734040450, 0],
 | 
			
		||||
							itemStyle: {
 | 
			
		||||
								normal: {
 | 
			
		||||
									color: types[0].color,
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							name: '故障',
 | 
			
		||||
							value: [0, 1696737040000, 1696754040450, 0],
 | 
			
		||||
							itemStyle: {
 | 
			
		||||
								normal: {
 | 
			
		||||
									color: types[1].color,
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							name: '计划停机',
 | 
			
		||||
							value: [0, 1696755000000, 1696759000000, 0],
 | 
			
		||||
							itemStyle: {
 | 
			
		||||
								normal: {
 | 
			
		||||
									color: types[2].color,
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							name: '运行',
 | 
			
		||||
							value: [0, 1696759000000, 1696769000000, 0],
 | 
			
		||||
							itemStyle: {
 | 
			
		||||
								normal: {
 | 
			
		||||
									color: types[0].color,
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							name: '计划停机',
 | 
			
		||||
							value: [0, 1696769400000, 1696779000000, 0],
 | 
			
		||||
							itemStyle: {
 | 
			
		||||
								normal: {
 | 
			
		||||
									color: types[2].color,
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					],
 | 
			
		||||
				},
 | 
			
		||||
			],
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
			const el = document.getElementById('app');
 | 
			
		||||
			const myChart = echarts.init(el);
 | 
			
		||||
		const el = document.getElementById('app');
 | 
			
		||||
		const myChart = echarts.init(el);
 | 
			
		||||
 | 
			
		||||
			console.log('mychart', myChart);
 | 
			
		||||
			myChart.setOption(option);
 | 
			
		||||
		</script>
 | 
			
		||||
	</body>
 | 
			
		||||
</html>
 | 
			
		||||
		console.log('mychart', myChart);
 | 
			
		||||
		myChart.setOption(option);
 | 
			
		||||
	</script>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
@@ -1,235 +0,0 @@
 | 
			
		||||
import * as echarts from 'echarts';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function renderItem(params, api) {
 | 
			
		||||
    var categoryIndex = api.value(0);
 | 
			
		||||
    var start = api.coord([api.value(1), categoryIndex]);
 | 
			
		||||
    var end = api.coord([api.value(2), categoryIndex]);
 | 
			
		||||
    var height = api.size([0, 1])[1] * 1;
 | 
			
		||||
    // var height = api.size([0, 1])[1] * 0.8;
 | 
			
		||||
    // var height = 56;
 | 
			
		||||
    var rectShape = echarts.graphic.clipRectByRect(
 | 
			
		||||
        {
 | 
			
		||||
            x: start[0],
 | 
			
		||||
            y: start[1] - height / 2,
 | 
			
		||||
            width: end[0] - start[0],
 | 
			
		||||
            height: height,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            x: params.coordSys.x,
 | 
			
		||||
            y: params.coordSys.y,
 | 
			
		||||
            width: params.coordSys.width,
 | 
			
		||||
            height: params.coordSys.height,
 | 
			
		||||
        }
 | 
			
		||||
    );
 | 
			
		||||
    return (
 | 
			
		||||
        rectShape && {
 | 
			
		||||
            type: 'rect',
 | 
			
		||||
            transition: ['shape'],
 | 
			
		||||
            shape: rectShape,
 | 
			
		||||
            style: api.style(),
 | 
			
		||||
        }
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** 颜色配置 */
 | 
			
		||||
const types = [
 | 
			
		||||
    { name: '运行', color: '#5ad8a6' },
 | 
			
		||||
    { name: '故障', color: '#fc9c91' },
 | 
			
		||||
    { name: '计划停机', color: '#000' },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** 从时间戳获取 startTime */
 | 
			
		||||
function getStartTime(timestamp) {
 | 
			
		||||
    return new Date(new Date(timestamp).toLocaleDateString()).getTime();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export default class GanttGraph {
 | 
			
		||||
    constructor(el) {
 | 
			
		||||
        this.chart = null;
 | 
			
		||||
        this.el = el;
 | 
			
		||||
        /** 默认配置 */
 | 
			
		||||
        this.grid = {
 | 
			
		||||
            top: 32,
 | 
			
		||||
            left: 128,
 | 
			
		||||
            right: 128,
 | 
			
		||||
            bottom: 64,
 | 
			
		||||
        }
 | 
			
		||||
        this.tooltip = {
 | 
			
		||||
            formatter: function (params) {
 | 
			
		||||
                return (
 | 
			
		||||
                    params.marker +
 | 
			
		||||
                    params.name +
 | 
			
		||||
                    ': ' +
 | 
			
		||||
                    new Date(params.value[1]).toLocaleTimeString() +
 | 
			
		||||
                    ' - ' +
 | 
			
		||||
                    new Date(params.value[2]).toLocaleTimeString()
 | 
			
		||||
                );
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
        this.xAxis = {
 | 
			
		||||
            type: 'time',
 | 
			
		||||
            min: getStartTime(1691568181000), // <===
 | 
			
		||||
            max: getStartTime(1691568181000 + 3600 * 24 * 1000), // <===
 | 
			
		||||
            splitNumber: 10,
 | 
			
		||||
            axisLabel: {
 | 
			
		||||
                // rotate: -15,
 | 
			
		||||
                formatter: function (val) {
 | 
			
		||||
                    return new Date(val).toLocaleTimeString();
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
            axisTick: {
 | 
			
		||||
                show: true,
 | 
			
		||||
            },
 | 
			
		||||
            splitLine: {
 | 
			
		||||
                show: false,
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
        this.yAxis = [
 | 
			
		||||
            {
 | 
			
		||||
                interval: 40,
 | 
			
		||||
                axisLine: {
 | 
			
		||||
                    lineStyle: {
 | 
			
		||||
                        color: '',
 | 
			
		||||
                    },
 | 
			
		||||
                },
 | 
			
		||||
                axisLabel: {
 | 
			
		||||
                    fontSize: 18,
 | 
			
		||||
                },
 | 
			
		||||
                axisTick: {
 | 
			
		||||
                    show: false,
 | 
			
		||||
                },
 | 
			
		||||
                splitLine: {
 | 
			
		||||
                    show: true,
 | 
			
		||||
                },
 | 
			
		||||
                // data: [], // <====
 | 
			
		||||
                data: ['设备1', '设备2', '设备3', '设备4'],
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                axisLine: {
 | 
			
		||||
                    lineStyle: {
 | 
			
		||||
                        color: '',
 | 
			
		||||
                    },
 | 
			
		||||
                },
 | 
			
		||||
                data: [],
 | 
			
		||||
            },
 | 
			
		||||
        ]
 | 
			
		||||
        this.series = [
 | 
			
		||||
            {
 | 
			
		||||
                type: 'custom',
 | 
			
		||||
                renderItem: renderItem,
 | 
			
		||||
                itemStyle: {
 | 
			
		||||
                    opacity: 0.8,
 | 
			
		||||
                },
 | 
			
		||||
                encode: {
 | 
			
		||||
                    x: [1, 2],
 | 
			
		||||
                    y: 0,
 | 
			
		||||
                },
 | 
			
		||||
                // data: [], // <===
 | 
			
		||||
                data: [
 | 
			
		||||
                    {
 | 
			
		||||
                        name: '运行',
 | 
			
		||||
                        value: [
 | 
			
		||||
                            0,
 | 
			
		||||
                            1691568181000,
 | 
			
		||||
                            1691568181000 + 60 * 60 * 1000,
 | 
			
		||||
                            60 * 10 * 1000,
 | 
			
		||||
                        ],
 | 
			
		||||
                        itemStyle: {
 | 
			
		||||
                            normal: {
 | 
			
		||||
                                color: types[0].color,
 | 
			
		||||
                            },
 | 
			
		||||
                        },
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        name: '计划停机',
 | 
			
		||||
                        value: [
 | 
			
		||||
                            0,
 | 
			
		||||
                            1691578581000,
 | 
			
		||||
                            1691578581000 + 10 * 60 * 1000,
 | 
			
		||||
                            60 * 10 * 1000,
 | 
			
		||||
                        ],
 | 
			
		||||
                        itemStyle: {
 | 
			
		||||
                            normal: {
 | 
			
		||||
                                color: types[2].color,
 | 
			
		||||
                            },
 | 
			
		||||
                        },
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        name: '运行',
 | 
			
		||||
                        value: [
 | 
			
		||||
                            1,
 | 
			
		||||
                            1691568181000,
 | 
			
		||||
                            1691568181000 + 60 * 60 * 1000,
 | 
			
		||||
                            60 * 10 * 1000,
 | 
			
		||||
                        ],
 | 
			
		||||
                        itemStyle: {
 | 
			
		||||
                            normal: {
 | 
			
		||||
                                color: types[0].color,
 | 
			
		||||
                            },
 | 
			
		||||
                        },
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        name: '故障',
 | 
			
		||||
                        value: [
 | 
			
		||||
                            2,
 | 
			
		||||
                            1691538181000,
 | 
			
		||||
                            1691538181000 + 60 * 60 * 1000,
 | 
			
		||||
                            60 * 10 * 1000,
 | 
			
		||||
                        ],
 | 
			
		||||
                        itemStyle: {
 | 
			
		||||
                            normal: {
 | 
			
		||||
                                color: types[1].color,
 | 
			
		||||
                            },
 | 
			
		||||
                        },
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        name: '运行',
 | 
			
		||||
                        value: [
 | 
			
		||||
                            2,
 | 
			
		||||
                            1691578181000,
 | 
			
		||||
                            1691578181000 + 90 * 60 * 1000,
 | 
			
		||||
                            90 * 10 * 1000,
 | 
			
		||||
                        ],
 | 
			
		||||
                        itemStyle: {
 | 
			
		||||
                            normal: {
 | 
			
		||||
                                color: types[0].color,
 | 
			
		||||
                            },
 | 
			
		||||
                        },
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        name: '计划停机',
 | 
			
		||||
                        value: [
 | 
			
		||||
                            3,
 | 
			
		||||
                            1691528181000,
 | 
			
		||||
                            1691528181000 + 240 * 60 * 1000,
 | 
			
		||||
                            240 * 10 * 1000,
 | 
			
		||||
                        ],
 | 
			
		||||
                        itemStyle: {
 | 
			
		||||
                            normal: {
 | 
			
		||||
                                color: types[2].color,
 | 
			
		||||
                            },
 | 
			
		||||
                        },
 | 
			
		||||
                    },
 | 
			
		||||
                ],
 | 
			
		||||
            },
 | 
			
		||||
        ]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    init() {
 | 
			
		||||
        this.chart = echarts.init(this.el);
 | 
			
		||||
        this.chart.setOption(this.getOption())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getOption() {
 | 
			
		||||
        const { grid, xAxis, yAxis, series, tooltip } = this;
 | 
			
		||||
        return {
 | 
			
		||||
            grid, xAxis, yAxis, series, tooltip
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -6,31 +6,19 @@
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div
 | 
			
		||||
		class="status-timegraph-container"
 | 
			
		||||
		style="background: #f2f4f9; flex: 1; display: flex; flex-direction: column">
 | 
			
		||||
		<el-row
 | 
			
		||||
			class=""
 | 
			
		||||
			style="
 | 
			
		||||
	<div class="status-timegraph-container" style="background: #f2f4f9; flex: 1; display: flex; flex-direction: column">
 | 
			
		||||
		<el-row class="" style="
 | 
			
		||||
				margin-bottom: 12px;
 | 
			
		||||
				background: #fff;
 | 
			
		||||
				padding: 16px 16px 0;
 | 
			
		||||
				border-radius: 8px;
 | 
			
		||||
			">
 | 
			
		||||
			<div class="blue-title">生产节拍时序图</div>
 | 
			
		||||
			<!-- <h1>设备状态时序图</h1> -->
 | 
			
		||||
			<!-- 搜索工作栏 -->
 | 
			
		||||
			<SearchBar
 | 
			
		||||
				:formConfigs="searchBarFormConfig"
 | 
			
		||||
				ref="search-bar"
 | 
			
		||||
				:remove-blue="true"
 | 
			
		||||
				@select-changed="handleSearchBarSelectChange"
 | 
			
		||||
				@headBtnClick="handleSearchBarBtnClick" />
 | 
			
		||||
			<SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" :remove-blue="true"
 | 
			
		||||
				@select-changed="handleSearchBarSelectChange" @headBtnClick="handleSearchBarBtnClick" />
 | 
			
		||||
		</el-row>
 | 
			
		||||
 | 
			
		||||
		<el-row
 | 
			
		||||
			class=""
 | 
			
		||||
			style="
 | 
			
		||||
		<el-row class="" style="
 | 
			
		||||
				height: 1px;
 | 
			
		||||
				flex: 1;
 | 
			
		||||
				margin-bottom: 12px;
 | 
			
		||||
@@ -49,66 +37,34 @@
 | 
			
		||||
						<div class="icon running"></div>
 | 
			
		||||
						<div>运行中</div>
 | 
			
		||||
					</div>
 | 
			
		||||
					<!-- <div class="legend">
 | 
			
		||||
					<div class="icon waiting"></div>
 | 
			
		||||
					<div>待机</div>
 | 
			
		||||
				</div> -->
 | 
			
		||||
					<div class="legend">
 | 
			
		||||
						<div class="icon fault"></div>
 | 
			
		||||
						<div>故障</div>
 | 
			
		||||
					</div>
 | 
			
		||||
					<!-- <div class="legend">
 | 
			
		||||
					<div class="icon lack"></div>
 | 
			
		||||
					<div>缺料</div>
 | 
			
		||||
				</div>
 | 
			
		||||
				<div class="legend">
 | 
			
		||||
					<div class="icon full"></div>
 | 
			
		||||
					<div>满料</div>
 | 
			
		||||
				</div> -->
 | 
			
		||||
					<div class="legend">
 | 
			
		||||
						<div class="icon stop"></div>
 | 
			
		||||
						<div>计划停机</div>
 | 
			
		||||
					</div>
 | 
			
		||||
				</el-col>
 | 
			
		||||
			</el-row>
 | 
			
		||||
			<div
 | 
			
		||||
				class="main-area"
 | 
			
		||||
				style="flex: 1; display: flex; flex-direction: column">
 | 
			
		||||
				<div
 | 
			
		||||
					class="graphs"
 | 
			
		||||
					v-show="graphList.length"
 | 
			
		||||
					id="status-chart"
 | 
			
		||||
					style="height: 1px; flex: 1"></div>
 | 
			
		||||
			<div class="main-area" style="flex: 1; display: flex; flex-direction: column">
 | 
			
		||||
				<div class="graphs" v-show="graphList.length" id="status-chart" style="height: 1px; flex: 1"></div>
 | 
			
		||||
				<h2 v-if="!graphList || graphList.length == 0" class="no-data-bg"></h2>
 | 
			
		||||
			</div>
 | 
			
		||||
		</el-row>
 | 
			
		||||
 | 
			
		||||
		<!-- 对话框(添加 / 修改) -->
 | 
			
		||||
		<base-dialog
 | 
			
		||||
			dialogTitle="添加设备"
 | 
			
		||||
			:dialogVisible="open"
 | 
			
		||||
			width="500px"
 | 
			
		||||
			@close="open = false"
 | 
			
		||||
			@cancel="open = false"
 | 
			
		||||
		<base-dialog dialogTitle="添加设备" :dialogVisible="open" width="500px" @close="open = false" @cancel="open = false"
 | 
			
		||||
			@confirm="submitForm">
 | 
			
		||||
			<el-select
 | 
			
		||||
				v-if="open"
 | 
			
		||||
				style="width: 100%"
 | 
			
		||||
				v-model="queryParams.equipmentId"
 | 
			
		||||
				placeholder="请选择一个设备">
 | 
			
		||||
				<el-option
 | 
			
		||||
					v-for="eq in eqList"
 | 
			
		||||
					:key="eq.id"
 | 
			
		||||
					:value="eq.id"
 | 
			
		||||
					:label="eq.name"></el-option>
 | 
			
		||||
			<el-select v-if="open" style="width: 100%" v-model="queryParams.equipmentId" placeholder="请选择一个设备">
 | 
			
		||||
				<el-option v-for="eq in eqList" :key="eq.id" :value="eq.id" :label="eq.name"></el-option>
 | 
			
		||||
			</el-select>
 | 
			
		||||
		</base-dialog>
 | 
			
		||||
	</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
// import * as echarts from 'echarts';
 | 
			
		||||
import Gantt from './gantt';
 | 
			
		||||
import Gantt from './chart';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'SGStatus',
 | 
			
		||||
@@ -169,6 +125,7 @@ export default {
 | 
			
		||||
				recordTime: null,
 | 
			
		||||
			},
 | 
			
		||||
			graphList: [],
 | 
			
		||||
			existingEquipments: [],
 | 
			
		||||
			open: false,
 | 
			
		||||
			eqList: [],
 | 
			
		||||
			startTime: null,
 | 
			
		||||
@@ -202,15 +159,19 @@ export default {
 | 
			
		||||
		this.initEquipment();
 | 
			
		||||
		// this.getList();
 | 
			
		||||
	},
 | 
			
		||||
	mounted() {},
 | 
			
		||||
	mounted() { },
 | 
			
		||||
	watch: {
 | 
			
		||||
		graphList: {
 | 
			
		||||
			handler(val) {
 | 
			
		||||
				if (val && val.length) {
 | 
			
		||||
					this.$nextTick(() => {
 | 
			
		||||
						if (!this.chart) this.initChart();
 | 
			
		||||
						this.setInitialConfig();
 | 
			
		||||
						this.handleGraphList();
 | 
			
		||||
						if (!this.gantt) {
 | 
			
		||||
							this.gantt = new Gantt('#status-chart', this.startTime);
 | 
			
		||||
							this.gantt.init(val);
 | 
			
		||||
							return;
 | 
			
		||||
						}
 | 
			
		||||
						this.gantt.update(val);
 | 
			
		||||
 | 
			
		||||
					});
 | 
			
		||||
				}
 | 
			
		||||
				return;
 | 
			
		||||
@@ -220,43 +181,6 @@ export default {
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		setInitialConfig() {
 | 
			
		||||
			console.log('in setInitialConfig', this.chartOption);
 | 
			
		||||
			this.chart.setOption(this.chartOption);
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleGraphList() {
 | 
			
		||||
			console.log('in handleGraphList:', this.graphList);
 | 
			
		||||
			return;
 | 
			
		||||
			const min = this.queryParams.recordTime
 | 
			
		||||
				? new Date(this.queryParams.recordTime).getTime()
 | 
			
		||||
				: this.findMin();
 | 
			
		||||
 | 
			
		||||
			console.log('min is', min);
 | 
			
		||||
			this.chartOption.xAxis.min = getStartTime(min);
 | 
			
		||||
			this.chartOption.xAxis.max = getStartTime(min + 3600 * 24 * 1000);
 | 
			
		||||
			this.graphList.forEach((arr) => {
 | 
			
		||||
				this.chartOption.yAxis[0].data.push(arr.key);
 | 
			
		||||
				arr.forEach((item) => {
 | 
			
		||||
					this.chartOption.series[0].data.push({
 | 
			
		||||
						name: ['运行', '故障', '计划停机'][item.status],
 | 
			
		||||
						value: [
 | 
			
		||||
							0,
 | 
			
		||||
							item.startTime,
 | 
			
		||||
							item.startTime + item.duration * 60 * 1000,
 | 
			
		||||
							item.duration * 60 * 1000,
 | 
			
		||||
						],
 | 
			
		||||
						itemStyle: {
 | 
			
		||||
							normal: {
 | 
			
		||||
								color: types[item.status].color,
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					});
 | 
			
		||||
				});
 | 
			
		||||
				console.log('chartOptions', this.chartOption);
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		findMin() {
 | 
			
		||||
			let min = 0;
 | 
			
		||||
			this.graphList.forEach((arr) => {
 | 
			
		||||
@@ -267,12 +191,6 @@ export default {
 | 
			
		||||
			return min;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		initChart() {
 | 
			
		||||
			const el = document.getElementById('status-chart');
 | 
			
		||||
			this.gantt = new Gantt(el);
 | 
			
		||||
			this.gantt.init();
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 重置查询条件 */
 | 
			
		||||
		initQuery() {
 | 
			
		||||
			this.queryParams.lineId = null;
 | 
			
		||||
@@ -297,8 +215,8 @@ export default {
 | 
			
		||||
				params: this.queryParams,
 | 
			
		||||
			});
 | 
			
		||||
			if (code == 0) {
 | 
			
		||||
				this.existingEquipments = Object.values(data).map((eq) => eq[0].equipmentId);
 | 
			
		||||
				this.graphList = this.objectToArray(data);
 | 
			
		||||
				console.log('graph list', this.graphList);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
@@ -384,27 +302,26 @@ export default {
 | 
			
		||||
						return;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					this.startTime = new Date(payload.recordTime).getTime();
 | 
			
		||||
 | 
			
		||||
					this.startTime = new Date(payload.recordTime)
 | 
			
		||||
					this.queryParams.lineId = payload.lineId || null;
 | 
			
		||||
					this.queryParams.sectionId = payload.sectionId || null;
 | 
			
		||||
					this.queryParams.equipmentId = payload.equipmentId || null;
 | 
			
		||||
					this.queryParams.recordTime = payload.recordTime
 | 
			
		||||
						? [
 | 
			
		||||
								payload.recordTime,
 | 
			
		||||
								new Date(
 | 
			
		||||
									new Date(payload.recordTime).getTime() + 24 * 3600 * 1000
 | 
			
		||||
								)
 | 
			
		||||
									.toLocaleDateString()
 | 
			
		||||
									.split('/')
 | 
			
		||||
									.map((value, index) => {
 | 
			
		||||
										if (index == 1 || index == 2) {
 | 
			
		||||
											return value.padStart(2, '0');
 | 
			
		||||
										}
 | 
			
		||||
										return value;
 | 
			
		||||
									})
 | 
			
		||||
									.join('-') + ' 00:00:00',
 | 
			
		||||
						  ]
 | 
			
		||||
							payload.recordTime,
 | 
			
		||||
							new Date(
 | 
			
		||||
								new Date(payload.recordTime).getTime() + 24 * 3600 * 1000
 | 
			
		||||
							)
 | 
			
		||||
								.toLocaleDateString()
 | 
			
		||||
								.split('/')
 | 
			
		||||
								.map((value, index) => {
 | 
			
		||||
									if (index == 1 || index == 2) {
 | 
			
		||||
										return value.padStart(2, '0');
 | 
			
		||||
									}
 | 
			
		||||
									return value;
 | 
			
		||||
								})
 | 
			
		||||
								.join('-') + ' 00:00:00',
 | 
			
		||||
						]
 | 
			
		||||
						: null;
 | 
			
		||||
					this.getList();
 | 
			
		||||
					break;
 | 
			
		||||
@@ -415,6 +332,10 @@ export default {
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		async submitForm() {
 | 
			
		||||
			if (this.existingEquipments.indexOf(this.queryParams.equipmentId) >= 0) {
 | 
			
		||||
				this.$message.error('该设备已存在');
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			const { code, data } = await this.$axios({
 | 
			
		||||
				url: '/analysis/equipment-analysis/status',
 | 
			
		||||
				method: 'get',
 | 
			
		||||
@@ -523,7 +444,7 @@ export default {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.running {
 | 
			
		||||
	background-color: #5ad8a6;
 | 
			
		||||
	background-color: #288AFF;
 | 
			
		||||
	// background-color: #84f04e;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -534,7 +455,7 @@ export default {
 | 
			
		||||
 | 
			
		||||
.fault {
 | 
			
		||||
	// background-color: #ea5b5b;
 | 
			
		||||
	background-color: #fc9c91;
 | 
			
		||||
	background-color: #FC9C91;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.full {
 | 
			
		||||
@@ -548,7 +469,7 @@ export default {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.stop {
 | 
			
		||||
	background-color: #000;
 | 
			
		||||
	background-color: #FFDC94;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.legend-row {
 | 
			
		||||
@@ -557,7 +478,7 @@ export default {
 | 
			
		||||
	display: flex;
 | 
			
		||||
	justify-content: flex-end;
 | 
			
		||||
 | 
			
		||||
	> .legend:not(:last-child) {
 | 
			
		||||
	>.legend:not(:last-child) {
 | 
			
		||||
		margin-right: 12px;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -600,7 +521,7 @@ export default {
 | 
			
		||||
	background: #ccc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.echarts__status-chart > div {
 | 
			
		||||
.echarts__status-chart>div {
 | 
			
		||||
	height: 100% !important;
 | 
			
		||||
	width: 100% !important;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -35,8 +35,7 @@
 | 
			
		||||
					" />
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div v-else style="margin-top: 20px; color: #c7c7c7; text-align: center">
 | 
			
		||||
			暂无数据
 | 
			
		||||
		<div v-else class="no-data-bg">
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
</template>
 | 
			
		||||
 
 | 
			
		||||
@@ -45,7 +45,7 @@ export default {
 | 
			
		||||
					axisLine: {
 | 
			
		||||
						show: true,
 | 
			
		||||
						lineStyle: {
 | 
			
		||||
							color: '#ccc',
 | 
			
		||||
							color: '#777',
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					axisTick: {
 | 
			
		||||
@@ -63,7 +63,7 @@ export default {
 | 
			
		||||
					axisLine: {
 | 
			
		||||
						show: true,
 | 
			
		||||
						lineStyle: {
 | 
			
		||||
							color: '#ccc',
 | 
			
		||||
							color: '#777',
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					name: '数量',
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,13 @@
 | 
			
		||||
							:data-value="fc.id"
 | 
			
		||||
							class="factory-list__item"
 | 
			
		||||
							:class="{ 'is-current': fc.id == currentFactory?.id }">
 | 
			
		||||
							{{ fc.label }}
 | 
			
		||||
							<span>
 | 
			
		||||
								{{ fc.label }}
 | 
			
		||||
							</span>
 | 
			
		||||
							<svg-icon
 | 
			
		||||
								v-if="fc.id == currentFactory?.id"
 | 
			
		||||
								icon-class="Confirm"
 | 
			
		||||
								style="height: 14px; width: 14px" />
 | 
			
		||||
						</li>
 | 
			
		||||
					</ul>
 | 
			
		||||
					<div v-else style="color: #0008; width: 128px; text-align: center">
 | 
			
		||||
@@ -93,15 +99,7 @@
 | 
			
		||||
										v-if="list.length"
 | 
			
		||||
										:equipment-list="list"
 | 
			
		||||
										:render="renderKey" />
 | 
			
		||||
									<div
 | 
			
		||||
										v-if="list.length == 0"
 | 
			
		||||
										style="
 | 
			
		||||
											color: #c7c7c7;
 | 
			
		||||
											text-align: center;
 | 
			
		||||
											margin-top: 20px;
 | 
			
		||||
										">
 | 
			
		||||
										没有设备
 | 
			
		||||
									</div>
 | 
			
		||||
									<div v-if="list.length == 0" class="no-data-bg"></div>
 | 
			
		||||
								</div>
 | 
			
		||||
							</el-tab-pane>
 | 
			
		||||
						</el-tabs>
 | 
			
		||||
@@ -507,9 +505,12 @@ li {
 | 
			
		||||
.factory-list__item {
 | 
			
		||||
	font-size: 16px;
 | 
			
		||||
	line-height: 1;
 | 
			
		||||
	padding: 8px 64px 8px 16px;
 | 
			
		||||
	/* min-width: 64px; */
 | 
			
		||||
	padding: 8px 16px 8px 16px;
 | 
			
		||||
	min-width: 128px;
 | 
			
		||||
	position: relative;
 | 
			
		||||
	display: flex;
 | 
			
		||||
	align-items: center;
 | 
			
		||||
	justify-content: space-between;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.factory-list__item:hover,
 | 
			
		||||
@@ -518,13 +519,13 @@ li {
 | 
			
		||||
	color: #0b58ff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.factory-list__item.is-current::after {
 | 
			
		||||
/* .factory-list__item.is-current::after {
 | 
			
		||||
	content: '√';
 | 
			
		||||
	position: absolute;
 | 
			
		||||
	top: 8px;
 | 
			
		||||
	right: 16px;
 | 
			
		||||
	font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
} */
 | 
			
		||||
 | 
			
		||||
.custom-tree-class >>> .el-tree-node__content {
 | 
			
		||||
	width: 100%;
 | 
			
		||||
@@ -551,8 +552,8 @@ li {
 | 
			
		||||
.custom-icon-class {
 | 
			
		||||
	margin-right: 8px;
 | 
			
		||||
	width: 20px;
 | 
			
		||||
	height: 24px;
 | 
			
		||||
	background: url('../../../assets/images/tree-icon-1.png') 100% / contain
 | 
			
		||||
	height: 20px;
 | 
			
		||||
	background: url('../../../assets/images/Qian.png') center center / contain
 | 
			
		||||
		no-repeat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -116,7 +116,7 @@ export default {
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					_action: 'params-monitor',
 | 
			
		||||
					label: '参数监控',
 | 
			
		||||
					label: '操作',
 | 
			
		||||
					subcomponent: {
 | 
			
		||||
						props: ['injectData'],
 | 
			
		||||
						render: function (h) {
 | 
			
		||||
@@ -136,7 +136,7 @@ export default {
 | 
			
		||||
										},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
								'查看监控'
 | 
			
		||||
								'查看详情'
 | 
			
		||||
							);
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										271
									
								
								src/views/print/design.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								src/views/print/design.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,271 @@
 | 
			
		||||
<!-- 
 | 
			
		||||
    filename: design.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-10-07 13:14:40
 | 
			
		||||
    description: 设计打印模板
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="print-design">
 | 
			
		||||
		<section id="menu">
 | 
			
		||||
			<NavMenu @action="handleAction" :menu="menu" />
 | 
			
		||||
		</section>
 | 
			
		||||
		<section id="main-panel">
 | 
			
		||||
			<section id="left-panel" v-drag="'right'">
 | 
			
		||||
				<h2>组件</h2>
 | 
			
		||||
				<div id="components"></div>
 | 
			
		||||
			</section>
 | 
			
		||||
			<section id="edit-panel"></section>
 | 
			
		||||
			<section id="right-panel">
 | 
			
		||||
				<h2>设置</h2>
 | 
			
		||||
				<div id="settings"></div>
 | 
			
		||||
			</section>
 | 
			
		||||
		</section>
 | 
			
		||||
	</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import vDrag from './drag'
 | 
			
		||||
import { hiprint, defaultElementTypeProvider } from "vue-plugin-hiprint";
 | 
			
		||||
hiprint.init({
 | 
			
		||||
	providers: [defaultElementTypeProvider()],
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const NavSelector = {
 | 
			
		||||
	name: 'NavSelector',
 | 
			
		||||
	props: ['name', 'options'],
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			open: false,
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		handleOpen() {
 | 
			
		||||
			// this.$emit('closeOtherMenu', this)
 | 
			
		||||
			// this.$emit('hover', this)
 | 
			
		||||
			this.open = !this.open;
 | 
			
		||||
		},
 | 
			
		||||
		handleClickItem(e) {
 | 
			
		||||
			this.$emit('click', e.target.innerText)
 | 
			
		||||
		},
 | 
			
		||||
		// 暴露一个close方法,供父组件调用
 | 
			
		||||
		closeSubMenu() {
 | 
			
		||||
			this.open = false;
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	render: function (h) {
 | 
			
		||||
		return (
 | 
			
		||||
			<li class={'nav-selector__item'} onMouseenter={this.handleOpen} onMouseleave={this.handleOpen}>
 | 
			
		||||
				<span class={'nav-selector__name'}>{this.name}</span>
 | 
			
		||||
				<ul class={`${this.open ? '' : 'hidden'} nav-selector__submenu-items`}>
 | 
			
		||||
					{this.options.map((item) => {
 | 
			
		||||
						return <li onClick={this.handleClickItem}>{item}</li>;
 | 
			
		||||
					})}
 | 
			
		||||
				</ul>
 | 
			
		||||
			</li>
 | 
			
		||||
		);
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const NavMenu = {
 | 
			
		||||
	name: 'NavMenu',
 | 
			
		||||
	props: ['menu'],
 | 
			
		||||
	components: { NavSelector },
 | 
			
		||||
	data() {
 | 
			
		||||
		return {}
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		handleCloseOtherMenu(vueInstance) {
 | 
			
		||||
			this.$children.forEach(vm => {
 | 
			
		||||
				if (vm != vueInstance) {
 | 
			
		||||
					vm.closeSubMenu()
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
		},
 | 
			
		||||
		handleItemClicked(e) {
 | 
			
		||||
			this.$emit('action', e);
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	render: function (h) {
 | 
			
		||||
		return (
 | 
			
		||||
			<ul class={'nav-menu'}>
 | 
			
		||||
				{this.menu.map((item) => {
 | 
			
		||||
					return <NavSelector onClick={this.handleItemClicked} onCloseOtherMenu={this.handleCloseOtherMenu} name={item.name} options={item.options} />;
 | 
			
		||||
				})}
 | 
			
		||||
			</ul>
 | 
			
		||||
		);
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'PrintDesignPage',
 | 
			
		||||
	components: { NavMenu },
 | 
			
		||||
	props: {},
 | 
			
		||||
	directives: { drag: vDrag },
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			hiprintTemplate: null,
 | 
			
		||||
			menu: [
 | 
			
		||||
				{
 | 
			
		||||
					name: '菜单',
 | 
			
		||||
					options: ['新建', '打开', '保存', '另存为', '导出', '打印', '退出'],
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					name: '视图',
 | 
			
		||||
					options: ['编辑', '布局'],
 | 
			
		||||
				},
 | 
			
		||||
			],
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	computed: {},
 | 
			
		||||
	mounted() {
 | 
			
		||||
		this.loadSideBar();
 | 
			
		||||
		this.loadDesigner();
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		loadDesigner() {
 | 
			
		||||
			$("#edit-panel").empty();
 | 
			
		||||
			this.hiprintTemplate = new hiprint.PrintTemplate({
 | 
			
		||||
				settingContainer: "#settings",
 | 
			
		||||
			});
 | 
			
		||||
			this.hiprintTemplate.design("#edit-panel");
 | 
			
		||||
		},
 | 
			
		||||
		loadSideBar() {
 | 
			
		||||
			this.loadProviders();
 | 
			
		||||
			this.loadSettings();
 | 
			
		||||
		},
 | 
			
		||||
		loadProviders() { },
 | 
			
		||||
		loadSettings() { },
 | 
			
		||||
		handleAction(name) {
 | 
			
		||||
			console.log('name', name)
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="scss">
 | 
			
		||||
::-webkit-scrollbar {
 | 
			
		||||
	width: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-webkit-scrollbar-button {
 | 
			
		||||
	// background: red;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.print-design {
 | 
			
		||||
	height: 100vh;
 | 
			
		||||
	display: flex;
 | 
			
		||||
	flex-direction: column;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#main-panel {
 | 
			
		||||
	height: 1px;
 | 
			
		||||
	flex: 1;
 | 
			
		||||
	display: grid;
 | 
			
		||||
	grid-template-columns: 1fr 3fr 1fr;
 | 
			
		||||
	grid-auto-rows: 1fr;
 | 
			
		||||
	grid-template-areas: 'left main right';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#menu {
 | 
			
		||||
	// background: black;
 | 
			
		||||
	// color: white;
 | 
			
		||||
	background: #fff;
 | 
			
		||||
	border-bottom: 1px solid #ccc;
 | 
			
		||||
 | 
			
		||||
	>ul {
 | 
			
		||||
		// background: #32aa32;
 | 
			
		||||
		padding: 0;
 | 
			
		||||
		list-style: none;
 | 
			
		||||
		margin: 0;
 | 
			
		||||
		margin-left: 10px;
 | 
			
		||||
		display: flex;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#left-panel {
 | 
			
		||||
	overflow: auto;
 | 
			
		||||
	grid-area: left;
 | 
			
		||||
	background: #fff;
 | 
			
		||||
 | 
			
		||||
	h2 {
 | 
			
		||||
		margin: 0;
 | 
			
		||||
		font-weight: 400;
 | 
			
		||||
		padding: 4px 20px;
 | 
			
		||||
		border-bottom: 1px solid #ccc;
 | 
			
		||||
		background: #ccc;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#edit-panel {
 | 
			
		||||
	padding: 20px;
 | 
			
		||||
	overflow: auto;
 | 
			
		||||
	grid-area: main;
 | 
			
		||||
	justify-items: center;
 | 
			
		||||
	background: #fff;
 | 
			
		||||
	border-left: 1px solid #ccc;
 | 
			
		||||
	border-right: 1px solid #ccc;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#right-panel {
 | 
			
		||||
	overflow: auto;
 | 
			
		||||
	grid-area: right;
 | 
			
		||||
	background: #fff;
 | 
			
		||||
 | 
			
		||||
	h2 {
 | 
			
		||||
		margin: 0;
 | 
			
		||||
		font-weight: 400;
 | 
			
		||||
		padding: 4px 12px;
 | 
			
		||||
		border-bottom: 1px solid #ccc;
 | 
			
		||||
		background: #ccc;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
// 子组件的样式
 | 
			
		||||
.nav-selector__item {
 | 
			
		||||
	font-size: 18px;
 | 
			
		||||
	letter-spacing: 1px;
 | 
			
		||||
	// font-weight: 600;
 | 
			
		||||
	padding: 6px 12px;
 | 
			
		||||
	line-height: 1.25;
 | 
			
		||||
	position: relative;
 | 
			
		||||
	cursor: pointer;
 | 
			
		||||
 | 
			
		||||
	&:hover {
 | 
			
		||||
		background: #f1f1f1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ul {
 | 
			
		||||
		list-style: none;
 | 
			
		||||
		margin: 0;
 | 
			
		||||
		padding: 0;
 | 
			
		||||
		position: absolute;
 | 
			
		||||
		top: 100%;
 | 
			
		||||
		min-width: 128px;
 | 
			
		||||
		left: 0px;
 | 
			
		||||
		background: #fff;
 | 
			
		||||
		border: 1px solid #ccc;
 | 
			
		||||
		// border-radius: 4px;
 | 
			
		||||
		margin: 0;
 | 
			
		||||
		box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
 | 
			
		||||
		z-index: 100;
 | 
			
		||||
 | 
			
		||||
		li {
 | 
			
		||||
			padding: 6px 12px;
 | 
			
		||||
			cursor: pointer;
 | 
			
		||||
 | 
			
		||||
			&:hover {
 | 
			
		||||
				background: #f1f1f1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	.hidden {
 | 
			
		||||
		display: none;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										41
									
								
								src/views/print/drag.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/views/print/drag.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
.v-drag-border-left {
 | 
			
		||||
    border-left: 1px solid #ccc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.v-drag-border-left > div.pseudo-border { 
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    right: -2px;
 | 
			
		||||
    width: 4px;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    background: transparent;
 | 
			
		||||
    z-index: 1;
 | 
			
		||||
    transition: all linear 0.3s; 
 | 
			
		||||
    cursor: col-resize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.v-drag-border-left > div.pseudo-border:hover {
 | 
			
		||||
    background: #ccc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.v-drag-border-right {
 | 
			
		||||
    /* border-right: 1px solid #ccc; */
 | 
			
		||||
    position: relative;
 | 
			
		||||
    transition: width linear 0.3s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.v-drag-border-right > div.pseudo-border { 
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    right: -2px;
 | 
			
		||||
    width: 4px;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    background: transparent;
 | 
			
		||||
    z-index: 1;
 | 
			
		||||
    transition: all linear 0.3s; 
 | 
			
		||||
    cursor: col-resize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.v-drag-border-right > div.pseudo-border:hover {
 | 
			
		||||
    background: #ccc;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										96
									
								
								src/views/print/drag.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/views/print/drag.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
import './drag.css';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    bind(el, { name, value }, vnode) {
 | 
			
		||||
        switch (name) {
 | 
			
		||||
            case 'drag': {
 | 
			
		||||
                if (['left', 'right', 'top', 'bottom'].indexOf(value) == -1) return;
 | 
			
		||||
                // 创建边框子元素
 | 
			
		||||
                const border = document.createElement('div');
 | 
			
		||||
                border.classList.add("pseudo-border");
 | 
			
		||||
                el.appendChild(border);
 | 
			
		||||
                // 添加拖拽样式
 | 
			
		||||
                addDragStyle(el, value);
 | 
			
		||||
                // 添加拖拽事件
 | 
			
		||||
                addDragEvent(el, border);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    // inserted()
 | 
			
		||||
    // update()
 | 
			
		||||
    // componentUpdated()
 | 
			
		||||
    // unbind()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function addDragEvent(el, border, direction) {
 | 
			
		||||
    // border.setAttribute('draggable', true)
 | 
			
		||||
    const onMouseMove = function (e) {
 | 
			
		||||
        console.log('move', e);
 | 
			
		||||
    }
 | 
			
		||||
    const onMouseUp = function (e) {
 | 
			
		||||
        console.log('up')
 | 
			
		||||
        border.removeEventListener('mousemove', onMouseMove);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    border.addEventListener('mousedown', function (e) {
 | 
			
		||||
        console.log('down');
 | 
			
		||||
        document.body.removeEventListener('mouseup', onMouseUp)
 | 
			
		||||
        document.body.addEventListener('mouseup', onMouseUp)
 | 
			
		||||
        border.addEventListener('mousemove', onMouseMove);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // TODO: 有点bug
 | 
			
		||||
 | 
			
		||||
    // el.addEventListener('mousedown', function (e) {
 | 
			
		||||
    //     console.log('mousedown', e);
 | 
			
		||||
    //     const { clientX, clientY } = e;
 | 
			
		||||
    //     const { left, top, width, height } = el.getBoundingClientRect();
 | 
			
		||||
    //     const { offsetLeft, offsetTop } = el;
 | 
			
		||||
    //     const startX = clientX;
 | 
			
		||||
    //     const startY = clientY;
 | 
			
		||||
    //     const startLeft = left;
 | 
			
		||||
    //     const startTop = top;
 | 
			
		||||
    //     const startWidth = width;
 | 
			
		||||
    //     const startHeight = height;
 | 
			
		||||
    //     const startOffsetLeft = offsetLeft;
 | 
			
		||||
    //     const startOffsetTop = offsetTop;
 | 
			
		||||
    //     const move = function (e) {
 | 
			
		||||
    //         console.log('mousemove', e);
 | 
			
		||||
    //         const { clientX, clientY } = e;
 | 
			
		||||
    //         const offsetX = clientX - startX;
 | 
			
		||||
    //         const offsetY = clientY - startY;
 | 
			
		||||
    //         switch (direction) {
 | 
			
		||||
    //             case 'left': {
 | 
			
		||||
    //                 el.style.left = startLeft + offsetX + 'px';
 | 
			
		||||
    //                 el.style.width = startWidth - offsetX + 'px';
 | 
			
		||||
    //                 break;
 | 
			
		||||
    //             }
 | 
			
		||||
    //             case 'right': {
 | 
			
		||||
    //                 el.style.width = startWidth + offsetX + 'px';
 | 
			
		||||
    //                 break;
 | 
			
		||||
    //             }
 | 
			
		||||
    //             case 'top': {
 | 
			
		||||
    //                 el.style.top = startTop + offsetY + 'px';
 | 
			
		||||
    //                 el.style.height = startHeight - offsetY + 'px';
 | 
			
		||||
    //                 break;
 | 
			
		||||
    //             }
 | 
			
		||||
    //             case 'bottom': {
 | 
			
		||||
    //                 el.style.height = startHeight + offsetY + 'px';
 | 
			
		||||
    //                 break;
 | 
			
		||||
    //             }
 | 
			
		||||
    //         }
 | 
			
		||||
    //     }
 | 
			
		||||
    //     const up = function (e) {
 | 
			
		||||
    //         console.log('mouseup', e);
 | 
			
		||||
    //         document.removeEventListener('mousemove', move);
 | 
			
		||||
    //         document.removeEventListener('mouseup', up);
 | 
			
		||||
    //     }
 | 
			
		||||
    //     document.addEventListener('mousemove', move);
 | 
			
		||||
    //     document.addEventListener('mouseup', up);
 | 
			
		||||
    // });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function addDragStyle(el, direction) {
 | 
			
		||||
    el.classList.add('v-drag-border-' + direction)
 | 
			
		||||
}
 | 
			
		||||
@@ -9,10 +9,10 @@
 | 
			
		||||
	<el-form
 | 
			
		||||
		ref="form"
 | 
			
		||||
		:model="dataForm"
 | 
			
		||||
		label-width="100px"
 | 
			
		||||
		label-width="120px"
 | 
			
		||||
		v-loading="formLoading">
 | 
			
		||||
		<el-row :gutter="20">
 | 
			
		||||
			<el-col>
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="产线"
 | 
			
		||||
					prop="productionId"
 | 
			
		||||
@@ -30,7 +30,7 @@
 | 
			
		||||
					</el-select>
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
			</el-col>
 | 
			
		||||
			<el-col>
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="工段"
 | 
			
		||||
					prop="sectionId"
 | 
			
		||||
@@ -49,7 +49,7 @@
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
			</el-col>
 | 
			
		||||
 | 
			
		||||
			<el-col>
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="按钮盒识别码"
 | 
			
		||||
					prop="buttonId"
 | 
			
		||||
@@ -85,7 +85,7 @@
 | 
			
		||||
				</el-form-item> -->
 | 
			
		||||
			</el-col>
 | 
			
		||||
 | 
			
		||||
			<el-col>
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item label="按钮盒模式" prop="model">
 | 
			
		||||
					<el-input
 | 
			
		||||
						v-model="dataForm.model"
 | 
			
		||||
@@ -94,7 +94,7 @@
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
			</el-col>
 | 
			
		||||
 | 
			
		||||
			<el-col>
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item
 | 
			
		||||
					label="按钮值"
 | 
			
		||||
					prop="keyValue"
 | 
			
		||||
@@ -121,7 +121,7 @@
 | 
			
		||||
				</el-form-item>
 | 
			
		||||
			</el-col>
 | 
			
		||||
 | 
			
		||||
			<el-col>
 | 
			
		||||
			<el-col :span="12">
 | 
			
		||||
				<el-form-item label="检测内容" prop="inspectionDetContent">
 | 
			
		||||
					<el-input
 | 
			
		||||
						type="textarea"
 | 
			
		||||
 
 | 
			
		||||
@@ -75,8 +75,6 @@ export default {
 | 
			
		||||
							filterable: true,
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						select: true,
 | 
			
		||||
						label: '工段',
 | 
			
		||||
@@ -103,8 +101,8 @@ export default {
 | 
			
		||||
							},
 | 
			
		||||
						],
 | 
			
		||||
					},
 | 
			
		||||
					{ input: true, label: '按钮盒模式', prop: 'model' },
 | 
			
		||||
				],
 | 
			
		||||
				[{ input: true, label: '按钮盒模式', prop: 'model' }],
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						input: true,
 | 
			
		||||
@@ -121,8 +119,6 @@ export default {
 | 
			
		||||
						],
 | 
			
		||||
						bind: { type: 'number', min: 0, max: 100 },
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				[
 | 
			
		||||
					{
 | 
			
		||||
						textarea: true,
 | 
			
		||||
						label: '检测内容',
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,8 @@
 | 
			
		||||
		</DetailGraph> -->
 | 
			
		||||
		<!-- <DetailGraph id="dg3" key="dg3" ref="dg3" />
 | 
			
		||||
			<DetailGraph id="dg4" key="dg4" ref="dg4" /> -->
 | 
			
		||||
		<div v-if="!series || series.length == 0" style="color: #777; font-size: 16px; letter-spacing: 1px; text-align: center; padding-top: 56px; text-decoration: underline;">暂无数据</div>
 | 
			
		||||
		<!-- <div v-if="!series || series.length == 0" style="color: #777; font-size: 16px; letter-spacing: 1px; text-align: center; padding-top: 56px; text-decoration: underline;">暂无数据</div> -->
 | 
			
		||||
		<div v-if="!series || series.length == 0" class="no-data-bg" />
 | 
			
		||||
		<LineGraph
 | 
			
		||||
			v-else
 | 
			
		||||
			:x-props="lineData.xProps"
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="quality-container" style="background: #f2f4f9; flex: 1">
 | 
			
		||||
	<div class="quality-container" style="background: #f2f4f9; flex: 1; display: flex; flex-direction: column;">
 | 
			
		||||
		<el-row
 | 
			
		||||
			class=""
 | 
			
		||||
			style="
 | 
			
		||||
@@ -43,6 +43,7 @@
 | 
			
		||||
				background: #fff;
 | 
			
		||||
				padding: 12px 16px 16px;
 | 
			
		||||
				border-radius: 8px;
 | 
			
		||||
				flex: 1;
 | 
			
		||||
			">
 | 
			
		||||
			<el-row style="display: flex; align-items: center">
 | 
			
		||||
				<div class="blue-title">产线检测详细</div>
 | 
			
		||||
@@ -64,12 +65,13 @@
 | 
			
		||||
			<transition mode="out-in" name="fade-down">
 | 
			
		||||
				<template v-if="mode == 'table'">
 | 
			
		||||
					<base-table
 | 
			
		||||
						v-if="mode == 'table'"
 | 
			
		||||
						v-if="mode == 'table' && list.length"
 | 
			
		||||
						:table-props="tableProps"
 | 
			
		||||
						:page="queryParams.pageNo"
 | 
			
		||||
						:limit="queryParams.pageSize"
 | 
			
		||||
						:table-data="list"
 | 
			
		||||
						@emitFun="handleEmitFun"></base-table>
 | 
			
		||||
					<div v-else class="no-data-bg"></div>
 | 
			
		||||
				</template>
 | 
			
		||||
 | 
			
		||||
				<GraphPage
 | 
			
		||||
@@ -302,8 +304,8 @@ export default {
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					// width: 128,
 | 
			
		||||
					prop: 'ratio',
 | 
			
		||||
					label: '比例',
 | 
			
		||||
					prop: 'scrapRatio',
 | 
			
		||||
					label: '比例(%)',
 | 
			
		||||
					// subcomponent: {
 | 
			
		||||
					// 	name: 'TextOnly',
 | 
			
		||||
					// 	props: {
 | 
			
		||||
@@ -445,6 +447,7 @@ export default {
 | 
			
		||||
					inspectionContent: item.inspectionContent,
 | 
			
		||||
					...keyValuePairs,
 | 
			
		||||
					sumInput: item.sumInput,
 | 
			
		||||
					scrapRatio: item.scrapRatio,
 | 
			
		||||
				};
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user