test #47
@@ -31,7 +31,6 @@ export default {
 | 
			
		||||
			// dialogFormConfig: [], // 占位
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	mounted() {},
 | 
			
		||||
	methods: {
 | 
			
		||||
		// 过滤后端传回的详情数据
 | 
			
		||||
		filterData(data, keys) {
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,98 @@
 | 
			
		||||
<!-- 
 | 
			
		||||
    filename: pieChart.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-09-06 15:02:49
 | 
			
		||||
    description: 饼图
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="pie-chart" :data-eqname="value.equipmentName || 'Default'"></div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import * as echarts from 'echarts';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'pieChart',
 | 
			
		||||
	components: {},
 | 
			
		||||
	props: ['value'],
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			chart: null,
 | 
			
		||||
			config: {
 | 
			
		||||
				grid: {
 | 
			
		||||
					top: 0,
 | 
			
		||||
					left: 0,
 | 
			
		||||
					right: 0,
 | 
			
		||||
					bottom: 0,
 | 
			
		||||
				},
 | 
			
		||||
				tooltip: {
 | 
			
		||||
					trigger: 'item',
 | 
			
		||||
				},
 | 
			
		||||
				legend: {
 | 
			
		||||
					top: '0%',
 | 
			
		||||
					left: 'center',
 | 
			
		||||
					textStyle: {
 | 
			
		||||
						fontSize: 10,
 | 
			
		||||
					},
 | 
			
		||||
					itemWidth: 10,
 | 
			
		||||
					itemHeight: 10,
 | 
			
		||||
				},
 | 
			
		||||
				series: [
 | 
			
		||||
					{
 | 
			
		||||
						name: this.value.equipmentName || 'Default',
 | 
			
		||||
						type: 'pie',
 | 
			
		||||
						radius: ['40%', '75%'],
 | 
			
		||||
						avoidLabelOverlap: false,
 | 
			
		||||
						label: {
 | 
			
		||||
							show: false,
 | 
			
		||||
							position: 'center',
 | 
			
		||||
						},
 | 
			
		||||
						data: ['workTime', 'stopTime', 'downTime'].map((v, index) => ({
 | 
			
		||||
							name: ['工作时长', '停机时长', '故障时长'][index],
 | 
			
		||||
							value: this.value[v],
 | 
			
		||||
						})),
 | 
			
		||||
						// data: [
 | 
			
		||||
						// 	{ value: 1048, name: 'Search Engine' },
 | 
			
		||||
						// 	{ value: 735, name: 'Direct' },
 | 
			
		||||
						// 	{ value: 580, name: 'Email' },
 | 
			
		||||
						// 	{ value: 484, name: 'Union Ads' },
 | 
			
		||||
						// 	{ value: 300, name: 'Video Ads' },
 | 
			
		||||
						// ],
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
			},
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	mounted() {
 | 
			
		||||
		if (!this.chart) {
 | 
			
		||||
			this.chart = echarts.init(this.$el);
 | 
			
		||||
			this.$nextTick(() => {
 | 
			
		||||
				this.chart.setOption(this.config);
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	beforeDestroy() {
 | 
			
		||||
		if (this.chart) this.chart.dispose();
 | 
			
		||||
	},
 | 
			
		||||
	methods: {},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="scss">
 | 
			
		||||
.pie-chart {
 | 
			
		||||
	padding: 12px;
 | 
			
		||||
	min-height: 320px;
 | 
			
		||||
	background: #f1f1f1;
 | 
			
		||||
	position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.pie-chart::before {
 | 
			
		||||
	content: attr(data-eqname);
 | 
			
		||||
	font-size: 16px;
 | 
			
		||||
	line-height: 1;
 | 
			
		||||
	position: absolute;
 | 
			
		||||
	top: -16px;
 | 
			
		||||
	left: 0;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										419
									
								
								src/views/equipment/analysis/efficiency/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										419
									
								
								src/views/equipment/analysis/efficiency/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,419 @@
 | 
			
		||||
<!-- 
 | 
			
		||||
    filename: index.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-09-04 09:34:52
 | 
			
		||||
    description: 设备效率分析
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="app-container">
 | 
			
		||||
		<!-- 搜索工作栏 -->
 | 
			
		||||
		<SearchBar
 | 
			
		||||
			:formConfigs="searchBarFormConfig"
 | 
			
		||||
			ref="search-bar"
 | 
			
		||||
			@headBtnClick="handleSearchBarBtnClick" />
 | 
			
		||||
 | 
			
		||||
		<!-- 列表 -->
 | 
			
		||||
		<base-table
 | 
			
		||||
			class="base-table__margin"
 | 
			
		||||
			:table-props="tableProps"
 | 
			
		||||
			:table-data="list"
 | 
			
		||||
			@emitFun="handleEmitFun">
 | 
			
		||||
			<!-- :page="queryParams.pageNo"
 | 
			
		||||
			:limit="queryParams.pageSize" -->
 | 
			
		||||
			<!-- <method-btn
 | 
			
		||||
				v-if="tableBtn.length"
 | 
			
		||||
				slot="handleBtn"
 | 
			
		||||
				label="操作"
 | 
			
		||||
				:method-list="tableBtn"
 | 
			
		||||
				@clickBtn="handleTableBtnClick" /> -->
 | 
			
		||||
		</base-table>
 | 
			
		||||
 | 
			
		||||
		<!-- 分页组件 -->
 | 
			
		||||
		<!-- <pagination
 | 
			
		||||
			v-show="total > 0"
 | 
			
		||||
			:total="total"
 | 
			
		||||
			:page.sync="queryParams.pageNo"
 | 
			
		||||
			:limit.sync="queryParams.pageSize"
 | 
			
		||||
			@pagination="getList" /> -->
 | 
			
		||||
 | 
			
		||||
		<!-- 对话框(添加 / 修改) -->
 | 
			
		||||
		<base-dialog
 | 
			
		||||
			:dialogTitle="visualizationOpen ? '设备可视化' : '查看趋势'"
 | 
			
		||||
			:dialogVisible="open"
 | 
			
		||||
			:width="visualizationOpen ? '80%' : '700px'"
 | 
			
		||||
			@closed="closed"
 | 
			
		||||
			@close="cancel"
 | 
			
		||||
			@cancel="cancel"
 | 
			
		||||
			@confirm="submitForm">
 | 
			
		||||
			<div class="visualization" v-if="visualizationOpen">
 | 
			
		||||
				<pie-chart v-for="item in list" :key="item.id" :value="item" />
 | 
			
		||||
			</div>
 | 
			
		||||
			<div v-if="trendOpen">
 | 
			
		||||
				<h1>查看趋势</h1>
 | 
			
		||||
			</div>
 | 
			
		||||
		</base-dialog>
 | 
			
		||||
	</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
// import moment from 'moment';
 | 
			
		||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
 | 
			
		||||
import PieChart from './components/pieChart.vue';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'EfficiencyAnalysis',
 | 
			
		||||
	mixins: [basicPageMixin],
 | 
			
		||||
	components: { PieChart },
 | 
			
		||||
	props: {},
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			open: false,
 | 
			
		||||
			visualizationOpen: false,
 | 
			
		||||
			trendOpen: false,
 | 
			
		||||
			// 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),
 | 
			
		||||
			tableProps: [
 | 
			
		||||
				{ prop: 'factoryName', label: '工厂', align: 'center' },
 | 
			
		||||
				{ prop: 'lineName', label: '产线', align: 'center' },
 | 
			
		||||
				{ prop: 'sectionName', label: '工段', align: 'center' },
 | 
			
		||||
				{ prop: 'equipmentName', label: '设备', align: 'center' },
 | 
			
		||||
				{
 | 
			
		||||
					label: '有效时间',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
					children: [
 | 
			
		||||
						{
 | 
			
		||||
							width: 128,
 | 
			
		||||
							prop: 'workTime',
 | 
			
		||||
							label: '工作时长',
 | 
			
		||||
							align: 'center',
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							width: 128,
 | 
			
		||||
							prop: 'workRate',
 | 
			
		||||
							label: '百分比',
 | 
			
		||||
							align: 'center',
 | 
			
		||||
							filter: (val) => (val != null ? +val.toFixed(3) : '-'),
 | 
			
		||||
						},
 | 
			
		||||
					],
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					label: '关机时间',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
					children: [
 | 
			
		||||
						{
 | 
			
		||||
							width: 128,
 | 
			
		||||
							prop: 'stopTime',
 | 
			
		||||
							label: '停机时长',
 | 
			
		||||
							align: 'center',
 | 
			
		||||
						},
 | 
			
		||||
						{ width: 128, prop: 'stopRate', label: '百分比', align: 'center' },
 | 
			
		||||
					],
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					label: '中断损失',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
					children: [
 | 
			
		||||
						{
 | 
			
		||||
							width: 128,
 | 
			
		||||
							prop: 'downTime',
 | 
			
		||||
							label: '故障时长',
 | 
			
		||||
							align: 'center',
 | 
			
		||||
							filter: (val) => (val != null ? +val.toFixed(3) : '-'),
 | 
			
		||||
						},
 | 
			
		||||
						{ width: 128, prop: 'downRate', label: '百分比', align: 'center' },
 | 
			
		||||
						{
 | 
			
		||||
							width: 128,
 | 
			
		||||
							prop: 'timeEfficiency',
 | 
			
		||||
							label: '时间开动率',
 | 
			
		||||
							align: 'center',
 | 
			
		||||
							filter: (val) => (val != null ? +val.toFixed(3) : '-'),
 | 
			
		||||
						},
 | 
			
		||||
					],
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					label: '速度损失',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
					children: [
 | 
			
		||||
						{
 | 
			
		||||
							width: 128,
 | 
			
		||||
							prop: 'realProcSpeed',
 | 
			
		||||
							label: '实际加工速度',
 | 
			
		||||
							align: 'center',
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							width: 128,
 | 
			
		||||
							prop: 'designProcSpeed',
 | 
			
		||||
							label: '理论加工速度',
 | 
			
		||||
							align: 'center',
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							width: 128,
 | 
			
		||||
							prop: 'peEfficiency',
 | 
			
		||||
							label: '速度开动率',
 | 
			
		||||
							align: 'center',
 | 
			
		||||
							filter: (val) => (val != null ? +val.toFixed(3) : '-'),
 | 
			
		||||
						},
 | 
			
		||||
					],
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					prop: 'oee',
 | 
			
		||||
					label: 'OEE',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
					filter: (val) => (val != null ? +val.toFixed(3) : '-'),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					prop: 'teep',
 | 
			
		||||
					label: 'TEEP',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
					filter: (val) => (val != null ? +val.toFixed(3) : '-'),
 | 
			
		||||
				},
 | 
			
		||||
				// {
 | 
			
		||||
				// 	_action: 'view-trend',
 | 
			
		||||
				// 	label: '趋势',
 | 
			
		||||
				// 	align: 'center',
 | 
			
		||||
				// 	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,
 | 
			
		||||
				// 							});
 | 
			
		||||
				// 						},
 | 
			
		||||
				// 					},
 | 
			
		||||
				// 				},
 | 
			
		||||
				// 				'查看趋势'
 | 
			
		||||
				// 			);
 | 
			
		||||
				// 		},
 | 
			
		||||
				// 	},
 | 
			
		||||
				// },
 | 
			
		||||
			],
 | 
			
		||||
			searchBarFormConfig: [
 | 
			
		||||
				{
 | 
			
		||||
					type: 'select',
 | 
			
		||||
					label: '工厂',
 | 
			
		||||
					placeholder: '请选择工厂',
 | 
			
		||||
					param: 'factoryId',
 | 
			
		||||
					selectOptions: [],
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'select',
 | 
			
		||||
					label: '产线',
 | 
			
		||||
					placeholder: '请选择产线',
 | 
			
		||||
					param: 'lineId',
 | 
			
		||||
					selectOptions: [],
 | 
			
		||||
				},
 | 
			
		||||
				// 选项切换
 | 
			
		||||
				{
 | 
			
		||||
					type: 'select',
 | 
			
		||||
					label: '时间类型',
 | 
			
		||||
					param: 'dateFilterType',
 | 
			
		||||
					defaultSelect: 0,
 | 
			
		||||
					selectOptions: [
 | 
			
		||||
						{ id: 0, name: '按时间段' },
 | 
			
		||||
						{ id: 1, name: '按日期' },
 | 
			
		||||
					],
 | 
			
		||||
					index: 2,
 | 
			
		||||
					extraOptions: [
 | 
			
		||||
						{
 | 
			
		||||
							parent: 'dateFilterType',
 | 
			
		||||
							// 时间段选择
 | 
			
		||||
							type: 'datePicker',
 | 
			
		||||
							label: '时间段',
 | 
			
		||||
							dateType: 'daterange',
 | 
			
		||||
							format: 'yyyy-MM-dd',
 | 
			
		||||
							valueFormat: 'yyyy-MM-dd HH:mm:ss',
 | 
			
		||||
							defaultTime: ['00:00:00', '00:00:00'],
 | 
			
		||||
							rangeSeparator: '-',
 | 
			
		||||
							startPlaceholder: '开始时间',
 | 
			
		||||
							endPlaceholder: '结束时间',
 | 
			
		||||
							param: 'recordTime',
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
							parent: 'dateFilterType',
 | 
			
		||||
							// 日期选择
 | 
			
		||||
							type: 'datePicker',
 | 
			
		||||
							label: '日期',
 | 
			
		||||
							dateType: 'date',
 | 
			
		||||
							placeholder: '选择日期',
 | 
			
		||||
							format: 'yyyy-MM-dd',
 | 
			
		||||
							valueFormat: 'yyyy-MM-dd',
 | 
			
		||||
							param: 'recordTime',
 | 
			
		||||
						},
 | 
			
		||||
					],
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'button',
 | 
			
		||||
					btnName: '查询',
 | 
			
		||||
					name: 'search',
 | 
			
		||||
					color: 'primary',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'separate',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'button',
 | 
			
		||||
					btnName: '设备可视化',
 | 
			
		||||
					name: 'visualization',
 | 
			
		||||
					plain: true,
 | 
			
		||||
					color: 'success',
 | 
			
		||||
				},
 | 
			
		||||
				// {
 | 
			
		||||
				// 	type: 'button',
 | 
			
		||||
				// 	btnName: 'OEE',
 | 
			
		||||
				// 	name: 'add',
 | 
			
		||||
				// 	plain: true,
 | 
			
		||||
				// 	color: 'success',
 | 
			
		||||
				// },
 | 
			
		||||
				// {
 | 
			
		||||
				// 	type: 'button',
 | 
			
		||||
				// 	btnName: 'TEEP',
 | 
			
		||||
				// 	name: 'add',
 | 
			
		||||
				// 	plain: true,
 | 
			
		||||
				// 	color: 'warning',
 | 
			
		||||
				// },
 | 
			
		||||
			],
 | 
			
		||||
			// 是否显示弹出层
 | 
			
		||||
			open: false,
 | 
			
		||||
			// 查询参数
 | 
			
		||||
			queryParams: {
 | 
			
		||||
				lineId: null,
 | 
			
		||||
				factoryId: null,
 | 
			
		||||
				recordTime: [],
 | 
			
		||||
			},
 | 
			
		||||
			// 表单参数
 | 
			
		||||
			form: {},
 | 
			
		||||
			list: [],
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	created() {
 | 
			
		||||
		this.getFactory();
 | 
			
		||||
		this.getLine();
 | 
			
		||||
		this.getList();
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		/** 准备工厂数据 */
 | 
			
		||||
		async getFactory() {
 | 
			
		||||
			const { code, data } = await this.$axios({
 | 
			
		||||
				url: '/base/factory/listAll',
 | 
			
		||||
				method: 'get',
 | 
			
		||||
			});
 | 
			
		||||
			if (code == 0) {
 | 
			
		||||
				this.searchBarFormConfig[0].selectOptions = data.map((item) => {
 | 
			
		||||
					return {
 | 
			
		||||
						name: item.name,
 | 
			
		||||
						id: item.id,
 | 
			
		||||
					};
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 准备产线数据 */
 | 
			
		||||
		async getLine() {
 | 
			
		||||
			const { code, data } = await this.$axios({
 | 
			
		||||
				url: '/base/production-line/listAll',
 | 
			
		||||
				method: 'get',
 | 
			
		||||
			});
 | 
			
		||||
			if (code == 0) {
 | 
			
		||||
				this.searchBarFormConfig[1].selectOptions = data.map((item) => {
 | 
			
		||||
					return {
 | 
			
		||||
						name: item.name,
 | 
			
		||||
						id: item.id,
 | 
			
		||||
					};
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 覆盖 handleEmitFun 的默认实现 */
 | 
			
		||||
		handleEmitFun({ action, value }) {
 | 
			
		||||
			switch (action) {
 | 
			
		||||
				case 'view-trend':
 | 
			
		||||
					const { id } = value;
 | 
			
		||||
					this.open = true;
 | 
			
		||||
					this.trendOpen = true;
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		/** 查询列表 */
 | 
			
		||||
		async getList() {
 | 
			
		||||
			this.loading = true;
 | 
			
		||||
			const { code, data } = await this.$axios({
 | 
			
		||||
				url: '/analysis/equipment-analysis/efficiency',
 | 
			
		||||
				method: 'get',
 | 
			
		||||
				params: this.queryParams,
 | 
			
		||||
			});
 | 
			
		||||
			if (code == 0) {
 | 
			
		||||
				console.log('data', data);
 | 
			
		||||
				this.list = data;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleSearchBarBtnClick({ btnName, ...payload }) {
 | 
			
		||||
			console.log('handleSearchBarBtnClick', btnName, payload);
 | 
			
		||||
			if (btnName == 'visualization') {
 | 
			
		||||
				// 可视化
 | 
			
		||||
				this.visualizationOpen = true;
 | 
			
		||||
				this.open = true;
 | 
			
		||||
			}
 | 
			
		||||
			if (btnName == 'search') {
 | 
			
		||||
				this.queryParams.factoryId = payload.factoryId || null;
 | 
			
		||||
				this.queryParams.lineId = payload.lineId || null;
 | 
			
		||||
				if (payload.recordTime != null) {
 | 
			
		||||
					if (typeof payload.recordTime == 'string') {
 | 
			
		||||
						if (payload.recordTime.trim() !== '') {
 | 
			
		||||
							this.queryParams.recordTime = [
 | 
			
		||||
								`${payload.recordTime} 00:00:00`,
 | 
			
		||||
								`${payload.recordTime} 23:59:59`,
 | 
			
		||||
							];
 | 
			
		||||
						}
 | 
			
		||||
					} else {
 | 
			
		||||
						this.queryParams.recordTime = payload.recordTime;
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					this.queryParams.recordTime = null;
 | 
			
		||||
				}
 | 
			
		||||
				this.getList();
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		cancel() {
 | 
			
		||||
			this.open = false;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		closed() {
 | 
			
		||||
			this.visualizationOpen = false;
 | 
			
		||||
			this.trendOpen = false;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		submitForm() {},
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="scss">
 | 
			
		||||
.visualization {
 | 
			
		||||
	display: grid;
 | 
			
		||||
	grid-template-columns: repeat(3, minmax(240px, 1fr));
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										194
									
								
								src/views/equipment/analysis/exception/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								src/views/equipment/analysis/exception/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,194 @@
 | 
			
		||||
<!-- 
 | 
			
		||||
    filename: index.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-09-04 09:34:52
 | 
			
		||||
    description: 设备异常分析
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="app-container">
 | 
			
		||||
		<!-- 搜索工作栏 -->
 | 
			
		||||
		<SearchBar
 | 
			
		||||
			:formConfigs="searchBarFormConfig"
 | 
			
		||||
			ref="search-bar"
 | 
			
		||||
			@headBtnClick="handleSearchBarBtnClick" />
 | 
			
		||||
 | 
			
		||||
		<!-- 列表 -->
 | 
			
		||||
		<base-table
 | 
			
		||||
			:table-props="tableProps"
 | 
			
		||||
			:page="queryParams.pageNo"
 | 
			
		||||
			:limit="queryParams.pageSize"
 | 
			
		||||
			:table-data="list"
 | 
			
		||||
			@emitFun="handleEmitFun">
 | 
			
		||||
			<!-- <method-btn
 | 
			
		||||
				v-if="tableBtn.length"
 | 
			
		||||
				slot="handleBtn"
 | 
			
		||||
				label="操作"
 | 
			
		||||
				:method-list="tableBtn"
 | 
			
		||||
				@clickBtn="handleTableBtnClick" /> -->
 | 
			
		||||
		</base-table>
 | 
			
		||||
 | 
			
		||||
		<!-- 分页组件 -->
 | 
			
		||||
		<pagination
 | 
			
		||||
			v-show="total > 0"
 | 
			
		||||
			:total="total"
 | 
			
		||||
			:page.sync="queryParams.pageNo"
 | 
			
		||||
			:limit.sync="queryParams.pageSize"
 | 
			
		||||
			@pagination="getList" />
 | 
			
		||||
	</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import moment from 'moment';
 | 
			
		||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'ExceptionAnalysis',
 | 
			
		||||
	mixins: [basicPageMixin],
 | 
			
		||||
	components: {},
 | 
			
		||||
	props: {},
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			searchBarKeys: ['name', 'code'],
 | 
			
		||||
			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),
 | 
			
		||||
			tableProps: [
 | 
			
		||||
				{ prop: 'lineName', label: '产线', align: 'center' },
 | 
			
		||||
				{ prop: 'sectionName', label: '工段', align: 'center' },
 | 
			
		||||
				{ prop: 'equipmentName', label: '设备', align: 'center' },
 | 
			
		||||
				{
 | 
			
		||||
					width: 188,
 | 
			
		||||
					prop: 'mtbf',
 | 
			
		||||
					label: '平均故障间隔时间[MTBF](h)',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					width: 180,
 | 
			
		||||
					prop: 'mttr',
 | 
			
		||||
					label: '平均维修时间[MTTR](h)',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
				},
 | 
			
		||||
				{ prop: 'workTime', label: '工作时长(h)', align: 'center' },
 | 
			
		||||
				{ prop: 'downTime', label: '故障时长(h)', align: 'center' },
 | 
			
		||||
				{ prop: 'downCount', label: '故障次数', align: 'center' },
 | 
			
		||||
			],
 | 
			
		||||
			searchBarFormConfig: [
 | 
			
		||||
				{
 | 
			
		||||
					type: 'select',
 | 
			
		||||
					label: '请选择月份',
 | 
			
		||||
					placeholder: '请选择月份',
 | 
			
		||||
					param: 'month',
 | 
			
		||||
					selectOptions: Array(12)
 | 
			
		||||
						.fill(0)
 | 
			
		||||
						.map((v, i) => ({
 | 
			
		||||
							id: i + 1,
 | 
			
		||||
							name: `${i + 1}月`,
 | 
			
		||||
						})),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					__index: 'line',
 | 
			
		||||
					type: 'select',
 | 
			
		||||
					label: '产线',
 | 
			
		||||
					placeholder: '请选择产线',
 | 
			
		||||
					param: 'lineId',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'button',
 | 
			
		||||
					btnName: '查询',
 | 
			
		||||
					name: 'search',
 | 
			
		||||
					color: 'primary',
 | 
			
		||||
				},
 | 
			
		||||
			],
 | 
			
		||||
			// 查询参数
 | 
			
		||||
			queryParams: {
 | 
			
		||||
				lineId: null,
 | 
			
		||||
				factoryId: null,
 | 
			
		||||
				recordTime: null,
 | 
			
		||||
			},
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	computed: {},
 | 
			
		||||
	created() {
 | 
			
		||||
		this.fillLineOptions();
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		async fillLineOptions() {
 | 
			
		||||
			const { data } = await this.$axios({
 | 
			
		||||
				url: '/base/production-line/listAll',
 | 
			
		||||
				method: 'get',
 | 
			
		||||
			});
 | 
			
		||||
			const cfg = this.searchBarFormConfig.find(
 | 
			
		||||
				(item) => item.__index == 'line'
 | 
			
		||||
			);
 | 
			
		||||
			this.$set(
 | 
			
		||||
				cfg,
 | 
			
		||||
				'selectOptions',
 | 
			
		||||
				data.map((item) => ({
 | 
			
		||||
					id: item.id,
 | 
			
		||||
					name: item.name,
 | 
			
		||||
				}))
 | 
			
		||||
			);
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		async getList() {
 | 
			
		||||
			this.loading = true;
 | 
			
		||||
			// 执行查询
 | 
			
		||||
			const { data } = await this.$axios({
 | 
			
		||||
				url: '/analysis/equipment-analysis/efficiency',
 | 
			
		||||
				method: 'get',
 | 
			
		||||
				params: {
 | 
			
		||||
					lineId: this.queryParams.lineId || null,
 | 
			
		||||
					recordTime: this.queryParams.recordTime || null,
 | 
			
		||||
				},
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleSearchBarBtnClick(btn) {
 | 
			
		||||
			switch (btn.btnName) {
 | 
			
		||||
				case 'search':
 | 
			
		||||
					if (btn.month) {
 | 
			
		||||
						this.queryParams.recordTime = [
 | 
			
		||||
							moment()
 | 
			
		||||
								.month(btn.month - 1)
 | 
			
		||||
								.format('YYYY-MM')+'-01 00:00:00',
 | 
			
		||||
							moment()
 | 
			
		||||
								.month(btn.month)
 | 
			
		||||
								.format('YYYY-MM')+'-01 00:00:00',
 | 
			
		||||
						];
 | 
			
		||||
					} else {
 | 
			
		||||
						this.queryParams.recordTime = null;
 | 
			
		||||
					}
 | 
			
		||||
                    this.queryParams.lineId = btn.lineId || null;
 | 
			
		||||
					this.handleQuery();
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 搜索按钮操作 */
 | 
			
		||||
		handleQuery() {
 | 
			
		||||
			// this.queryParams.pageNo = 1;
 | 
			
		||||
			this.getList();
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 重置按钮操作 */
 | 
			
		||||
		resetQuery() {
 | 
			
		||||
			this.resetForm('queryForm');
 | 
			
		||||
			this.handleQuery();
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="scss"></style>
 | 
			
		||||
@@ -0,0 +1,49 @@
 | 
			
		||||
<!-- 
 | 
			
		||||
    filename: lineChart.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-09-04 13:45:00
 | 
			
		||||
    description: 
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="line-chart"></div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import * as echarts from 'echarts';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'LineChart',
 | 
			
		||||
	components: {},
 | 
			
		||||
	props: ['config'],
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			chart: null,
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	computed: {},
 | 
			
		||||
	mounted() {
 | 
			
		||||
		this.init();
 | 
			
		||||
	},
 | 
			
		||||
	beforeDestroy() {
 | 
			
		||||
		if (this.chart) {
 | 
			
		||||
			this.chart.dispose();
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		init() {
 | 
			
		||||
			console.log('thsi el', this.$el);
 | 
			
		||||
			if (!this.chart) this.chart = echarts.init(this.$el);
 | 
			
		||||
			this.chart.setOption(this.config);
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="scss">
 | 
			
		||||
.line-chart {
 | 
			
		||||
	padding: 0 12px;
 | 
			
		||||
	background: #e1e1e1;
 | 
			
		||||
	min-height: 320px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										343
									
								
								src/views/equipment/analysis/quality/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										343
									
								
								src/views/equipment/analysis/quality/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,343 @@
 | 
			
		||||
<!-- 
 | 
			
		||||
    filename: index.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-09-04 09:34:52
 | 
			
		||||
    description: 设备质量分析
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="app-container">
 | 
			
		||||
		<!-- 搜索工作栏 -->
 | 
			
		||||
		<SearchBar
 | 
			
		||||
			:formConfigs="searchBarFormConfig"
 | 
			
		||||
			ref="search-bar"
 | 
			
		||||
			@headBtnClick="handleSearchBarBtnClick" />
 | 
			
		||||
 | 
			
		||||
		<!-- 列表 -->
 | 
			
		||||
		<base-table
 | 
			
		||||
			:table-props="tableProps"
 | 
			
		||||
			:page="queryParams.pageNo"
 | 
			
		||||
			:limit="queryParams.pageSize"
 | 
			
		||||
			:table-data="list"
 | 
			
		||||
			@emitFun="handleEmitFun"></base-table>
 | 
			
		||||
 | 
			
		||||
		<!-- 图形分析 dialog -->
 | 
			
		||||
		<!-- <base-dialog
 | 
			
		||||
			dialogTitle="图形视角"
 | 
			
		||||
			:dialogVisible="dialogVisible"
 | 
			
		||||
			width="60%"
 | 
			
		||||
			@close="dialogClose"
 | 
			
		||||
			@cancel="dialogClose"
 | 
			
		||||
			@confirm="dialogClose">
 | 
			
		||||
			<LineChart v-if="dialogVisible" :config="lineChartConfig" />
 | 
			
		||||
		</base-dialog> -->
 | 
			
		||||
	</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import LineChart from './components/lineChart.vue';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'QualityAnalysis',
 | 
			
		||||
	components: { LineChart },
 | 
			
		||||
	props: {},
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			dialogVisible: false,
 | 
			
		||||
			urls: {
 | 
			
		||||
				page: '/analysis/equipment-analysis/quality',
 | 
			
		||||
			},
 | 
			
		||||
			mode: 'table', // defaults to 'table'
 | 
			
		||||
			searchBarFormConfig: [
 | 
			
		||||
				// 产品
 | 
			
		||||
				{
 | 
			
		||||
					__index: 'product',
 | 
			
		||||
					type: 'select',
 | 
			
		||||
					label: '产品',
 | 
			
		||||
					placeholder: '请选择产品',
 | 
			
		||||
					param: 'productId',
 | 
			
		||||
				},
 | 
			
		||||
				// 产线
 | 
			
		||||
				{
 | 
			
		||||
					__index: 'line',
 | 
			
		||||
					type: 'select',
 | 
			
		||||
					label: '产线',
 | 
			
		||||
					placeholder: '请选择产线',
 | 
			
		||||
					param: 'lineId',
 | 
			
		||||
				},
 | 
			
		||||
				// 时间段
 | 
			
		||||
				{
 | 
			
		||||
					type: 'datePicker',
 | 
			
		||||
					label: '时间段',
 | 
			
		||||
					dateType: 'daterange', // datetimerange
 | 
			
		||||
					// format: 'yyyy-MM-dd HH:mm:ss',
 | 
			
		||||
					format: 'yyyy-MM-dd',
 | 
			
		||||
					valueFormat: 'yyyy-MM-dd HH:mm:ss',
 | 
			
		||||
					// valueFormat: 'timestamp',
 | 
			
		||||
					rangeSeparator: '-',
 | 
			
		||||
					startPlaceholder: '开始日期',
 | 
			
		||||
					endPlaceholder: '结束日期',
 | 
			
		||||
					defaultTime: ['00:00:00', '23:59:59'],
 | 
			
		||||
					param: 'recordTime',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'button',
 | 
			
		||||
					btnName: '查询',
 | 
			
		||||
					name: 'search',
 | 
			
		||||
					color: 'primary',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'separate',
 | 
			
		||||
				},
 | 
			
		||||
				// {
 | 
			
		||||
				// 	type: 'button',
 | 
			
		||||
				// 	btnName: '列表数据',
 | 
			
		||||
				// 	name: 'tableVersion',
 | 
			
		||||
				// 	color: 'text btn-table',
 | 
			
		||||
				// },
 | 
			
		||||
				// {
 | 
			
		||||
				// 	type: 'separate',
 | 
			
		||||
				// },
 | 
			
		||||
				// {
 | 
			
		||||
				// 	type: 'button',
 | 
			
		||||
				// 	btnName: '图形分析',
 | 
			
		||||
				// 	name: 'graphVersion',
 | 
			
		||||
				// 	color: 'text btn-graph',
 | 
			
		||||
				// },
 | 
			
		||||
			],
 | 
			
		||||
			// 动态的 props
 | 
			
		||||
			tableProps: [
 | 
			
		||||
				{
 | 
			
		||||
					// width: 160,
 | 
			
		||||
					prop: 'sectionName',
 | 
			
		||||
					label: '工段',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					// width: 160,
 | 
			
		||||
					prop: 'equipmentName',
 | 
			
		||||
					label: '设备名称',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					// width: 160,
 | 
			
		||||
					prop: 'products',
 | 
			
		||||
					label: '产品名称',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					// width: 160,
 | 
			
		||||
					prop: 'inQuantity',
 | 
			
		||||
					label: '进片数量',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					// width: 160,
 | 
			
		||||
					prop: 'outQuantity',
 | 
			
		||||
					label: '出片数量',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					// width: 160,
 | 
			
		||||
					prop: 'nokQuantity',
 | 
			
		||||
					label: '破损/不合格数',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					// width: 160,
 | 
			
		||||
					prop: 'passRate',
 | 
			
		||||
					label: '合格率',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
				},
 | 
			
		||||
			],
 | 
			
		||||
			lineChartConfig: {
 | 
			
		||||
				grid: {
 | 
			
		||||
					top: 88,
 | 
			
		||||
					left: 56,
 | 
			
		||||
					right: 56,
 | 
			
		||||
					bottom: 56,
 | 
			
		||||
				},
 | 
			
		||||
				legend: {
 | 
			
		||||
					top: 0,
 | 
			
		||||
					left: 0,
 | 
			
		||||
					padding: 5,
 | 
			
		||||
                    icon: 'roundRect',
 | 
			
		||||
                    itemWidth: 12,
 | 
			
		||||
                    itemHeight: 12,
 | 
			
		||||
                    itemGap: 20,
 | 
			
		||||
					textStyle: {
 | 
			
		||||
                        fontSize: 14,
 | 
			
		||||
                        lineHeight: 14
 | 
			
		||||
                    },
 | 
			
		||||
				},
 | 
			
		||||
				xAxis: {
 | 
			
		||||
					type: 'category',
 | 
			
		||||
					data: ['设备1', '设备2', '设备3', '设备4', '设备5'],
 | 
			
		||||
				},
 | 
			
		||||
				yAxis: {
 | 
			
		||||
					type: 'value',
 | 
			
		||||
                    name: '合格率',
 | 
			
		||||
                    nameLocation: 'end',
 | 
			
		||||
                    nameTextStyle: {
 | 
			
		||||
                        fontSize: 14,
 | 
			
		||||
                        align: 'right'
 | 
			
		||||
                    },
 | 
			
		||||
                    nameGap: 26
 | 
			
		||||
				},
 | 
			
		||||
				series: [
 | 
			
		||||
					{
 | 
			
		||||
						name: '产线1',
 | 
			
		||||
						data: [150, 230, 224, 218, 135],
 | 
			
		||||
						type: 'line',
 | 
			
		||||
						smooth: true,
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						name: '产线2',
 | 
			
		||||
						data: [111, 224, 42, 11, 24],
 | 
			
		||||
						type: 'line',
 | 
			
		||||
						smooth: true,
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						name: '产线3',
 | 
			
		||||
						data: [218, 112, 331, 44, 99],
 | 
			
		||||
						type: 'line',
 | 
			
		||||
						smooth: true,
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						name: '产线4',
 | 
			
		||||
						data: [3, 221, 42, 553, 311],
 | 
			
		||||
						type: 'line',
 | 
			
		||||
						smooth: true,
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
			},
 | 
			
		||||
			// 查询参数
 | 
			
		||||
			queryParams: {
 | 
			
		||||
				pageNo: 1,
 | 
			
		||||
				pageSize: 10,
 | 
			
		||||
				lineId: null,
 | 
			
		||||
				productId: null,
 | 
			
		||||
				recordTime: [],
 | 
			
		||||
			},
 | 
			
		||||
			list: [],
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	computed: {},
 | 
			
		||||
	created() {
 | 
			
		||||
		this.fillLineOptions();
 | 
			
		||||
		this.fillProductOptions();
 | 
			
		||||
		this.getList();
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		async fillLineOptions() {
 | 
			
		||||
			const { data } = await this.$axios({
 | 
			
		||||
				url: '/base/production-line/listAll',
 | 
			
		||||
				method: 'get',
 | 
			
		||||
			});
 | 
			
		||||
			const cfg = this.searchBarFormConfig.find(
 | 
			
		||||
				(item) => item.__index == 'line'
 | 
			
		||||
			);
 | 
			
		||||
			this.$set(
 | 
			
		||||
				cfg,
 | 
			
		||||
				'selectOptions',
 | 
			
		||||
				data.map((item) => ({
 | 
			
		||||
					id: item.id,
 | 
			
		||||
					name: item.name,
 | 
			
		||||
				}))
 | 
			
		||||
			);
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		async fillProductOptions() {
 | 
			
		||||
			const { data } = await this.$axios({
 | 
			
		||||
				url: '/base/product/listAll',
 | 
			
		||||
				method: 'get',
 | 
			
		||||
			});
 | 
			
		||||
			const cfg = this.searchBarFormConfig.find(
 | 
			
		||||
				(item) => item.__index == 'product'
 | 
			
		||||
			);
 | 
			
		||||
			this.$set(
 | 
			
		||||
				cfg,
 | 
			
		||||
				'selectOptions',
 | 
			
		||||
				data.map((item) => ({
 | 
			
		||||
					id: item.id,
 | 
			
		||||
					name: item.name,
 | 
			
		||||
				}))
 | 
			
		||||
			);
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		async getList() {
 | 
			
		||||
			const { data } = await this.$axios({
 | 
			
		||||
				url: '/analysis/equipment-analysis/quality',
 | 
			
		||||
				method: 'get',
 | 
			
		||||
				params: {
 | 
			
		||||
					lineId: this.queryParams.lineId || null,
 | 
			
		||||
					productId: this.queryParams.productId || null,
 | 
			
		||||
					recordTime: this.queryParams.recordTime || null,
 | 
			
		||||
				},
 | 
			
		||||
			});
 | 
			
		||||
			this.list = data.map((item) => ({
 | 
			
		||||
				...item,
 | 
			
		||||
				products: item.products.join(','),
 | 
			
		||||
			}));
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleSearchBarBtnClick(btn) {
 | 
			
		||||
			console.log('handleSearchBarBtnClick', btn);
 | 
			
		||||
			switch (btn.btnName) {
 | 
			
		||||
				case 'search':
 | 
			
		||||
					this.queryParams.lineId = btn.lineId;
 | 
			
		||||
					this.queryParams.productId = btn.productId;
 | 
			
		||||
					this.queryParams.recordTime = btn.recordTime;
 | 
			
		||||
					this.$nextTick(() => {
 | 
			
		||||
						this.getList();
 | 
			
		||||
					});
 | 
			
		||||
					break;
 | 
			
		||||
				case 'tableVersion':
 | 
			
		||||
					this.dialogClose();
 | 
			
		||||
					break;
 | 
			
		||||
				case 'graphVersion':
 | 
			
		||||
					this.dialogShow();
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleEmitFun({ action, payload }) {},
 | 
			
		||||
 | 
			
		||||
		dialogShow() {
 | 
			
		||||
			this.dialogVisible = true;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		dialogClose() {
 | 
			
		||||
			this.dialogVisible = false;
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
<style scoped lang="scss">
 | 
			
		||||
:deep(.searchBar) {
 | 
			
		||||
	.el-button.btn-table {
 | 
			
		||||
		color: rgb(0, 130, 130);
 | 
			
		||||
		border: 1px solid rgb(0, 130, 130);
 | 
			
		||||
		padding: 8px 10px;
 | 
			
		||||
		border: 1px solid rgb(0, 130, 130);
 | 
			
		||||
		padding: 8px 10px;
 | 
			
		||||
 | 
			
		||||
		&:hover {
 | 
			
		||||
			border-color: #fff;
 | 
			
		||||
			color: #fff;
 | 
			
		||||
			background: rgb(0, 130, 130);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	.el-button.btn-graph {
 | 
			
		||||
		color: rgb(130, 0, 130);
 | 
			
		||||
		border: 1px solid rgb(130, 0, 130);
 | 
			
		||||
		padding: 8px 10px;
 | 
			
		||||
 | 
			
		||||
		&:hover {
 | 
			
		||||
			border-color: #fff;
 | 
			
		||||
			color: #fff;
 | 
			
		||||
			background: rgb(130, 0, 130);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -0,0 +1,49 @@
 | 
			
		||||
<!-- 
 | 
			
		||||
    filename: lineChart.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-09-04 13:45:00
 | 
			
		||||
    description: 
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="line-chart"></div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import * as echarts from 'echarts';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'LineChart',
 | 
			
		||||
	components: {},
 | 
			
		||||
	props: ['config'],
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			chart: null,
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	computed: {},
 | 
			
		||||
	mounted() {
 | 
			
		||||
		this.init();
 | 
			
		||||
	},
 | 
			
		||||
	beforeDestroy() {
 | 
			
		||||
		if (this.chart) {
 | 
			
		||||
			this.chart.dispose();
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		init() {
 | 
			
		||||
			console.log('thsi el', this.$el);
 | 
			
		||||
			if (!this.chart) this.chart = echarts.init(this.$el);
 | 
			
		||||
			this.chart.setOption(this.config);
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="scss">
 | 
			
		||||
.line-chart {
 | 
			
		||||
	padding: 0 12px;
 | 
			
		||||
	// background: #e1e1e1;
 | 
			
		||||
	min-height: 320px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										330
									
								
								src/views/equipment/timing-diagram/output/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										330
									
								
								src/views/equipment/timing-diagram/output/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,330 @@
 | 
			
		||||
<!-- 
 | 
			
		||||
    filename: index.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-09-04 09:34:52
 | 
			
		||||
    description: 设备产量时序图
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="app-container">
 | 
			
		||||
		<h1>设备产量时序图</h1>
 | 
			
		||||
		<!-- 搜索工作栏 -->
 | 
			
		||||
		<SearchBar
 | 
			
		||||
			:formConfigs="searchBarFormConfig"
 | 
			
		||||
			ref="search-bar"
 | 
			
		||||
			@headBtnClick="handleSearchBarBtnClick" />
 | 
			
		||||
 | 
			
		||||
		<div class="main-area">
 | 
			
		||||
			<div class="graphs" v-if="graphList.length">
 | 
			
		||||
				<div class="graph" v-for="(eq, index) in graphList" :key="eq.key">
 | 
			
		||||
					<h2 class="graph-title">{{ eq.key }}</h2>
 | 
			
		||||
					<LineChart
 | 
			
		||||
						:key="eq.key + '__linechart'"
 | 
			
		||||
						:config="getRealConfig(index)" />
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
			<h2 v-else>请添加设备</h2>
 | 
			
		||||
		</div>
 | 
			
		||||
 | 
			
		||||
		<!-- 对话框(添加 / 修改) -->
 | 
			
		||||
		<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 LineChart from './components/lineChart.vue';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'SGProduction',
 | 
			
		||||
	components: { LineChart },
 | 
			
		||||
	props: {},
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			searchBarFormConfig: [
 | 
			
		||||
				{
 | 
			
		||||
					type: 'select',
 | 
			
		||||
					label: '产线',
 | 
			
		||||
					placeholder: '请选择产线',
 | 
			
		||||
					selectOptions: [],
 | 
			
		||||
					param: 'lineId',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'select',
 | 
			
		||||
					label: '工段',
 | 
			
		||||
					placeholder: '请选择工段',
 | 
			
		||||
					selectOptions: [],
 | 
			
		||||
					param: 'sectionId',
 | 
			
		||||
				},
 | 
			
		||||
				// 时间段
 | 
			
		||||
				{
 | 
			
		||||
					type: 'datePicker',
 | 
			
		||||
					label: '时间段',
 | 
			
		||||
					dateType: 'daterange', // datetimerange
 | 
			
		||||
					// format: 'yyyy-MM-dd HH:mm:ss',
 | 
			
		||||
					format: 'yyyy-MM-dd',
 | 
			
		||||
					valueFormat: 'yyyy-MM-dd HH:mm:ss',
 | 
			
		||||
					// valueFormat: 'timestamp',
 | 
			
		||||
					rangeSeparator: '-',
 | 
			
		||||
					startPlaceholder: '开始日期',
 | 
			
		||||
					endPlaceholder: '结束日期',
 | 
			
		||||
					defaultTime: ['00:00:00', '23:59:59'],
 | 
			
		||||
					param: 'recordTime',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'button',
 | 
			
		||||
					btnName: '查询',
 | 
			
		||||
					name: 'search',
 | 
			
		||||
					color: 'primary',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'separate',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'button',
 | 
			
		||||
					btnName: '设备对比',
 | 
			
		||||
					name: 'compare',
 | 
			
		||||
					color: 'warning',
 | 
			
		||||
					plain: true,
 | 
			
		||||
				},
 | 
			
		||||
			],
 | 
			
		||||
			queryParams: {
 | 
			
		||||
				lineId: null,
 | 
			
		||||
				sectionId: null,
 | 
			
		||||
				equipmentId: null,
 | 
			
		||||
				recordTime: [],
 | 
			
		||||
			},
 | 
			
		||||
			open: false,
 | 
			
		||||
			eqList: [],
 | 
			
		||||
			graphList: [],
 | 
			
		||||
			templateConfig: {
 | 
			
		||||
				grid: {
 | 
			
		||||
					top: 88,
 | 
			
		||||
					left: 56,
 | 
			
		||||
					right: 56,
 | 
			
		||||
					bottom: 56,
 | 
			
		||||
				},
 | 
			
		||||
				legend: {
 | 
			
		||||
					top: 0,
 | 
			
		||||
					left: 0,
 | 
			
		||||
					padding: 5,
 | 
			
		||||
					icon: 'roundRect',
 | 
			
		||||
					itemWidth: 12,
 | 
			
		||||
					itemHeight: 12,
 | 
			
		||||
					itemGap: 20,
 | 
			
		||||
					textStyle: {
 | 
			
		||||
						fontSize: 14,
 | 
			
		||||
						lineHeight: 14,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				xAxis: {
 | 
			
		||||
					type: 'category',
 | 
			
		||||
					data: Array(24)
 | 
			
		||||
						.fill(1)
 | 
			
		||||
						.map((item, index) => `${index}:00`),
 | 
			
		||||
				},
 | 
			
		||||
				yAxis: {
 | 
			
		||||
					type: 'value',
 | 
			
		||||
					name: '产量',
 | 
			
		||||
					nameLocation: 'end',
 | 
			
		||||
					nameTextStyle: {
 | 
			
		||||
						fontSize: 14,
 | 
			
		||||
						align: 'right',
 | 
			
		||||
					},
 | 
			
		||||
					nameGap: 26,
 | 
			
		||||
				},
 | 
			
		||||
				series: [
 | 
			
		||||
					{
 | 
			
		||||
						name: '产线1',
 | 
			
		||||
						data: Array(24)
 | 
			
		||||
							.fill(1)
 | 
			
		||||
							.map(() => Math.random() * 100),
 | 
			
		||||
						type: 'line',
 | 
			
		||||
						smooth: true,
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
			},
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	created() {
 | 
			
		||||
		this.initProductline();
 | 
			
		||||
		this.initWorksection();
 | 
			
		||||
		this.initEquipment();
 | 
			
		||||
		this.getList();
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		handleSearchBarBtnClick({ btnName, ...payload }) {
 | 
			
		||||
			switch (btnName) {
 | 
			
		||||
				case 'search':
 | 
			
		||||
					this.queryParams.lineId = payload.lineId || null;
 | 
			
		||||
					this.queryParams.sectionId = payload.sectionId || null;
 | 
			
		||||
					this.queryParams.equipmentId = payload.equipmentId || null;
 | 
			
		||||
					this.queryParams.recordTime = payload.recordTime || null;
 | 
			
		||||
					this.getList();
 | 
			
		||||
					break;
 | 
			
		||||
				case 'compare':
 | 
			
		||||
					this.open = true;
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 重置查询条件 */
 | 
			
		||||
		initQuery() {
 | 
			
		||||
			this.queryParams.lineId = null;
 | 
			
		||||
			this.queryParams.sectionId = null;
 | 
			
		||||
			this.queryParams.equipmentId = null;
 | 
			
		||||
			this.queryParams.recordTime = [];
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 对象到数组的转换 */
 | 
			
		||||
		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/quantity',
 | 
			
		||||
				method: 'get',
 | 
			
		||||
				params: this.queryParams,
 | 
			
		||||
			});
 | 
			
		||||
			if (code == 0) {
 | 
			
		||||
				this.graphList = this.objectToArray(data);
 | 
			
		||||
				// const eq1 = [
 | 
			
		||||
				// 	{ totalQuantity: 20, startTime: 1693964578000 },
 | 
			
		||||
				// 	{ totalQuantity: 43, startTime: 1693964678000 },
 | 
			
		||||
				// 	{ totalQuantity: 12, startTime: 1693964778000 },
 | 
			
		||||
				// 	{ totalQuantity: 11, startTime: 1693964878000 },
 | 
			
		||||
				// 	{ totalQuantity: 98, startTime: 1693965478000 },
 | 
			
		||||
				// 	{ totalQuantity: 87, startTime: 1693965578000 },
 | 
			
		||||
				// ];
 | 
			
		||||
				// eq1.key = 'SS1';
 | 
			
		||||
				// const eq2 = [
 | 
			
		||||
				// 	{ totalQuantity: 23, startTime: 1693961578000 },
 | 
			
		||||
				// 	{ totalQuantity: 42, startTime: 1693964578000 },
 | 
			
		||||
				// 	{ totalQuantity: 51, startTime: 1693965578000 },
 | 
			
		||||
				// 	{ totalQuantity: 18, startTime: 1693966578000 },
 | 
			
		||||
				// 	{ totalQuantity: 77, startTime: 1693966778000 },
 | 
			
		||||
				// 	{ totalQuantity: 38, startTime: 1693967578000 },
 | 
			
		||||
				// 	{ totalQuantity: 57, startTime: 1693969578000 },
 | 
			
		||||
				// ];
 | 
			
		||||
				// eq2.key = 'SS2';
 | 
			
		||||
				// this.graphList = [eq1, eq2];
 | 
			
		||||
				console.log('graph list', this.graphList);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 获得设备产量 */
 | 
			
		||||
		getEquipmentQuantity(equipmentArr) {
 | 
			
		||||
			return equipmentArr.map((item) => item.totalQuantity);
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 获得设备产量的时间 */
 | 
			
		||||
		getTimeinfo(equipmentArr) {
 | 
			
		||||
			return equipmentArr.map((item) =>
 | 
			
		||||
				new Date(item.startTime).toLocaleTimeString()
 | 
			
		||||
			);
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		getRealConfig(index) {
 | 
			
		||||
			// if (!this.graphList || this.graphList.length == 0) return;
 | 
			
		||||
			const config = JSON.parse(JSON.stringify(this.templateConfig));
 | 
			
		||||
			// config.legend.data = this.graphList[index].key;
 | 
			
		||||
			config.series[0].name = this.graphList[index]?.key;
 | 
			
		||||
			// console.log("this.graphList?.[index]", this.graphList?.[index]);
 | 
			
		||||
			config.series[0].data = this.getEquipmentQuantity(
 | 
			
		||||
				this.graphList?.[index] || []
 | 
			
		||||
			);
 | 
			
		||||
			config.xAxis.data = this.getTimeinfo(this.graphList?.[index] || []);
 | 
			
		||||
			return config;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 准备设备数据 */
 | 
			
		||||
		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,
 | 
			
		||||
					};
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		async submitForm() {
 | 
			
		||||
			const { code, data } = await this.$axios({
 | 
			
		||||
				url: '/analysis/equipment-analysis/quantity',
 | 
			
		||||
				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"></style>
 | 
			
		||||
							
								
								
									
										449
									
								
								src/views/equipment/timing-diagram/status/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										449
									
								
								src/views/equipment/timing-diagram/status/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,449 @@
 | 
			
		||||
<!-- 
 | 
			
		||||
    filename: index.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-09-04 09:34:52
 | 
			
		||||
    description: 设备状态时序图
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="app-container">
 | 
			
		||||
		<h1>设备状态时序图</h1>
 | 
			
		||||
		<!-- 搜索工作栏 -->
 | 
			
		||||
		<SearchBar
 | 
			
		||||
			:formConfigs="searchBarFormConfig"
 | 
			
		||||
			ref="search-bar"
 | 
			
		||||
			@headBtnClick="handleSearchBarBtnClick" />
 | 
			
		||||
 | 
			
		||||
		<div class="main-area">
 | 
			
		||||
			<div 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>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div class="graphs" v-if="graphList.length">
 | 
			
		||||
				<!-- <div class="graph">
 | 
			
		||||
					<h2 class="graph-title">设备1</h2>
 | 
			
		||||
					<div class="graph-item running tick" data-time="00:00"></div>
 | 
			
		||||
					<div class="graph-item running"></div>
 | 
			
		||||
					<div class="graph-item running"></div>
 | 
			
		||||
					<div class="graph-item lack tick" data-time="03:00"></div>
 | 
			
		||||
					<div class="graph-item full tick" data-time="04:00"></div>
 | 
			
		||||
					<div class="graph-item waiting tick" data-time="05:00"></div>
 | 
			
		||||
					<div class="graph-item running tick" data-time="06:00"></div>
 | 
			
		||||
					<div class="graph-item running"></div>
 | 
			
		||||
					<div class="graph-item fault tick" data-time="08:00"></div>
 | 
			
		||||
					<div class="graph-item waiting tick" data-time="09:00"></div>
 | 
			
		||||
					<div class="graph-item running tick" data-time="10:00"></div>
 | 
			
		||||
					<div class="graph-item running"></div>
 | 
			
		||||
					<div class="graph-item running"></div>
 | 
			
		||||
					<div class="graph-item lack tick" data-time="13:00"></div>
 | 
			
		||||
					<div class="graph-item full tick" data-time="14:00"></div>
 | 
			
		||||
					<div class="graph-item running tick" data-time="15:00"></div>
 | 
			
		||||
					<div class="graph-item running"></div>
 | 
			
		||||
					<div class="graph-item running"></div>
 | 
			
		||||
					<div class="graph-item fault tick" data-time="18:00"></div>
 | 
			
		||||
					<div class="graph-item running tick" data-time="19:00"></div>
 | 
			
		||||
					<div class="graph-item running"></div>
 | 
			
		||||
					<div class="graph-item running"></div>
 | 
			
		||||
					<div class="graph-item running"></div>
 | 
			
		||||
					<div class="graph-item stop tick" data-time="23:00"></div>
 | 
			
		||||
				</div> -->
 | 
			
		||||
				<div class="graph" v-for="eq in graphList" :key="eq.key">
 | 
			
		||||
					<h2 class="graph-title">{{ eq.key }}</h2>
 | 
			
		||||
					<div
 | 
			
		||||
						v-for="blc in eq"
 | 
			
		||||
						:key="blc.startTime"
 | 
			
		||||
						class="graph-item-fixed tick"
 | 
			
		||||
						:class="{
 | 
			
		||||
							running: blc.status == 0,
 | 
			
		||||
							fault: blc.status == 2,
 | 
			
		||||
							stop: blc.status == 1,
 | 
			
		||||
						}"
 | 
			
		||||
						:style="{ width: blc.duration * 2 + 'px' }"
 | 
			
		||||
						:data-time="new Date(blc.startTime).toLocaleTimeString()"></div>
 | 
			
		||||
				</div>
 | 
			
		||||
				<!-- <div class="graph">
 | 
			
		||||
					<h2 class="graph-title">设备3</h2>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
					<div class="graph-item"></div>
 | 
			
		||||
				</div> -->
 | 
			
		||||
			</div>
 | 
			
		||||
			<h2 v-else>请添加设备</h2>
 | 
			
		||||
		</div>
 | 
			
		||||
 | 
			
		||||
		<!-- 对话框(添加 / 修改) -->
 | 
			
		||||
		<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>
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'SGStatus',
 | 
			
		||||
	components: {},
 | 
			
		||||
	props: {},
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			searchBarFormConfig: [
 | 
			
		||||
				{
 | 
			
		||||
					type: 'select',
 | 
			
		||||
					label: '产线',
 | 
			
		||||
					placeholder: '请选择产线',
 | 
			
		||||
					selectOptions: [],
 | 
			
		||||
					param: 'lineId',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'select',
 | 
			
		||||
					label: '工段',
 | 
			
		||||
					placeholder: '请选择工段',
 | 
			
		||||
					selectOptions: [],
 | 
			
		||||
					param: 'sectionId',
 | 
			
		||||
				},
 | 
			
		||||
				// 时间段
 | 
			
		||||
				{
 | 
			
		||||
					type: 'datePicker',
 | 
			
		||||
					label: '时间段',
 | 
			
		||||
					dateType: 'daterange', // datetimerange
 | 
			
		||||
					// format: 'yyyy-MM-dd HH:mm:ss',
 | 
			
		||||
					format: 'yyyy-MM-dd',
 | 
			
		||||
					valueFormat: 'yyyy-MM-dd HH:mm:ss',
 | 
			
		||||
					// valueFormat: 'timestamp',
 | 
			
		||||
					rangeSeparator: '-',
 | 
			
		||||
					startPlaceholder: '开始日期',
 | 
			
		||||
					endPlaceholder: '结束日期',
 | 
			
		||||
					defaultTime: ['00:00:00', '23:59:59'],
 | 
			
		||||
					param: 'recordTime',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'button',
 | 
			
		||||
					btnName: '查询',
 | 
			
		||||
					name: 'search',
 | 
			
		||||
					color: 'primary',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'separate',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					type: 'button',
 | 
			
		||||
					btnName: '设备对比',
 | 
			
		||||
					name: 'compare',
 | 
			
		||||
					color: 'warning',
 | 
			
		||||
					plain: true,
 | 
			
		||||
				},
 | 
			
		||||
			],
 | 
			
		||||
			queryParams: {
 | 
			
		||||
				lineId: null,
 | 
			
		||||
				sectionId: null,
 | 
			
		||||
				equipmentId: null,
 | 
			
		||||
				recordTime: [],
 | 
			
		||||
			},
 | 
			
		||||
			graphList: [],
 | 
			
		||||
			open: false,
 | 
			
		||||
			eqList: [],
 | 
			
		||||
			// 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();
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		/** 重置查询条件 */
 | 
			
		||||
		initQuery() {
 | 
			
		||||
			this.queryParams.lineId = null;
 | 
			
		||||
			this.queryParams.equipmentId = null;
 | 
			
		||||
			this.queryParams.sectionId = null;
 | 
			
		||||
			this.queryParams.recordTime = [];
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 对象到数组的转换 */
 | 
			
		||||
		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,
 | 
			
		||||
					};
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleSearchBarBtnClick({ btnName, ...payload }) {
 | 
			
		||||
			switch (btnName) {
 | 
			
		||||
				case 'search':
 | 
			
		||||
					this.queryParams.lineId = payload.lineId || null;
 | 
			
		||||
					this.queryParams.sectionId = payload.sectionId || null;
 | 
			
		||||
					this.queryParams.equipmentId = payload.equipmentId || null;
 | 
			
		||||
					this.queryParams.recordTime = payload.recordTime || 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;
 | 
			
		||||
	background: #ccc;
 | 
			
		||||
	font-size: 18px;
 | 
			
		||||
	line-height: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.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: #84f04e;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.waiting {
 | 
			
		||||
	background-color: #409eff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.fault {
 | 
			
		||||
	background-color: #ea5b5b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.full {
 | 
			
		||||
	background-color: #e6a23c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.lack {
 | 
			
		||||
	background-color: #a69c8d;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.stop {
 | 
			
		||||
	background-color: #000c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.legend-row {
 | 
			
		||||
	margin: 12px 0;
 | 
			
		||||
	display: flex;
 | 
			
		||||
	> .legend:not(:last-child) {
 | 
			
		||||
		margin-right: 12px;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	.legend {
 | 
			
		||||
		display: flex;
 | 
			
		||||
		align-items: center;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	.icon {
 | 
			
		||||
		width: 16px;
 | 
			
		||||
		height: 16px;
 | 
			
		||||
		margin-right: 8px;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -12,80 +12,64 @@
 | 
			
		||||
			ref="search-bar"
 | 
			
		||||
			@headBtnClick="handleSearchBarBtnClick" />
 | 
			
		||||
 | 
			
		||||
		<!-- <base-table
 | 
			
		||||
			:table-props="[
 | 
			
		||||
				{ type: 'index', label: '序号' },
 | 
			
		||||
				{ prop: 'name', label: '设备名称', align: 'center' },
 | 
			
		||||
				{ prop: 'code', label: '设备代码', align: 'center' },
 | 
			
		||||
				{ prop: 'time', label: '时间', align: 'center' },
 | 
			
		||||
			]"
 | 
			
		||||
			:table-data="[
 | 
			
		||||
				{ index: 1, name: '1', code: 'c1', time: '2021-08-31 09:14:19' },
 | 
			
		||||
				{ index: 2, name: '2', code: 'c2', time: '2021-08-31 09:14:19' },
 | 
			
		||||
				{ index: 3, name: '3', code: 'c3', time: '2021-08-31 09:14:19' },
 | 
			
		||||
				{ index: 4, name: '4', code: 'c4', time: '2021-08-31 09:14:19' },
 | 
			
		||||
				{ index: 5, name: '5', code: 'c5', time: '2021-08-31 09:14:19' },
 | 
			
		||||
			]"
 | 
			
		||||
			:span-method="
 | 
			
		||||
				({ rowIndex, columnIndex }) => {
 | 
			
		||||
					if (rowIndex == 1 && columnIndex == 0) {
 | 
			
		||||
						return [1, 3];
 | 
			
		||||
					}
 | 
			
		||||
					return [1, 1];
 | 
			
		||||
				}
 | 
			
		||||
			"
 | 
			
		||||
			@emitFun="(val) => handleEmitFun(table, val)"></base-table> -->
 | 
			
		||||
 | 
			
		||||
		<div class="tables">
 | 
			
		||||
			<base-table
 | 
			
		||||
				:key="1 + '__basetable'"
 | 
			
		||||
				:table-props="table1.tableProps"
 | 
			
		||||
				:page="1"
 | 
			
		||||
				:limit="999"
 | 
			
		||||
				:table-data="table1.data"
 | 
			
		||||
				@emitFun="(val) => handleEmitFun(table1, val)"></base-table>
 | 
			
		||||
			<base-table
 | 
			
		||||
				:key="2 + '__basetable'"
 | 
			
		||||
				:table-props="table2.tableProps"
 | 
			
		||||
				:page="1"
 | 
			
		||||
				:limit="999"
 | 
			
		||||
				:table-data="table2.data"
 | 
			
		||||
				@emitFun="(val) => handleEmitFun(table2, val)"></base-table>
 | 
			
		||||
			<base-table
 | 
			
		||||
				:key="3 + '__basetable'"
 | 
			
		||||
				:table-props="table3.tableProps"
 | 
			
		||||
				:page="1"
 | 
			
		||||
				:limit="999"
 | 
			
		||||
				:table-data="table3.data"
 | 
			
		||||
				@emitFun="(val) => handleEmitFun(table3, val)"></base-table>
 | 
			
		||||
			<base-table
 | 
			
		||||
				:key="4 + '__basetable'"
 | 
			
		||||
				:table-props="table4.tableProps"
 | 
			
		||||
				:page="1"
 | 
			
		||||
				:limit="999"
 | 
			
		||||
				:table-data="table4.data"
 | 
			
		||||
				@emitFun="(val) => handleEmitFun(table4, val)"></base-table>
 | 
			
		||||
			<base-table
 | 
			
		||||
				:key="5 + '__basetable'"
 | 
			
		||||
				:table-props="table5.tableProps"
 | 
			
		||||
				:page="1"
 | 
			
		||||
				:limit="999"
 | 
			
		||||
				:table-data="table5.data"
 | 
			
		||||
				@emitFun="(val) => handleEmitFun(table5, val)"></base-table>
 | 
			
		||||
			<base-table
 | 
			
		||||
				:key="6 + '__basetable'"
 | 
			
		||||
				:table-props="table6.tableProps"
 | 
			
		||||
				:page="1"
 | 
			
		||||
				:limit="999"
 | 
			
		||||
				:table-data="table6.data"
 | 
			
		||||
				@emitFun="(val) => handleEmitFun(table6, val)"></base-table>
 | 
			
		||||
			<base-table
 | 
			
		||||
				:key="7 + '__basetable'"
 | 
			
		||||
				:table-props="table7.tableProps"
 | 
			
		||||
				:page="1"
 | 
			
		||||
				:limit="999"
 | 
			
		||||
				:table-data="table7.data"
 | 
			
		||||
				@emitFun="(val) => handleEmitFun(table7, val)"></base-table>
 | 
			
		||||
		</div>
 | 
			
		||||
		<!-- <div class="tables">
 | 
			
		||||
			<div class="table-wrapper" v-for="table in tableList" :key="table.key">
 | 
			
		||||
				<div class="table-title">PLC 1</div>
 | 
			
		||||
			<div class="custom-table" v-for="table in tableList" :key="table.key">
 | 
			
		||||
				<!-- {{ JSON.stringify(spanMethod) }} -->
 | 
			
		||||
				<base-table
 | 
			
		||||
					:key="table.key + '__basetable'"
 | 
			
		||||
					:table-props="table.tableProps"
 | 
			
		||||
					:page="1"
 | 
			
		||||
					:limit="999"
 | 
			
		||||
					:table-data="table.data"
 | 
			
		||||
					@emitFun="(val) => handleEmitFun(table, val)">
 | 
			
		||||
				</base-table>
 | 
			
		||||
					:table-data="table.dataManager?.dataList ?? []"
 | 
			
		||||
					:span-method="spanMethod"
 | 
			
		||||
					@emitFun="(val) => handleEmitFun(table, val)"></base-table>
 | 
			
		||||
				<pagination
 | 
			
		||||
					:key="table.key + '__pagination'"
 | 
			
		||||
					v-show="table.total > 0"
 | 
			
		||||
					:total="table.total"
 | 
			
		||||
					:page.sync="table.queryParams.pageNo"
 | 
			
		||||
					:limit.sync="table.queryParams.pageSize"
 | 
			
		||||
					@pagination="(val) => getListFor(table, val)" />
 | 
			
		||||
					:page.sync="table.pageNo"
 | 
			
		||||
					:limit.sync="table.pageSize"
 | 
			
		||||
					:page-size="table.pageSize"
 | 
			
		||||
					:page-sizes="[1, 3, 5, 10, 20]"
 | 
			
		||||
					@pagination="
 | 
			
		||||
						({ page, limit, current }) =>
 | 
			
		||||
							getListFor(table, { page, limit, current })
 | 
			
		||||
					" />
 | 
			
		||||
			</div>
 | 
			
		||||
		</div> -->
 | 
			
		||||
			<!-- v-show="table.dataManager?.total > 0"
 | 
			
		||||
				:total="table.dataManager?.total || 0" -->
 | 
			
		||||
			<!-- @size-change="($event) => handleSizeChange(table, $event)" -->
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import LocalDataManager from './utils/local-data-manager';
 | 
			
		||||
import response from './response';
 | 
			
		||||
import moment from 'moment';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'EquipmentFullParams',
 | 
			
		||||
	components: {},
 | 
			
		||||
@@ -138,286 +122,16 @@ export default {
 | 
			
		||||
				id: null,
 | 
			
		||||
				time: [new Date(aWeekAgo), new Date(today)],
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			table1: {
 | 
			
		||||
				tableProps: [
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'time',
 | 
			
		||||
						label: '时间',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'plcCode',
 | 
			
		||||
						label: 'PLC编码',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val1',
 | 
			
		||||
						label: '数值1',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol1',
 | 
			
		||||
						label: '布尔1',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val2',
 | 
			
		||||
						label: '数值2',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol2',
 | 
			
		||||
						label: '布尔2',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val3',
 | 
			
		||||
						label: '数值3',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol3',
 | 
			
		||||
						label: '布尔3',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val4',
 | 
			
		||||
						label: '数值4',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol4',
 | 
			
		||||
						label: '布尔4',
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				data: [
 | 
			
		||||
					{
 | 
			
		||||
						time: 1111111111111111,
 | 
			
		||||
						plcCode: 2,
 | 
			
		||||
						val1: 3,
 | 
			
		||||
						bol1: 4,
 | 
			
		||||
						val2: 5,
 | 
			
		||||
						bol2: 6,
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						time: 1,
 | 
			
		||||
						plcCode: 22222222222222,
 | 
			
		||||
						val1: 3,
 | 
			
		||||
						bol1: 4,
 | 
			
		||||
						val2: 5,
 | 
			
		||||
						bol2: 6,
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						time: 1,
 | 
			
		||||
						plcCode: 2,
 | 
			
		||||
						val1: 33333333333333,
 | 
			
		||||
						bol1: 4,
 | 
			
		||||
						val2: 5,
 | 
			
		||||
						bol2: 6,
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						time: 1,
 | 
			
		||||
						plcCode: 2,
 | 
			
		||||
						val1: 3,
 | 
			
		||||
						bol1: 44444444444444,
 | 
			
		||||
						val2: 5,
 | 
			
		||||
						bol2: 6,
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						time: 1,
 | 
			
		||||
						plcCode: 2,
 | 
			
		||||
						val1: 3,
 | 
			
		||||
						bol1: 4,
 | 
			
		||||
						val2: 5555555555555,
 | 
			
		||||
						bol2: 6,
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						time: 1,
 | 
			
		||||
						plcCode: 2,
 | 
			
		||||
						val1: 3,
 | 
			
		||||
						bol1: 4,
 | 
			
		||||
						val2: 5,
 | 
			
		||||
						bol2: 6666666666666666666,
 | 
			
		||||
					},
 | 
			
		||||
					{ time: 1, plcCode: 2, val1: 3, bol1: 4, val2: 5, bol2: 6 },
 | 
			
		||||
					{ time: 1, plcCode: 2, val1: 3, bol1: 4, val2: 5, bol2: 6 },
 | 
			
		||||
					{ time: 1, plcCode: 2, val1: 3, bol1: 4, val2: 5, bol2: 6 },
 | 
			
		||||
					{ time: 1, plcCode: 2, val1: 3, bol1: 4, val2: 5, bol2: 6 },
 | 
			
		||||
					{ time: 1, plcCode: 2, val1: 3, bol1: 4, val2: 5, bol2: 6 },
 | 
			
		||||
					{ time: 1, plcCode: 2, val1: 3, bol1: 4, val2: 5, bol2: 6 },
 | 
			
		||||
					{ time: 1, plcCode: 2, val1: 3, bol1: 4, val2: 5, bol2: 6 },
 | 
			
		||||
					{ time: 1, plcCode: 2, val1: 3, bol1: 4, val2: 5, bol2: 6 },
 | 
			
		||||
					{ time: 1, plcCode: 2, val1: 3, bol1: 4, val2: 5, bol2: 6 },
 | 
			
		||||
					{ time: 1, plcCode: 2, val1: 3, bol1: 4, val2: 5, bol2: 6 },
 | 
			
		||||
					{ time: 1, plcCode: 2, val1: 3, bol1: 4, val2: 5, bol2: 6 },
 | 
			
		||||
				],
 | 
			
		||||
			},
 | 
			
		||||
			table2: {
 | 
			
		||||
				tableProps: [
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'time',
 | 
			
		||||
						label: '时间',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'plcCode',
 | 
			
		||||
						label: 'PLC编码',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val1',
 | 
			
		||||
						label: '数值1',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol1',
 | 
			
		||||
						label: '布尔1',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val2',
 | 
			
		||||
						label: '数值2',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol2',
 | 
			
		||||
						label: '布尔2',
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				data: [],
 | 
			
		||||
			},
 | 
			
		||||
			table3: {
 | 
			
		||||
				tableProps: [
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'time',
 | 
			
		||||
						label: '时间',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'plcCode',
 | 
			
		||||
						label: 'PLC编码',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val1',
 | 
			
		||||
						label: '数值1',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol1',
 | 
			
		||||
						label: '布尔1',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val2',
 | 
			
		||||
						label: '数值2',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol2',
 | 
			
		||||
						label: '布尔2',
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				data: [],
 | 
			
		||||
			},
 | 
			
		||||
			table4: {
 | 
			
		||||
				tableProps: [
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'time',
 | 
			
		||||
						label: '时间',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'plcCode',
 | 
			
		||||
						label: 'PLC编码',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val1',
 | 
			
		||||
						label: '数值1',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol1',
 | 
			
		||||
						label: '布尔1',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val2',
 | 
			
		||||
						label: '数值2',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol2',
 | 
			
		||||
						label: '布尔2',
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				data: [],
 | 
			
		||||
			},
 | 
			
		||||
			table5: {
 | 
			
		||||
				tableProps: [
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'time',
 | 
			
		||||
						label: '时间',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'plcCode',
 | 
			
		||||
						label: 'PLC编码',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val1',
 | 
			
		||||
						label: '数值1',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol1',
 | 
			
		||||
						label: '布尔1',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val2',
 | 
			
		||||
						label: '数值2',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol2',
 | 
			
		||||
						label: '布尔2',
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				data: [],
 | 
			
		||||
			},
 | 
			
		||||
			table6: {
 | 
			
		||||
				tableProps: [
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'time',
 | 
			
		||||
						label: '时间',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'plcCode',
 | 
			
		||||
						label: 'PLC编码',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val1',
 | 
			
		||||
						label: '数值1',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol1',
 | 
			
		||||
						label: '布尔1',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val2',
 | 
			
		||||
						label: '数值2',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol2',
 | 
			
		||||
						label: '布尔2',
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				data: [],
 | 
			
		||||
			},
 | 
			
		||||
			table7: {
 | 
			
		||||
				tableProps: [
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'time',
 | 
			
		||||
						label: '时间',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'plcCode',
 | 
			
		||||
						label: 'PLC编码',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val1',
 | 
			
		||||
						label: '数值1',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol1',
 | 
			
		||||
						label: '布尔1',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'val2',
 | 
			
		||||
						label: '数值2',
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						prop: 'bol2',
 | 
			
		||||
						label: '布尔2',
 | 
			
		||||
					},
 | 
			
		||||
				],
 | 
			
		||||
				data: [],
 | 
			
		||||
			},
 | 
			
		||||
			tableList: [
 | 
			
		||||
				{
 | 
			
		||||
					key: 'base-table__key__1',
 | 
			
		||||
					tableProps: [],
 | 
			
		||||
					list: [],
 | 
			
		||||
					pageNo: 1,
 | 
			
		||||
					pageSize: 3,
 | 
			
		||||
					total: 0,
 | 
			
		||||
				},
 | 
			
		||||
			],
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	computed: {
 | 
			
		||||
@@ -437,8 +151,108 @@ export default {
 | 
			
		||||
			this.$set(this.searchBarFormConfig[0], 'defaultSelect', this.code);
 | 
			
		||||
		if (this.name)
 | 
			
		||||
			this.$set(this.searchBarFormConfig[1], 'defaultSelect', this.name);
 | 
			
		||||
 | 
			
		||||
		this.handleResponse();
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		buildProps(table) {
 | 
			
		||||
			console.log('building props', table);
 | 
			
		||||
			// 通过 otherList 来构建 props
 | 
			
		||||
			const { otherList } = table;
 | 
			
		||||
			const props = [
 | 
			
		||||
				{
 | 
			
		||||
					// type: 'index',
 | 
			
		||||
					width: 48,
 | 
			
		||||
					prop: 'index',
 | 
			
		||||
					label: '序号',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					width: 160,
 | 
			
		||||
					prop: 'time',
 | 
			
		||||
					label: '时间',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					width: 200,
 | 
			
		||||
					prop: 'plcCode',
 | 
			
		||||
					label: 'PLC编码',
 | 
			
		||||
					align: 'center',
 | 
			
		||||
				},
 | 
			
		||||
			];
 | 
			
		||||
			const firstLineData = {
 | 
			
		||||
				index: '参考值: [最小]-[最大][/标准]',
 | 
			
		||||
				time: null, // 此处必须是空白
 | 
			
		||||
				plcCode: null, // 此处必须是空白
 | 
			
		||||
			};
 | 
			
		||||
			otherList.forEach((item) => {
 | 
			
		||||
				props.push({
 | 
			
		||||
					label: item.name,
 | 
			
		||||
					align: 'center',
 | 
			
		||||
					prop: item.name,
 | 
			
		||||
					width: 128,
 | 
			
		||||
				});
 | 
			
		||||
				firstLineData[item.name] = `${item.minValue ?? ''}-${
 | 
			
		||||
					item.maxValue ?? ''
 | 
			
		||||
				}${item.defaultValue != null ? '/' + item.defaultValue : ''}`;
 | 
			
		||||
			});
 | 
			
		||||
			return { props, firstLineData };
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleResponse() {
 | 
			
		||||
			const { code, data } = response;
 | 
			
		||||
			if (code == 0) {
 | 
			
		||||
				console.log('response', code, data);
 | 
			
		||||
 | 
			
		||||
				// 处理一个表格
 | 
			
		||||
				data.forEach((table, index) => {
 | 
			
		||||
					console.log('handle index:', index, table);
 | 
			
		||||
					const { props: tableProps, firstLineData } = this.buildProps(table);
 | 
			
		||||
					this.$set(this.tableList, index, {
 | 
			
		||||
						key: 'base-table__key__' + index,
 | 
			
		||||
						tableProps,
 | 
			
		||||
						list: [firstLineData],
 | 
			
		||||
						dataManager: null,
 | 
			
		||||
						pageNo: 1,
 | 
			
		||||
						pageSize: 5,
 | 
			
		||||
						total: 0,
 | 
			
		||||
					});
 | 
			
		||||
 | 
			
		||||
					// 处理某一表格的各个行
 | 
			
		||||
					const { data } = table;
 | 
			
		||||
					data.forEach((row, idx) => {
 | 
			
		||||
						const listItem = {
 | 
			
		||||
							index: idx + 1,
 | 
			
		||||
							time: moment(+row.time).format('YYYY-MM-DD HH:mm:ss'),
 | 
			
		||||
							plcCode: row.plcCode,
 | 
			
		||||
						};
 | 
			
		||||
						row.data.forEach((column) => {
 | 
			
		||||
							listItem[column.dynamicName] = column.dynamicValue;
 | 
			
		||||
						});
 | 
			
		||||
						this.tableList[index].list.push(listItem);
 | 
			
		||||
						this.tableList[index].total++;
 | 
			
		||||
					});
 | 
			
		||||
 | 
			
		||||
					// 处理分页
 | 
			
		||||
					const { pageNo, pageSize, list } = this.tableList[index];
 | 
			
		||||
					this.tableList[index].dataManager = new LocalDataManager(
 | 
			
		||||
						list,
 | 
			
		||||
						pageNo,
 | 
			
		||||
						pageSize
 | 
			
		||||
					);
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		spanMethod({ row, column, rowIndex, columnIndex }) {
 | 
			
		||||
			if (rowIndex == 0 && columnIndex == 0) {
 | 
			
		||||
				return [1, 3];
 | 
			
		||||
			} else if (rowIndex == 0 && (columnIndex == 1 || columnIndex == 2)) {
 | 
			
		||||
				return [0, 0];
 | 
			
		||||
			}
 | 
			
		||||
			return [1, 1];
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 查询 */
 | 
			
		||||
		async handleQuery() {
 | 
			
		||||
			const { data } = this.$axios({
 | 
			
		||||
@@ -462,19 +276,11 @@ export default {
 | 
			
		||||
			console.log('table val', table, val);
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 构造 props */
 | 
			
		||||
		buildProps() {
 | 
			
		||||
			this.tableList.forEach((table) => {
 | 
			
		||||
				this.buildTableProp(table);
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		/** 构造一个 tableProps - 根据动态结构 */
 | 
			
		||||
		buildTableProp(table) {},
 | 
			
		||||
 | 
			
		||||
		/** 为某个 table 获取 list 数据 */
 | 
			
		||||
		getListFor(table, val) {
 | 
			
		||||
			console.log('get list for', table, val);
 | 
			
		||||
		getListFor(table, { page, limit, current }) {
 | 
			
		||||
			console.log('get list for', table, { page, limit, current });
 | 
			
		||||
			table.dataManager.pageNo = page ?? current;
 | 
			
		||||
			table.dataManager.pageSize = limit;
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
@@ -494,4 +300,8 @@ export default {
 | 
			
		||||
.tables >>> .baseTable {
 | 
			
		||||
	overflow-x: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.custom-table {
 | 
			
		||||
	overflow-x: hidden;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										247
									
								
								src/views/monitoring/equipmentFullParams/response.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								src/views/monitoring/equipmentFullParams/response.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,247 @@
 | 
			
		||||
export default {
 | 
			
		||||
	"code": 0,
 | 
			
		||||
	"data": [
 | 
			
		||||
		// 一个表格
 | 
			
		||||
		{
 | 
			
		||||
			"data": [
 | 
			
		||||
				// 一行参数
 | 
			
		||||
				{
 | 
			
		||||
					"time": "1694056192800",
 | 
			
		||||
					"plcCode": "PLC_CODE_1",
 | 
			
		||||
					"data": [
 | 
			
		||||
						// 一个参数值
 | 
			
		||||
						{ "id": 'param-1', "parentId": 0, "dynamicName": "P1V1", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-2', "parentId": 0, "dynamicName": "P1V2", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-3', "parentId": 0, "dynamicName": "P1V3", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-4', "parentId": 0, "dynamicName": "P1V4", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-5', "parentId": 0, "dynamicName": "P1V5", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-6', "parentId": 0, "dynamicName": "P1V6", "dynamicValue": 15 },
 | 
			
		||||
					]
 | 
			
		||||
				}
 | 
			
		||||
			],
 | 
			
		||||
			"otherList": [
 | 
			
		||||
				// 一个参数的属性
 | 
			
		||||
				{
 | 
			
		||||
					"id": "attr-1",
 | 
			
		||||
					"plcParamName": "P1V1",
 | 
			
		||||
					"name": "P1V1", // 和 dynamicName 对应
 | 
			
		||||
					"minValue": 1,
 | 
			
		||||
					"maxValue": 100
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"id": "attr-2",
 | 
			
		||||
					"plcParamName": "P1V2",
 | 
			
		||||
					"name": "P1V2",
 | 
			
		||||
					"minValue": 10,
 | 
			
		||||
					"maxValue": 90,
 | 
			
		||||
					"defaultValue": 24
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"id": "attr-3",
 | 
			
		||||
					"plcParamName": "P1V3",
 | 
			
		||||
					"name": "P1V3",
 | 
			
		||||
					"minValue": 10,
 | 
			
		||||
					"maxValue": 98
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"id": "attr-4",
 | 
			
		||||
					"plcParamName": "P1V4",
 | 
			
		||||
					"name": "P1V4",
 | 
			
		||||
					"minValue": 10,
 | 
			
		||||
					"maxValue": 90
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"id": "attr-5",
 | 
			
		||||
					"plcParamName": "P1V5",
 | 
			
		||||
					"name": "P1V5",
 | 
			
		||||
					"minValue": null,
 | 
			
		||||
					"maxValue": null
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"id": "attr-6",
 | 
			
		||||
					"plcParamName": "P1V6",
 | 
			
		||||
					"name": "P1V6",
 | 
			
		||||
					"minValue": null,
 | 
			
		||||
					"maxValue": null,
 | 
			
		||||
					"defaultValue": false
 | 
			
		||||
				},
 | 
			
		||||
			],
 | 
			
		||||
			"nameData": [],
 | 
			
		||||
			"otherMap": []
 | 
			
		||||
		},
 | 
			
		||||
		// 一个表格
 | 
			
		||||
		{
 | 
			
		||||
			"data": [
 | 
			
		||||
				// 一行参数
 | 
			
		||||
				{
 | 
			
		||||
					"time": "1694056100800",
 | 
			
		||||
					"plcCode": "PLC_CODE_2",
 | 
			
		||||
					"data": [
 | 
			
		||||
						// 一个参数值
 | 
			
		||||
						{ "id": 'param-1', "parentId": 0, "dynamicName": "P1V1", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-2', "parentId": 0, "dynamicName": "P1V2", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-3', "parentId": 0, "dynamicName": "P1V3", "dynamicValue": 15 },
 | 
			
		||||
 | 
			
		||||
					]
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"time": "1694056102800",
 | 
			
		||||
					"plcCode": "PLC_CODE_2",
 | 
			
		||||
					"data": [
 | 
			
		||||
						// 一个参数值
 | 
			
		||||
						{ "id": 'param-1', "parentId": 0, "dynamicName": "P1V1", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-2', "parentId": 0, "dynamicName": "P1V2", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-3', "parentId": 0, "dynamicName": "P1V3", "dynamicValue": 15 },
 | 
			
		||||
 | 
			
		||||
					]
 | 
			
		||||
				}
 | 
			
		||||
			],
 | 
			
		||||
			"otherList": [
 | 
			
		||||
				// 一个参数的属性
 | 
			
		||||
				{
 | 
			
		||||
					"id": "attr-1",
 | 
			
		||||
					"plcParamName": "P1V1",
 | 
			
		||||
					"name": "P1V1", // 和 dynamicName 对应
 | 
			
		||||
					"minValue": 1,
 | 
			
		||||
					"maxValue": 100
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"id": "attr-2",
 | 
			
		||||
					"plcParamName": "P1V2",
 | 
			
		||||
					"name": "P1V2",
 | 
			
		||||
					"minValue": 10,
 | 
			
		||||
					"maxValue": 90
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"id": "attr-3",
 | 
			
		||||
					"plcParamName": "P1V3",
 | 
			
		||||
					"name": "P1V3",
 | 
			
		||||
					"minValue": 10,
 | 
			
		||||
					"maxValue": 98
 | 
			
		||||
				},
 | 
			
		||||
			],
 | 
			
		||||
			"nameData": [],
 | 
			
		||||
			"otherMap": []
 | 
			
		||||
		},
 | 
			
		||||
		// 一个表格
 | 
			
		||||
		{
 | 
			
		||||
			"data": [
 | 
			
		||||
				// 一行参数
 | 
			
		||||
				{
 | 
			
		||||
					"time": "1694056100800",
 | 
			
		||||
					"plcCode": "PLC_CODE_2",
 | 
			
		||||
					"data": [
 | 
			
		||||
						// 一个参数值
 | 
			
		||||
						{ "id": 'param-1', "parentId": 0, "dynamicName": "P1V1", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-2', "parentId": 0, "dynamicName": "P1V2", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-3', "parentId": 0, "dynamicName": "P1V3", "dynamicValue": 15 },
 | 
			
		||||
 | 
			
		||||
					]
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"time": "1694056102800",
 | 
			
		||||
					"plcCode": "PLC_CODE_2",
 | 
			
		||||
					"data": [
 | 
			
		||||
						// 一个参数值
 | 
			
		||||
						{ "id": 'param-1', "parentId": 0, "dynamicName": "P1V1", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-2', "parentId": 0, "dynamicName": "P1V2", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-3', "parentId": 0, "dynamicName": "P1V3", "dynamicValue": 15 },
 | 
			
		||||
 | 
			
		||||
					]
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"time": "1694056109800",
 | 
			
		||||
					"plcCode": "PLC_CODE_2",
 | 
			
		||||
					"data": [
 | 
			
		||||
						// 一个参数值
 | 
			
		||||
						{ "id": 'param-1', "parentId": 0, "dynamicName": "P1V1", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-2', "parentId": 0, "dynamicName": "P1V2", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-3', "parentId": 0, "dynamicName": "P1V3", "dynamicValue": 15 },
 | 
			
		||||
 | 
			
		||||
					]
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"time": "1694066109800",
 | 
			
		||||
					"plcCode": "PLC_CODE_2",
 | 
			
		||||
					"data": [
 | 
			
		||||
						// 一个参数值
 | 
			
		||||
						{ "id": 'param-1', "parentId": 0, "dynamicName": "P1V1", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-2', "parentId": 0, "dynamicName": "P1V2", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-3', "parentId": 0, "dynamicName": "P1V3", "dynamicValue": 15 },
 | 
			
		||||
 | 
			
		||||
					]
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"time": "1694067109800",
 | 
			
		||||
					"plcCode": "PLC_CODE_2",
 | 
			
		||||
					"data": [
 | 
			
		||||
						// 一个参数值
 | 
			
		||||
						{ "id": 'param-1', "parentId": 0, "dynamicName": "P1V1", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-2', "parentId": 0, "dynamicName": "P1V2", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-3', "parentId": 0, "dynamicName": "P1V3", "dynamicValue": 15 },
 | 
			
		||||
 | 
			
		||||
					]
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"time": "1694068109800",
 | 
			
		||||
					"plcCode": "PLC_CODE_2",
 | 
			
		||||
					"data": [
 | 
			
		||||
						// 一个参数值
 | 
			
		||||
						{ "id": 'param-1', "parentId": 0, "dynamicName": "P1V1", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-2', "parentId": 0, "dynamicName": "P1V2", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-3', "parentId": 0, "dynamicName": "P1V3", "dynamicValue": 15 },
 | 
			
		||||
 | 
			
		||||
					]
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"time": "1694069109800",
 | 
			
		||||
					"plcCode": "PLC_CODE_2",
 | 
			
		||||
					"data": [
 | 
			
		||||
						// 一个参数值
 | 
			
		||||
						{ "id": 'param-1', "parentId": 0, "dynamicName": "P1V1", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-2', "parentId": 0, "dynamicName": "P1V2", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-3', "parentId": 0, "dynamicName": "P1V3", "dynamicValue": 15 },
 | 
			
		||||
 | 
			
		||||
					]
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"time": "1694071109800",
 | 
			
		||||
					"plcCode": "PLC_CODE_2",
 | 
			
		||||
					"data": [
 | 
			
		||||
						// 一个参数值
 | 
			
		||||
						{ "id": 'param-1', "parentId": 0, "dynamicName": "P1V1", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-2', "parentId": 0, "dynamicName": "P1V2", "dynamicValue": 15 },
 | 
			
		||||
						{ "id": 'param-3', "parentId": 0, "dynamicName": "P1V3", "dynamicValue": 15 },
 | 
			
		||||
 | 
			
		||||
					]
 | 
			
		||||
				}
 | 
			
		||||
			],
 | 
			
		||||
			"otherList": [
 | 
			
		||||
				// 一个参数的属性
 | 
			
		||||
				{
 | 
			
		||||
					"id": "attr-1",
 | 
			
		||||
					"plcParamName": "P1V1",
 | 
			
		||||
					"name": "P1V1", // 和 dynamicName 对应
 | 
			
		||||
					"minValue": 1,
 | 
			
		||||
					"maxValue": 100
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"id": "attr-2",
 | 
			
		||||
					"plcParamName": "P1V2",
 | 
			
		||||
					"name": "P1V2",
 | 
			
		||||
					"minValue": 10,
 | 
			
		||||
					"maxValue": 90
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"id": "attr-3",
 | 
			
		||||
					"plcParamName": "P1V3",
 | 
			
		||||
					"name": "P1V3",
 | 
			
		||||
					"minValue": 10,
 | 
			
		||||
					"maxValue": 98
 | 
			
		||||
				}
 | 
			
		||||
			],
 | 
			
		||||
			"nameData": [],
 | 
			
		||||
			"otherMap": []
 | 
			
		||||
		}
 | 
			
		||||
	]
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,36 @@
 | 
			
		||||
export default class LocalDataManager {
 | 
			
		||||
    constructor(dataList, pageNo, pageSize) {
 | 
			
		||||
        this._dataListStore = dataList;
 | 
			
		||||
        this._pageNo = pageNo;
 | 
			
		||||
        this._pageSize = pageSize;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    set pageNo(pageNo) {
 | 
			
		||||
        console.log('set pageNo', pageNo);
 | 
			
		||||
        this._pageNo = pageNo;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    set pageSize(pageSize) {
 | 
			
		||||
        console.log('set pageSize', pageSize);
 | 
			
		||||
        this._pageSize = pageSize;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get dataList() {
 | 
			
		||||
        const firstLine = this._dataListStore[0];
 | 
			
		||||
        const realDataList = this._dataListStore.slice(1);
 | 
			
		||||
        return [
 | 
			
		||||
            firstLine,
 | 
			
		||||
            ...realDataList.slice((this._pageNo - 1) * this._pageSize, this._pageNo * this._pageSize)
 | 
			
		||||
        ]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get total() {
 | 
			
		||||
        return this._dataListStore.length;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    deleteData(id) {
 | 
			
		||||
        const idx = this._dataListStore.findIndex(item => item.id == id);
 | 
			
		||||
        this._dataListStore.splice(idx, 1);
 | 
			
		||||
        // send http request
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -7,7 +7,6 @@
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="chart-wrapper">
 | 
			
		||||
		<h4>line graph</h4>
 | 
			
		||||
		<div class="chart" ref="chart"></div>
 | 
			
		||||
	</div>
 | 
			
		||||
</template>
 | 
			
		||||
@@ -18,22 +17,65 @@ import * as echarts from 'echarts';
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'LineChartInEquipmentProcessAmount',
 | 
			
		||||
	components: {},
 | 
			
		||||
	props: {},
 | 
			
		||||
	props: ['equipmentList'],
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			chart: null,
 | 
			
		||||
			option: {
 | 
			
		||||
				xAxis: {
 | 
			
		||||
					type: 'category',
 | 
			
		||||
					data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
 | 
			
		||||
				grid: {
 | 
			
		||||
					top: 64,
 | 
			
		||||
					left: 56,
 | 
			
		||||
					right: 24,
 | 
			
		||||
					bottom: 56,
 | 
			
		||||
				},
 | 
			
		||||
				title: {
 | 
			
		||||
					show: true,
 | 
			
		||||
					text: '各设备加工数量',
 | 
			
		||||
					textStyle: {
 | 
			
		||||
						color: '#232323',
 | 
			
		||||
						fontSize: 16,
 | 
			
		||||
					},
 | 
			
		||||
					left: 'center',
 | 
			
		||||
					top: 24,
 | 
			
		||||
				},
 | 
			
		||||
				yAxis: {
 | 
			
		||||
					type: 'category',
 | 
			
		||||
					axisLine: {
 | 
			
		||||
						show: true,
 | 
			
		||||
						lineStyle: {
 | 
			
		||||
							color: '#ccc',
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					axisTick: {
 | 
			
		||||
						show: false,
 | 
			
		||||
					},
 | 
			
		||||
					// data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
 | 
			
		||||
					data: [],
 | 
			
		||||
					name: '设备名',
 | 
			
		||||
					nameTextStyle: {
 | 
			
		||||
						fontSize: 14,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				xAxis: {
 | 
			
		||||
					type: 'value',
 | 
			
		||||
					axisLine: {
 | 
			
		||||
						show: true,
 | 
			
		||||
						lineStyle: {
 | 
			
		||||
							color: '#ccc',
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				series: [
 | 
			
		||||
					{
 | 
			
		||||
						data: [120, 200, 150, 80, 70, 110, 130],
 | 
			
		||||
						// data: [120, 200, 150, 80, 70, 110, 130],
 | 
			
		||||
						data: [],
 | 
			
		||||
						type: 'bar',
 | 
			
		||||
						barWidth: 20,
 | 
			
		||||
						label: {
 | 
			
		||||
							show: true,
 | 
			
		||||
							distance: 50,
 | 
			
		||||
							formatter: '{c}',
 | 
			
		||||
						},
 | 
			
		||||
						showBackground: true,
 | 
			
		||||
						backgroundStyle: {
 | 
			
		||||
							color: 'rgba(180, 180, 180, 0.2)',
 | 
			
		||||
@@ -44,13 +86,29 @@ export default {
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	mounted() {
 | 
			
		||||
		// console.log('this.eq list', this.equipmentList);
 | 
			
		||||
		if (!this.chart) this.chart = echarts.init(this.$refs.chart);
 | 
			
		||||
		this.chart.setOption(this.option);
 | 
			
		||||
 | 
			
		||||
		this.$nextTick(() => {
 | 
			
		||||
			this.chart.setOption(this.updateConfig(this.option));
 | 
			
		||||
		});
 | 
			
		||||
	},
 | 
			
		||||
	beforeDestroy() {
 | 
			
		||||
		this.chart.dispose();
 | 
			
		||||
	},
 | 
			
		||||
	methods: {},
 | 
			
		||||
	methods: {
 | 
			
		||||
		updateConfig(config) {
 | 
			
		||||
			let nameData = [];
 | 
			
		||||
			let valueData = [];
 | 
			
		||||
			this.equipmentList.map((eq) => {
 | 
			
		||||
				nameData.push(eq.equipmentName);
 | 
			
		||||
				valueData.push(eq.totalQuantity);
 | 
			
		||||
			});
 | 
			
		||||
			config.yAxis.data = nameData;
 | 
			
		||||
			config.series[0].data = valueData;
 | 
			
		||||
			return config;
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
@@ -58,8 +116,7 @@ export default {
 | 
			
		||||
.chart-wrapper {
 | 
			
		||||
	height: 100%;
 | 
			
		||||
	flex: 1;
 | 
			
		||||
	background: #f1f1f1;
 | 
			
		||||
	padding: 12px;
 | 
			
		||||
	// background: #f9f9f9;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chart {
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,8 @@
 | 
			
		||||
 | 
			
		||||
					<div class="graph" style="height: 56vh;" v-else>
 | 
			
		||||
						<!-- graph  -->
 | 
			
		||||
						<Graph />
 | 
			
		||||
						<Graph v-if="list.length" :equipment-list="list" />
 | 
			
		||||
						<div v-else style="color: #c7c7c7; text-align: center; margin-top: 20px;">没有设备</div>
 | 
			
		||||
					</div>
 | 
			
		||||
				</transition>
 | 
			
		||||
			</div>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user