update gantt
This commit is contained in:
		| @@ -0,0 +1,338 @@ | ||||
| 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) => { | ||||
|             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 = [] | ||||
|     xAxis = [] | ||||
|     yAxis = [] | ||||
|     series = [] | ||||
|  | ||||
|     constructor(data, startTime) { | ||||
|         this.gridIndex = 0; | ||||
|         this.currentXaxisId = null; | ||||
|         this.currentYaxisId = null; | ||||
|         // this.startTime = new Date(startTime); | ||||
|         this.startTime = new Date(new Date().toLocaleDateString()); | ||||
|         console.log('<> Gantt Created', this.startTime); | ||||
|  | ||||
|         this.grid.push(this.makeGrid()) | ||||
|         this.xAxis.push(...this.makeXaxis()) | ||||
|         this.yAxis.push(...this.makeYaxis("设备1")) | ||||
|         this.series.push(...this.makeSeries({ equipmentName: "设备1" })) | ||||
|  | ||||
|     } | ||||
|  | ||||
|     // 构造一个新的 grid | ||||
|     makeGrid() { | ||||
|         this.gridIndex++; | ||||
|         return { | ||||
|             id: 'GRID_' + this.gridIndex, | ||||
|             top: 12 + 64 * (this.gridIndex - 1), | ||||
|             right: 64, | ||||
|             height: 56 | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // 构造一个 xAxis | ||||
|     makeXaxis() { | ||||
|         const [id1, id2] = ['' + Math.random(), '' + Math.random()] | ||||
|         this.currentXaxisId = id1; | ||||
|         return [ | ||||
|             { | ||||
|                 id: id1, | ||||
|                 gridIndex: 'GRID_' + 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(':'); | ||||
|                     }, | ||||
|                 }, | ||||
|                 boundaryGap: false, | ||||
|                 // data: getXaxisRange(getTodayStart(new Date())), | ||||
|             }, | ||||
|             { | ||||
|                 id: id2, | ||||
|                 gridIndex: 'GRID_' + this.gridIndex, | ||||
|                 axisLabel: { show: false }, | ||||
|                 axisLine: { show: false }, | ||||
|             }, | ||||
|         ] | ||||
|     } | ||||
|  | ||||
|  | ||||
|     // 构造一个 yAxis | ||||
|     makeYaxis(equipmentName) { | ||||
|         const [id1, id2] = ['' + Math.random(), '' + Math.random()] | ||||
|         this.currentYaxisId = id1; | ||||
|         return [ | ||||
|             // 主y轴 | ||||
|             { | ||||
|                 id: id1, | ||||
|                 gridIndex: 'GRID_' +  this.gridIndex, | ||||
|                 type: 'value', | ||||
|                 splitLine: { show: false }, | ||||
|                 name: equipmentName, | ||||
|                 nameLocation: 'center', | ||||
|                 nameGap: 56, | ||||
|                 nameRotate: 0, | ||||
|                 nameTextStyle: { | ||||
|                     fontSize: 18, | ||||
|                 }, | ||||
|                 axisLine: { | ||||
|                     show: true, | ||||
|                     lineStyle: {}, | ||||
|                 }, | ||||
|                 axisLabel: { show: false }, | ||||
|                 axisTick: { show: false }, | ||||
|             }, | ||||
|             // 辅y轴 | ||||
|             { | ||||
|                 id: id2, | ||||
|                 gridIndex: 'GRID_' +  this.gridIndex, | ||||
|                 type: 'value', | ||||
|                 splitLine: { show: false }, | ||||
|                 axisLabel: { show: false }, | ||||
|                 axisTick: { show: false }, | ||||
|             }, | ||||
|         ] | ||||
|     } | ||||
|  | ||||
|     // 构造一个 series | ||||
|     makeSeries({ equipmentName }) { | ||||
|         const { currentXaxisId: xAxisIndex, currentYaxisId: yAxisIndex } = this; | ||||
|         const bgStartTime = this.startTime.getTime(); | ||||
|         const bgEndTime = bgStartTime + 3600 * 24 * 1000; | ||||
|         return [ | ||||
|             // 沉默的背景 | ||||
|             { | ||||
|                 xAxisIndex, | ||||
|                 yAxisIndex, | ||||
|                 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: '#ccc', | ||||
|                             opacity: 0.3, | ||||
|                         } | ||||
|                     }, | ||||
|                 ] | ||||
|             }, | ||||
|             { | ||||
|                 name: equipmentName, | ||||
|                 xAxisIndex, | ||||
|                 yAxisIndex, | ||||
|                 type: 'custom', | ||||
|                 renderItem: renderItem, | ||||
|                 itemStyle: { | ||||
|                     opacity: 0.8, | ||||
|                 }, | ||||
|                 encode: { | ||||
|                     x: [1, 2], | ||||
|                     y: 0, | ||||
|                 }, | ||||
|                 data: [ | ||||
|                     // 暂时先静态数据 | ||||
|                     { | ||||
|                         name: '运行', | ||||
|                         value: [0, 1696694400000, 1696699400000, 0], | ||||
|                         itemStyle: { | ||||
|  | ||||
|                             color: types[0].color, | ||||
|  | ||||
|                         }, | ||||
|                     }, | ||||
|                     { | ||||
|                         name: '运行', | ||||
|                         value: [0, 1696730000000, 1696734040450, 0], | ||||
|                         itemStyle: { | ||||
|  | ||||
|                             color: types[0].color, | ||||
|  | ||||
|                         }, | ||||
|                     }, | ||||
|                     { | ||||
|                         name: '故障', | ||||
|                         value: [0, 1696737040000, 1696754040450, 0], | ||||
|                         itemStyle: { | ||||
|  | ||||
|                             color: types[1].color, | ||||
|  | ||||
|                         }, | ||||
|                     }, | ||||
|                     { | ||||
|                         name: '计划停机', | ||||
|                         value: [0, 1696755000000, 1696759000000, 0], | ||||
|                         itemStyle: { | ||||
|  | ||||
|                             color: types[2].color, | ||||
|  | ||||
|                         }, | ||||
|                     }, | ||||
|                     { | ||||
|                         name: '运行', | ||||
|                         value: [0, 1696759000000, 1696769000000, 0], | ||||
|                         itemStyle: { | ||||
|  | ||||
|                             color: types[0].color, | ||||
|  | ||||
|                         }, | ||||
|                     }, | ||||
|                     { | ||||
|                         name: '计划停机', | ||||
|                         value: [0, 1696769400000, 1696779000000, 0], | ||||
|                         itemStyle: { | ||||
|  | ||||
|                             color: types[2].color, | ||||
|  | ||||
|                         }, | ||||
|                     }, | ||||
|                 ], | ||||
|             }, | ||||
|         ] | ||||
|     } | ||||
|  | ||||
|     init(el) { | ||||
|         if (typeof el == 'string') { | ||||
|             el = document.querySelector(el); | ||||
|         } | ||||
|         this.chart = echarts.init(el); | ||||
|  | ||||
|         setTimeout(() => { | ||||
|             console.log("init....", this.chart, this.option); | ||||
|             debugger; | ||||
|             this.chart.setOption(this.option); | ||||
|         }, 200); | ||||
|     } | ||||
|  | ||||
|     update(data) { | ||||
|         // todo , handle data | ||||
|         this.chart.setOption(this.option); | ||||
|     } | ||||
|  | ||||
|     resize() { | ||||
|         this.chart.resize(); | ||||
|     } | ||||
|  | ||||
|     get option() { | ||||
|         return { | ||||
|             tooltip: this.tooltip, | ||||
|             grid: this.grid, | ||||
|             xAxis: this.xAxis, | ||||
|             yAxis: this.yAxis, | ||||
|             series: this.series, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // print option | ||||
|     print() { | ||||
|         console.log(JSON.stringify(this.option, null, 2)); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										607
									
								
								src/views/equipment/timing-diagram/status/index copy.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										607
									
								
								src/views/equipment/timing-diagram/status/index copy.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,607 @@ | ||||
| <!--  | ||||
|     filename: index.vue | ||||
|     author: liubin | ||||
|     date: 2023-09-04 09:34:52 | ||||
|     description: 设备状态时序图 | ||||
| --> | ||||
|  | ||||
| <template> | ||||
| 	<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" /> | ||||
| 		</el-row> | ||||
|  | ||||
| 		<el-row | ||||
| 			class="" | ||||
| 			style=" | ||||
| 				height: 1px; | ||||
| 				flex: 1; | ||||
| 				margin-bottom: 12px; | ||||
| 				background: #fff; | ||||
| 				padding: 16px 16px 32px; | ||||
| 				border-radius: 8px; | ||||
| 				display: flex; | ||||
| 				flex-direction: column; | ||||
| 			"> | ||||
| 			<el-row :gutter="20"> | ||||
| 				<el-col :span="6"> | ||||
| 					<div class="blue-title">设备状态时序图</div> | ||||
| 				</el-col> | ||||
| 				<el-col :span="18" class="legend-row"> | ||||
| 					<div class="legend"> | ||||
| 						<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> | ||||
| 				<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" | ||||
| 			@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> | ||||
| 		</base-dialog> | ||||
| 	</div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| // import * as echarts from 'echarts'; | ||||
| import Gantt from './gantt'; | ||||
|  | ||||
| export default { | ||||
| 	name: 'SGStatus', | ||||
| 	components: {}, | ||||
| 	props: {}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			chart: null, | ||||
| 			searchBarFormConfig: [ | ||||
| 				{ | ||||
| 					type: 'select', | ||||
| 					label: '产线', | ||||
| 					placeholder: '请选择产线', | ||||
| 					selectOptions: [], | ||||
| 					param: 'lineId', | ||||
| 					onchange: true, | ||||
| 				}, | ||||
| 				{ | ||||
| 					type: 'select', | ||||
| 					label: '工段', | ||||
| 					placeholder: '请选择工段', | ||||
| 					selectOptions: [], | ||||
| 					param: 'sectionId', | ||||
| 				}, | ||||
| 				// 时间段 | ||||
| 				{ | ||||
| 					type: 'datePicker', | ||||
| 					label: '时间段', | ||||
| 					dateType: 'date', | ||||
| 					format: 'yyyy-MM-dd', | ||||
| 					valueFormat: 'yyyy-MM-dd HH:mm:ss', | ||||
| 					rangeSeparator: '-', | ||||
| 					placeholder: '选择日期', | ||||
| 					param: 'recordTime', | ||||
| 					required: true, | ||||
| 				}, | ||||
| 				{ | ||||
| 					type: 'button', | ||||
| 					btnName: '查询', | ||||
| 					name: 'search', | ||||
| 					color: 'primary', | ||||
| 				}, | ||||
| 				{ | ||||
| 					type: 'separate', | ||||
| 				}, | ||||
| 				{ | ||||
| 					type: 'button', | ||||
| 					btnName: '添加对比', | ||||
| 					name: 'compare', | ||||
| 					color: 'primary', | ||||
| 					plain: true, | ||||
| 				}, | ||||
| 			], | ||||
| 			queryParams: { | ||||
| 				lineId: null, | ||||
| 				sectionId: null, | ||||
| 				equipmentId: null, | ||||
| 				recordTime: null, | ||||
| 			}, | ||||
| 			graphList: [], | ||||
| 			open: false, | ||||
| 			eqList: [], | ||||
| 			startTime: null, | ||||
| 			gantt: null | ||||
| 			// demo: [ | ||||
| 			// 	[ | ||||
| 			// 		{ | ||||
| 			// 			equipmentName: '下片机', | ||||
| 			// 			duration: 30, | ||||
| 			// 			relativeDuration: 0.6, | ||||
| 			// 			status: 0, | ||||
| 			// 			startPos: 0, | ||||
| 			//             startTime: 1691568181000, | ||||
| 			// 		}, | ||||
| 			// 		{ | ||||
| 			// 			equipmentName: '下片机', | ||||
| 			// 			duration: 20, | ||||
| 			// 			relativeDuration: 0.4, | ||||
| 			// 			status: 2, | ||||
| 			// 			startPos: 30, | ||||
| 			//             startTime: 1691569981000 | ||||
| 			// 		}, | ||||
| 			// 	], | ||||
| 			// ], | ||||
| 		}; | ||||
| 	}, | ||||
| 	computed: {}, | ||||
| 	created() { | ||||
| 		this.initProductline(); | ||||
| 		this.initWorksection(); | ||||
| 		this.initEquipment(); | ||||
| 		// this.getList(); | ||||
| 	}, | ||||
| 	mounted() {}, | ||||
| 	watch: { | ||||
| 		graphList: { | ||||
| 			handler(val) { | ||||
| 				if (val && val.length) { | ||||
| 					this.$nextTick(() => { | ||||
| 						if (!this.chart) this.initChart(); | ||||
| 						this.setInitialConfig(); | ||||
| 						this.handleGraphList(); | ||||
| 					}); | ||||
| 				} | ||||
| 				return; | ||||
| 			}, | ||||
| 			deep: true, | ||||
| 			immediate: true, | ||||
| 		}, | ||||
| 	}, | ||||
| 	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) => { | ||||
| 				arr.forEach((item) => { | ||||
| 					if (min < item.startTime) min = item.startTime; | ||||
| 				}); | ||||
| 			}); | ||||
| 			return min; | ||||
| 		}, | ||||
|  | ||||
| 		initChart() { | ||||
| 			const el = document.getElementById('status-chart'); | ||||
| 			this.gantt = new Gantt(el); | ||||
| 			this.gantt.init(); | ||||
| 		}, | ||||
|  | ||||
| 		/** 重置查询条件 */ | ||||
| 		initQuery() { | ||||
| 			this.queryParams.lineId = null; | ||||
| 			this.queryParams.equipmentId = null; | ||||
| 			this.queryParams.sectionId = null; | ||||
| 			this.queryParams.recordTime = null; | ||||
| 		}, | ||||
|  | ||||
| 		/** 对象到数组的转换 */ | ||||
| 		objectToArray(obj) { | ||||
| 			return Object.keys(obj).map((key) => { | ||||
| 				obj[key].sort((a, b) => a.startTime - b.startTime); | ||||
| 				obj[key].key = key; | ||||
| 				return obj[key]; | ||||
| 			}); | ||||
| 		}, | ||||
|  | ||||
| 		async getList() { | ||||
| 			const { code, data } = await this.$axios({ | ||||
| 				url: '/analysis/equipment-analysis/status', | ||||
| 				method: 'get', | ||||
| 				params: this.queryParams, | ||||
| 			}); | ||||
| 			if (code == 0) { | ||||
| 				this.graphList = this.objectToArray(data); | ||||
| 				console.log('graph list', this.graphList); | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| 		/** 准备设备数据 */ | ||||
| 		async initEquipment() { | ||||
| 			const { code, data } = await this.$axios({ | ||||
| 				url: '/base/equipment/listAll', | ||||
| 				method: 'get', | ||||
| 			}); | ||||
| 			if (code == 0) { | ||||
| 				this.eqList = data.map((item) => { | ||||
| 					return { | ||||
| 						name: item.name, | ||||
| 						id: item.id, | ||||
| 					}; | ||||
| 				}); | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| 		/** 准备产线数据 */ | ||||
| 		async initProductline() { | ||||
| 			const { code, data } = await this.$axios({ | ||||
| 				url: '/base/production-line/listAll', | ||||
| 				method: 'get', | ||||
| 			}); | ||||
| 			if (code == 0) { | ||||
| 				this.searchBarFormConfig[0].selectOptions = data.map((item) => { | ||||
| 					return { | ||||
| 						name: item.name, | ||||
| 						id: item.id, | ||||
| 					}; | ||||
| 				}); | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| 		/** 准备工段数据 */ | ||||
| 		async initWorksection() { | ||||
| 			const { code, data } = await this.$axios({ | ||||
| 				url: '/base/workshop-section/listAll', | ||||
| 				method: 'get', | ||||
| 			}); | ||||
| 			if (code == 0) { | ||||
| 				this.searchBarFormConfig[1].selectOptions = data.map((item) => { | ||||
| 					return { | ||||
| 						name: item.name, | ||||
| 						id: item.id, | ||||
| 					}; | ||||
| 				}); | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| 		handleSearchBarSelectChange({ param, value }) { | ||||
| 			if (!value) { | ||||
| 				this.searchBarFormConfig[1].selectOptions = []; | ||||
| 				return; | ||||
| 			} | ||||
| 			switch (param) { | ||||
| 				case 'lineId': | ||||
| 					this.$axios({ | ||||
| 						url: '/base/workshop-section/listByParentId', | ||||
| 						method: 'get', | ||||
| 						params: { | ||||
| 							id: value, | ||||
| 						}, | ||||
| 					}).then(({ code, data }) => { | ||||
| 						if (code == 0) { | ||||
| 							this.searchBarFormConfig[1].selectOptions = data.map((item) => { | ||||
| 								return { | ||||
| 									name: item.name, | ||||
| 									id: item.id, | ||||
| 								}; | ||||
| 							}); | ||||
| 						} | ||||
| 					}); | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| 		handleSearchBarBtnClick({ btnName, ...payload }) { | ||||
| 			switch (btnName) { | ||||
| 				case 'search': | ||||
| 					if (!payload.recordTime || payload.recordTime.length <= 0) { | ||||
| 						this.$message.error('请选择时间段'); | ||||
| 						return; | ||||
| 					} | ||||
|  | ||||
| 					this.startTime = new Date(payload.recordTime).getTime(); | ||||
|  | ||||
| 					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', | ||||
| 						  ] | ||||
| 						: null; | ||||
| 					this.getList(); | ||||
| 					break; | ||||
| 				case 'compare': | ||||
| 					this.open = true; | ||||
| 					break; | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| 		async submitForm() { | ||||
| 			const { code, data } = await this.$axios({ | ||||
| 				url: '/analysis/equipment-analysis/status', | ||||
| 				method: 'get', | ||||
| 				params: this.queryParams, | ||||
| 			}); | ||||
| 			if (code == 0) { | ||||
| 				const newEqlist = this.objectToArray(data); | ||||
| 				if (!newEqlist || newEqlist.length == 0) { | ||||
| 					this.$message.error('该设备没有状态数据'); | ||||
| 					return; | ||||
| 				} | ||||
| 				this.graphList.push(newEqlist[0]); | ||||
| 			} | ||||
| 			this.open = false; | ||||
| 		}, | ||||
| 	}, | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| .graph { | ||||
| 	// border: 1px solid #ccc; | ||||
| 	// padding: 12px 12px 28px 12px; | ||||
| 	// margin: 64px 0; | ||||
| 	position: relative; | ||||
| 	display: flex; | ||||
| } | ||||
|  | ||||
| .graph-title { | ||||
| 	// position: absolute; | ||||
| 	// top: -64px; | ||||
| 	// left: -1px; | ||||
| 	// padding: 8px 18px; | ||||
| 	padding: 0 12px; | ||||
| 	font-size: 14px; | ||||
| 	line-height: 1; | ||||
| } | ||||
|  | ||||
| .graph-content { | ||||
| 	display: flex; | ||||
| 	flex: 1; | ||||
| 	padding: 22px 12px; | ||||
| 	border: 1px solid #ccc; | ||||
| 	border-bottom-width: 2px; | ||||
| 	border-top: none; | ||||
| 	position: relative; | ||||
| } | ||||
|  | ||||
| .graph-content::after, | ||||
| .graph-content::before { | ||||
| 	content: ''; | ||||
| 	position: absolute; | ||||
| 	width: 3px; | ||||
| 	height: 80%; | ||||
| 	background: #fff; | ||||
| 	right: -1px; | ||||
| 	top: 0; | ||||
| } | ||||
|  | ||||
| .graph-content::before { | ||||
| 	right: unset; | ||||
| 	left: -1px; | ||||
| } | ||||
|  | ||||
| .graph-item, | ||||
| .graph-item-fixed { | ||||
| 	// height: 88px; | ||||
| 	// width: 24px; | ||||
| 	flex: 1; | ||||
| 	// border: 1px solid #ccc; | ||||
| 	position: relative; | ||||
| } | ||||
|  | ||||
| .graph-item-fixed { | ||||
| 	flex: unset; | ||||
| } | ||||
|  | ||||
| .graph-item::before, | ||||
| .graph-item-fixed::before { | ||||
| 	position: absolute; | ||||
| 	bottom: -16px; | ||||
| 	left: 0; | ||||
| 	content: attr(data-time); | ||||
| 	// font-size - js | ||||
| 	// rotate - js | ||||
| 	// color - js, default: | ||||
| 	color: #777; | ||||
| 	transform-origin: left top; | ||||
| 	transform: rotate(12deg); | ||||
| } | ||||
|  | ||||
| .graph-item-fixed::after, | ||||
| .graph-item::after { | ||||
| 	content: ''; | ||||
| 	position: absolute; | ||||
| 	left: 0; | ||||
| 	bottom: -3px; | ||||
| 	display: inline-block; | ||||
| } | ||||
|  | ||||
| .graph-item.tick::after, | ||||
| .graph-item-fixed.tick::after { | ||||
| 	width: 1px; | ||||
| 	height: 6px; | ||||
| 	border-left: 1px solid #777; | ||||
| } | ||||
|  | ||||
| .running { | ||||
| 	background-color: #5ad8a6; | ||||
| 	// background-color: #84f04e; | ||||
| } | ||||
|  | ||||
| .waiting { | ||||
| 	background-color: #5ad8a6; | ||||
| 	// background-color: #409eff; | ||||
| } | ||||
|  | ||||
| .fault { | ||||
| 	// background-color: #ea5b5b; | ||||
| 	background-color: #fc9c91; | ||||
| } | ||||
|  | ||||
| .full { | ||||
| 	// background-color: #e6a23c; | ||||
| 	background-color: #598fff; | ||||
| } | ||||
|  | ||||
| .lack { | ||||
| 	// background-color: #a69c8d; | ||||
| 	background-color: #7585a2; | ||||
| } | ||||
|  | ||||
| .stop { | ||||
| 	background-color: #000; | ||||
| } | ||||
|  | ||||
| .legend-row { | ||||
| 	margin: 6px 0; | ||||
| 	padding-right: 12px; | ||||
| 	display: flex; | ||||
| 	justify-content: flex-end; | ||||
|  | ||||
| 	> .legend:not(:last-child) { | ||||
| 		margin-right: 12px; | ||||
| 	} | ||||
|  | ||||
| 	.legend { | ||||
| 		display: flex; | ||||
| 		align-items: center; | ||||
| 	} | ||||
|  | ||||
| 	.icon { | ||||
| 		width: 8px; | ||||
| 		height: 8px; | ||||
| 		border-radius: 2px; | ||||
| 		margin-right: 4px; | ||||
| 		margin-top: 1px; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| .blue-title { | ||||
| 	position: relative; | ||||
| 	padding: 4px 0; | ||||
| 	padding-left: 12px; | ||||
| 	font-size: 14px; | ||||
| 	color: #606266; | ||||
| 	font-weight: 700; | ||||
| 	margin-bottom: 12px; | ||||
|  | ||||
| 	&::before { | ||||
| 		content: ''; | ||||
| 		position: absolute; | ||||
| 		left: 0; | ||||
| 		top: 6px; | ||||
| 		height: 16px; | ||||
| 		width: 4px; | ||||
| 		border-radius: 1px; | ||||
| 		background: #0b58ff; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| .echarts__status-chart { | ||||
| 	background: #ccc; | ||||
| } | ||||
|  | ||||
| .echarts__status-chart > div { | ||||
| 	height: 100% !important; | ||||
| 	width: 100% !important; | ||||
| } | ||||
| </style> | ||||
| @@ -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,58 +37,27 @@ | ||||
| 						<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; background: lightyellow; 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> | ||||
| @@ -108,7 +65,7 @@ | ||||
|  | ||||
| <script> | ||||
| // import * as echarts from 'echarts'; | ||||
| import Gantt from './gantt'; | ||||
| import Gantt from './demo'; | ||||
|  | ||||
| export default { | ||||
| 	name: 'SGStatus', | ||||
| @@ -202,15 +159,22 @@ 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.chart) this.initChart(); | ||||
| 						// this.setInitialConfig(); | ||||
| 						// this.handleGraphList(); | ||||
| 						if (!this.gantt) { | ||||
| 							this.gantt = new Gantt(null, this.startTime); | ||||
| 							this.gantt.init('#status-chart'); | ||||
| 							return; | ||||
| 						} | ||||
| 						this.gantt.update(val); | ||||
|  | ||||
| 					}); | ||||
| 				} | ||||
| 				return; | ||||
| @@ -385,26 +349,26 @@ export default { | ||||
| 					} | ||||
|  | ||||
| 					this.startTime = new Date(payload.recordTime).getTime(); | ||||
|  | ||||
| 					console.log("startTime", new Date(payload.recordTime).getTime()); | ||||
| 					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; | ||||
| @@ -557,7 +521,7 @@ export default { | ||||
| 	display: flex; | ||||
| 	justify-content: flex-end; | ||||
|  | ||||
| 	> .legend:not(:last-child) { | ||||
| 	>.legend:not(:last-child) { | ||||
| 		margin-right: 12px; | ||||
| 	} | ||||
|  | ||||
| @@ -600,7 +564,7 @@ export default { | ||||
| 	background: #ccc; | ||||
| } | ||||
|  | ||||
| .echarts__status-chart > div { | ||||
| .echarts__status-chart>div { | ||||
| 	height: 100% !important; | ||||
| 	width: 100% !important; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user