test #47
@ -0,0 +1,338 @@
|
|||||||
|
import * as echarts from 'echarts'
|
||||||
|
|
||||||
|
function getStartTime(timestamp) {
|
||||||
|
return new Date(new Date(timestamp).toLocaleDateString()).getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderItem(params, api) {
|
||||||
|
var categoryIndex = api.value(0);
|
||||||
|
var start = api.coord([api.value(1), categoryIndex]);
|
||||||
|
var end = api.coord([api.value(2), categoryIndex]);
|
||||||
|
|
||||||
|
var height = api.size([0, 1])[1] * 2;
|
||||||
|
var rectShape = echarts.graphic.clipRectByRect(
|
||||||
|
{
|
||||||
|
x: start[0],
|
||||||
|
y: start[1] - height / 2,
|
||||||
|
width: end[0] - start[0],
|
||||||
|
height: height,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: params.coordSys.x,
|
||||||
|
y: params.coordSys.y - 16,
|
||||||
|
width: params.coordSys.width,
|
||||||
|
height: params.coordSys.height,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
rectShape && {
|
||||||
|
type: 'rect',
|
||||||
|
transition: ['shape'],
|
||||||
|
shape: rectShape,
|
||||||
|
style: api.style(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// unused
|
||||||
|
function getXaxisRange(startTime) {
|
||||||
|
return Array(24)
|
||||||
|
.fill(startTime)
|
||||||
|
.map((item, index) => {
|
||||||
|
return new Date(item + index * 3600 * 1000)
|
||||||
|
.toLocaleTimeString()
|
||||||
|
.split(':')
|
||||||
|
.slice(0, 2)
|
||||||
|
.join(':');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTodayStart(today) {
|
||||||
|
const [y, m, d] = [
|
||||||
|
today.getFullYear(),
|
||||||
|
today.getMonth(),
|
||||||
|
today.getDate(),
|
||||||
|
];
|
||||||
|
// debugger;
|
||||||
|
return new Date(y, m, d).getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 颜色配置 */
|
||||||
|
const types = [
|
||||||
|
{ name: '运行', color: '#288AFF' },
|
||||||
|
{ name: '故障', color: '#FC9C91' },
|
||||||
|
{ name: '计划停机', color: '#FFDC94' },
|
||||||
|
{ name: '空白', color: '#F2F4F9' },
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
export default class GanttGraph {
|
||||||
|
// tooltip - 基本是固定的
|
||||||
|
tooltip = {
|
||||||
|
trigger: 'item',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'none',
|
||||||
|
},
|
||||||
|
formatter: (params) => {
|
||||||
|
return `
|
||||||
|
<div style="display: flex; align-items: center; justify-content: space-between">
|
||||||
|
<h1 style="font-size: 18px; font-weight: 600;">${params.seriesName}</h1>
|
||||||
|
<h2 style="font-size: 18px; font-weight: 400; letter-spacing: 1px;">${params.name} <span style="display: inline-block; margin-left: 8px; width: 12px; height: 12px; border-radius: 50%; background: ${params.color} "></span></h2>
|
||||||
|
</div>
|
||||||
|
<div>${new Date(params.value[1]).toLocaleString()} ~ ${new Date(params.value[2]).toLocaleString()}</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
grid = []
|
||||||
|
xAxis = []
|
||||||
|
yAxis = []
|
||||||
|
series = []
|
||||||
|
|
||||||
|
constructor(data, startTime) {
|
||||||
|
this.gridIndex = 0;
|
||||||
|
this.currentXaxisId = null;
|
||||||
|
this.currentYaxisId = null;
|
||||||
|
// this.startTime = new Date(startTime);
|
||||||
|
this.startTime = new Date(new Date().toLocaleDateString());
|
||||||
|
console.log('<> Gantt Created', this.startTime);
|
||||||
|
|
||||||
|
this.grid.push(this.makeGrid())
|
||||||
|
this.xAxis.push(...this.makeXaxis())
|
||||||
|
this.yAxis.push(...this.makeYaxis("设备1"))
|
||||||
|
this.series.push(...this.makeSeries({ equipmentName: "设备1" }))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造一个新的 grid
|
||||||
|
makeGrid() {
|
||||||
|
this.gridIndex++;
|
||||||
|
return {
|
||||||
|
id: 'GRID_' + this.gridIndex,
|
||||||
|
top: 12 + 64 * (this.gridIndex - 1),
|
||||||
|
right: 64,
|
||||||
|
height: 56
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造一个 xAxis
|
||||||
|
makeXaxis() {
|
||||||
|
const [id1, id2] = ['' + Math.random(), '' + Math.random()]
|
||||||
|
this.currentXaxisId = id1;
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: id1,
|
||||||
|
gridIndex: 'GRID_' + this.gridIndex,
|
||||||
|
axisTick: {
|
||||||
|
alignWithLabel: true,
|
||||||
|
inside: true,
|
||||||
|
},
|
||||||
|
type: 'time',
|
||||||
|
min: getTodayStart(this.startTime),
|
||||||
|
max: getStartTime(this.startTime.getTime() + 3600 * 24 * 1000),
|
||||||
|
splitNumber: 10,
|
||||||
|
axisLabel: {
|
||||||
|
margin: 12,
|
||||||
|
formatter: function (val) {
|
||||||
|
return new Date(val)
|
||||||
|
.toLocaleTimeString()
|
||||||
|
.split(':')
|
||||||
|
.slice(0, 2)
|
||||||
|
.join(':');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
boundaryGap: false,
|
||||||
|
// data: getXaxisRange(getTodayStart(new Date())),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: id2,
|
||||||
|
gridIndex: 'GRID_' + this.gridIndex,
|
||||||
|
axisLabel: { show: false },
|
||||||
|
axisLine: { show: false },
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 构造一个 yAxis
|
||||||
|
makeYaxis(equipmentName) {
|
||||||
|
const [id1, id2] = ['' + Math.random(), '' + Math.random()]
|
||||||
|
this.currentYaxisId = id1;
|
||||||
|
return [
|
||||||
|
// 主y轴
|
||||||
|
{
|
||||||
|
id: id1,
|
||||||
|
gridIndex: 'GRID_' + this.gridIndex,
|
||||||
|
type: 'value',
|
||||||
|
splitLine: { show: false },
|
||||||
|
name: equipmentName,
|
||||||
|
nameLocation: 'center',
|
||||||
|
nameGap: 56,
|
||||||
|
nameRotate: 0,
|
||||||
|
nameTextStyle: {
|
||||||
|
fontSize: 18,
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {},
|
||||||
|
},
|
||||||
|
axisLabel: { show: false },
|
||||||
|
axisTick: { show: false },
|
||||||
|
},
|
||||||
|
// 辅y轴
|
||||||
|
{
|
||||||
|
id: id2,
|
||||||
|
gridIndex: 'GRID_' + this.gridIndex,
|
||||||
|
type: 'value',
|
||||||
|
splitLine: { show: false },
|
||||||
|
axisLabel: { show: false },
|
||||||
|
axisTick: { show: false },
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造一个 series
|
||||||
|
makeSeries({ equipmentName }) {
|
||||||
|
const { currentXaxisId: xAxisIndex, currentYaxisId: yAxisIndex } = this;
|
||||||
|
const bgStartTime = this.startTime.getTime();
|
||||||
|
const bgEndTime = bgStartTime + 3600 * 24 * 1000;
|
||||||
|
return [
|
||||||
|
// 沉默的背景
|
||||||
|
{
|
||||||
|
xAxisIndex,
|
||||||
|
yAxisIndex,
|
||||||
|
type: 'custom',
|
||||||
|
renderItem: renderItem,
|
||||||
|
silent: true,
|
||||||
|
itemStyle: {
|
||||||
|
opacity: 0.8,
|
||||||
|
},
|
||||||
|
encode: {
|
||||||
|
x: [1, 2],
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
name: '无数据',
|
||||||
|
value: [0, bgStartTime, bgEndTime, 0],
|
||||||
|
tooltip: { show: false },
|
||||||
|
itemStyle: {
|
||||||
|
color: '#ccc',
|
||||||
|
opacity: 0.3,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: equipmentName,
|
||||||
|
xAxisIndex,
|
||||||
|
yAxisIndex,
|
||||||
|
type: 'custom',
|
||||||
|
renderItem: renderItem,
|
||||||
|
itemStyle: {
|
||||||
|
opacity: 0.8,
|
||||||
|
},
|
||||||
|
encode: {
|
||||||
|
x: [1, 2],
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
// 暂时先静态数据
|
||||||
|
{
|
||||||
|
name: '运行',
|
||||||
|
value: [0, 1696694400000, 1696699400000, 0],
|
||||||
|
itemStyle: {
|
||||||
|
|
||||||
|
color: types[0].color,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '运行',
|
||||||
|
value: [0, 1696730000000, 1696734040450, 0],
|
||||||
|
itemStyle: {
|
||||||
|
|
||||||
|
color: types[0].color,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '故障',
|
||||||
|
value: [0, 1696737040000, 1696754040450, 0],
|
||||||
|
itemStyle: {
|
||||||
|
|
||||||
|
color: types[1].color,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '计划停机',
|
||||||
|
value: [0, 1696755000000, 1696759000000, 0],
|
||||||
|
itemStyle: {
|
||||||
|
|
||||||
|
color: types[2].color,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '运行',
|
||||||
|
value: [0, 1696759000000, 1696769000000, 0],
|
||||||
|
itemStyle: {
|
||||||
|
|
||||||
|
color: types[0].color,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '计划停机',
|
||||||
|
value: [0, 1696769400000, 1696779000000, 0],
|
||||||
|
itemStyle: {
|
||||||
|
|
||||||
|
color: types[2].color,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
init(el) {
|
||||||
|
if (typeof el == 'string') {
|
||||||
|
el = document.querySelector(el);
|
||||||
|
}
|
||||||
|
this.chart = echarts.init(el);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log("init....", this.chart, this.option);
|
||||||
|
debugger;
|
||||||
|
this.chart.setOption(this.option);
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(data) {
|
||||||
|
// todo , handle data
|
||||||
|
this.chart.setOption(this.option);
|
||||||
|
}
|
||||||
|
|
||||||
|
resize() {
|
||||||
|
this.chart.resize();
|
||||||
|
}
|
||||||
|
|
||||||
|
get option() {
|
||||||
|
return {
|
||||||
|
tooltip: this.tooltip,
|
||||||
|
grid: this.grid,
|
||||||
|
xAxis: this.xAxis,
|
||||||
|
yAxis: this.yAxis,
|
||||||
|
series: this.series,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print option
|
||||||
|
print() {
|
||||||
|
console.log(JSON.stringify(this.option, null, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
607
src/views/equipment/timing-diagram/status/index copy.vue
Normal file
607
src/views/equipment/timing-diagram/status/index copy.vue
Normal file
@ -0,0 +1,607 @@
|
|||||||
|
<!--
|
||||||
|
filename: index.vue
|
||||||
|
author: liubin
|
||||||
|
date: 2023-09-04 09:34:52
|
||||||
|
description: 设备状态时序图
|
||||||
|
-->
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="status-timegraph-container"
|
||||||
|
style="background: #f2f4f9; flex: 1; display: flex; flex-direction: column">
|
||||||
|
<el-row
|
||||||
|
class=""
|
||||||
|
style="
|
||||||
|
margin-bottom: 12px;
|
||||||
|
background: #fff;
|
||||||
|
padding: 16px 16px 0;
|
||||||
|
border-radius: 8px;
|
||||||
|
">
|
||||||
|
<div class="blue-title">生产节拍时序图</div>
|
||||||
|
<!-- <h1>设备状态时序图</h1> -->
|
||||||
|
<!-- 搜索工作栏 -->
|
||||||
|
<SearchBar
|
||||||
|
:formConfigs="searchBarFormConfig"
|
||||||
|
ref="search-bar"
|
||||||
|
:remove-blue="true"
|
||||||
|
@select-changed="handleSearchBarSelectChange"
|
||||||
|
@headBtnClick="handleSearchBarBtnClick" />
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row
|
||||||
|
class=""
|
||||||
|
style="
|
||||||
|
height: 1px;
|
||||||
|
flex: 1;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
background: #fff;
|
||||||
|
padding: 16px 16px 32px;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="6">
|
||||||
|
<div class="blue-title">设备状态时序图</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="18" class="legend-row">
|
||||||
|
<div class="legend">
|
||||||
|
<div class="icon running"></div>
|
||||||
|
<div>运行中</div>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="legend">
|
||||||
|
<div class="icon waiting"></div>
|
||||||
|
<div>待机</div>
|
||||||
|
</div> -->
|
||||||
|
<div class="legend">
|
||||||
|
<div class="icon fault"></div>
|
||||||
|
<div>故障</div>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="legend">
|
||||||
|
<div class="icon lack"></div>
|
||||||
|
<div>缺料</div>
|
||||||
|
</div>
|
||||||
|
<div class="legend">
|
||||||
|
<div class="icon full"></div>
|
||||||
|
<div>满料</div>
|
||||||
|
</div> -->
|
||||||
|
<div class="legend">
|
||||||
|
<div class="icon stop"></div>
|
||||||
|
<div>计划停机</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<div
|
||||||
|
class="main-area"
|
||||||
|
style="flex: 1; display: flex; flex-direction: column">
|
||||||
|
<div
|
||||||
|
class="graphs"
|
||||||
|
v-show="graphList.length"
|
||||||
|
id="status-chart"
|
||||||
|
style="height: 1px; flex: 1"></div>
|
||||||
|
<h2 v-if="!graphList || graphList.length == 0" class="no-data-bg"></h2>
|
||||||
|
</div>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 对话框(添加 / 修改) -->
|
||||||
|
<base-dialog
|
||||||
|
dialogTitle="添加设备"
|
||||||
|
:dialogVisible="open"
|
||||||
|
width="500px"
|
||||||
|
@close="open = false"
|
||||||
|
@cancel="open = false"
|
||||||
|
@confirm="submitForm">
|
||||||
|
<el-select
|
||||||
|
v-if="open"
|
||||||
|
style="width: 100%"
|
||||||
|
v-model="queryParams.equipmentId"
|
||||||
|
placeholder="请选择一个设备">
|
||||||
|
<el-option
|
||||||
|
v-for="eq in eqList"
|
||||||
|
:key="eq.id"
|
||||||
|
:value="eq.id"
|
||||||
|
:label="eq.name"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</base-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// import * as echarts from 'echarts';
|
||||||
|
import Gantt from './gantt';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SGStatus',
|
||||||
|
components: {},
|
||||||
|
props: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
chart: null,
|
||||||
|
searchBarFormConfig: [
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '产线',
|
||||||
|
placeholder: '请选择产线',
|
||||||
|
selectOptions: [],
|
||||||
|
param: 'lineId',
|
||||||
|
onchange: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '工段',
|
||||||
|
placeholder: '请选择工段',
|
||||||
|
selectOptions: [],
|
||||||
|
param: 'sectionId',
|
||||||
|
},
|
||||||
|
// 时间段
|
||||||
|
{
|
||||||
|
type: 'datePicker',
|
||||||
|
label: '时间段',
|
||||||
|
dateType: 'date',
|
||||||
|
format: 'yyyy-MM-dd',
|
||||||
|
valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||||
|
rangeSeparator: '-',
|
||||||
|
placeholder: '选择日期',
|
||||||
|
param: 'recordTime',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
btnName: '查询',
|
||||||
|
name: 'search',
|
||||||
|
color: 'primary',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
btnName: '添加对比',
|
||||||
|
name: 'compare',
|
||||||
|
color: 'primary',
|
||||||
|
plain: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
queryParams: {
|
||||||
|
lineId: null,
|
||||||
|
sectionId: null,
|
||||||
|
equipmentId: null,
|
||||||
|
recordTime: null,
|
||||||
|
},
|
||||||
|
graphList: [],
|
||||||
|
open: false,
|
||||||
|
eqList: [],
|
||||||
|
startTime: null,
|
||||||
|
gantt: null
|
||||||
|
// demo: [
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// equipmentName: '下片机',
|
||||||
|
// duration: 30,
|
||||||
|
// relativeDuration: 0.6,
|
||||||
|
// status: 0,
|
||||||
|
// startPos: 0,
|
||||||
|
// startTime: 1691568181000,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// equipmentName: '下片机',
|
||||||
|
// duration: 20,
|
||||||
|
// relativeDuration: 0.4,
|
||||||
|
// status: 2,
|
||||||
|
// startPos: 30,
|
||||||
|
// startTime: 1691569981000
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// ],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
created() {
|
||||||
|
this.initProductline();
|
||||||
|
this.initWorksection();
|
||||||
|
this.initEquipment();
|
||||||
|
// this.getList();
|
||||||
|
},
|
||||||
|
mounted() {},
|
||||||
|
watch: {
|
||||||
|
graphList: {
|
||||||
|
handler(val) {
|
||||||
|
if (val && val.length) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (!this.chart) this.initChart();
|
||||||
|
this.setInitialConfig();
|
||||||
|
this.handleGraphList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setInitialConfig() {
|
||||||
|
console.log('in setInitialConfig', this.chartOption);
|
||||||
|
this.chart.setOption(this.chartOption);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleGraphList() {
|
||||||
|
console.log('in handleGraphList:', this.graphList);
|
||||||
|
return;
|
||||||
|
const min = this.queryParams.recordTime
|
||||||
|
? new Date(this.queryParams.recordTime).getTime()
|
||||||
|
: this.findMin();
|
||||||
|
|
||||||
|
console.log('min is', min);
|
||||||
|
this.chartOption.xAxis.min = getStartTime(min);
|
||||||
|
this.chartOption.xAxis.max = getStartTime(min + 3600 * 24 * 1000);
|
||||||
|
this.graphList.forEach((arr) => {
|
||||||
|
this.chartOption.yAxis[0].data.push(arr.key);
|
||||||
|
arr.forEach((item) => {
|
||||||
|
this.chartOption.series[0].data.push({
|
||||||
|
name: ['运行', '故障', '计划停机'][item.status],
|
||||||
|
value: [
|
||||||
|
0,
|
||||||
|
item.startTime,
|
||||||
|
item.startTime + item.duration * 60 * 1000,
|
||||||
|
item.duration * 60 * 1000,
|
||||||
|
],
|
||||||
|
itemStyle: {
|
||||||
|
normal: {
|
||||||
|
color: types[item.status].color,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
console.log('chartOptions', this.chartOption);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
findMin() {
|
||||||
|
let min = 0;
|
||||||
|
this.graphList.forEach((arr) => {
|
||||||
|
arr.forEach((item) => {
|
||||||
|
if (min < item.startTime) min = item.startTime;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return min;
|
||||||
|
},
|
||||||
|
|
||||||
|
initChart() {
|
||||||
|
const el = document.getElementById('status-chart');
|
||||||
|
this.gantt = new Gantt(el);
|
||||||
|
this.gantt.init();
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 重置查询条件 */
|
||||||
|
initQuery() {
|
||||||
|
this.queryParams.lineId = null;
|
||||||
|
this.queryParams.equipmentId = null;
|
||||||
|
this.queryParams.sectionId = null;
|
||||||
|
this.queryParams.recordTime = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 对象到数组的转换 */
|
||||||
|
objectToArray(obj) {
|
||||||
|
return Object.keys(obj).map((key) => {
|
||||||
|
obj[key].sort((a, b) => a.startTime - b.startTime);
|
||||||
|
obj[key].key = key;
|
||||||
|
return obj[key];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async getList() {
|
||||||
|
const { code, data } = await this.$axios({
|
||||||
|
url: '/analysis/equipment-analysis/status',
|
||||||
|
method: 'get',
|
||||||
|
params: this.queryParams,
|
||||||
|
});
|
||||||
|
if (code == 0) {
|
||||||
|
this.graphList = this.objectToArray(data);
|
||||||
|
console.log('graph list', this.graphList);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 准备设备数据 */
|
||||||
|
async initEquipment() {
|
||||||
|
const { code, data } = await this.$axios({
|
||||||
|
url: '/base/equipment/listAll',
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
if (code == 0) {
|
||||||
|
this.eqList = data.map((item) => {
|
||||||
|
return {
|
||||||
|
name: item.name,
|
||||||
|
id: item.id,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 准备产线数据 */
|
||||||
|
async initProductline() {
|
||||||
|
const { code, data } = await this.$axios({
|
||||||
|
url: '/base/production-line/listAll',
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
if (code == 0) {
|
||||||
|
this.searchBarFormConfig[0].selectOptions = data.map((item) => {
|
||||||
|
return {
|
||||||
|
name: item.name,
|
||||||
|
id: item.id,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 准备工段数据 */
|
||||||
|
async initWorksection() {
|
||||||
|
const { code, data } = await this.$axios({
|
||||||
|
url: '/base/workshop-section/listAll',
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
if (code == 0) {
|
||||||
|
this.searchBarFormConfig[1].selectOptions = data.map((item) => {
|
||||||
|
return {
|
||||||
|
name: item.name,
|
||||||
|
id: item.id,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSearchBarSelectChange({ param, value }) {
|
||||||
|
if (!value) {
|
||||||
|
this.searchBarFormConfig[1].selectOptions = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (param) {
|
||||||
|
case 'lineId':
|
||||||
|
this.$axios({
|
||||||
|
url: '/base/workshop-section/listByParentId',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
id: value,
|
||||||
|
},
|
||||||
|
}).then(({ code, data }) => {
|
||||||
|
if (code == 0) {
|
||||||
|
this.searchBarFormConfig[1].selectOptions = data.map((item) => {
|
||||||
|
return {
|
||||||
|
name: item.name,
|
||||||
|
id: item.id,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSearchBarBtnClick({ btnName, ...payload }) {
|
||||||
|
switch (btnName) {
|
||||||
|
case 'search':
|
||||||
|
if (!payload.recordTime || payload.recordTime.length <= 0) {
|
||||||
|
this.$message.error('请选择时间段');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.startTime = new Date(payload.recordTime).getTime();
|
||||||
|
|
||||||
|
this.queryParams.lineId = payload.lineId || null;
|
||||||
|
this.queryParams.sectionId = payload.sectionId || null;
|
||||||
|
this.queryParams.equipmentId = payload.equipmentId || null;
|
||||||
|
this.queryParams.recordTime = payload.recordTime
|
||||||
|
? [
|
||||||
|
payload.recordTime,
|
||||||
|
new Date(
|
||||||
|
new Date(payload.recordTime).getTime() + 24 * 3600 * 1000
|
||||||
|
)
|
||||||
|
.toLocaleDateString()
|
||||||
|
.split('/')
|
||||||
|
.map((value, index) => {
|
||||||
|
if (index == 1 || index == 2) {
|
||||||
|
return value.padStart(2, '0');
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
})
|
||||||
|
.join('-') + ' 00:00:00',
|
||||||
|
]
|
||||||
|
: null;
|
||||||
|
this.getList();
|
||||||
|
break;
|
||||||
|
case 'compare':
|
||||||
|
this.open = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async submitForm() {
|
||||||
|
const { code, data } = await this.$axios({
|
||||||
|
url: '/analysis/equipment-analysis/status',
|
||||||
|
method: 'get',
|
||||||
|
params: this.queryParams,
|
||||||
|
});
|
||||||
|
if (code == 0) {
|
||||||
|
const newEqlist = this.objectToArray(data);
|
||||||
|
if (!newEqlist || newEqlist.length == 0) {
|
||||||
|
this.$message.error('该设备没有状态数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.graphList.push(newEqlist[0]);
|
||||||
|
}
|
||||||
|
this.open = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.graph {
|
||||||
|
// border: 1px solid #ccc;
|
||||||
|
// padding: 12px 12px 28px 12px;
|
||||||
|
// margin: 64px 0;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graph-title {
|
||||||
|
// position: absolute;
|
||||||
|
// top: -64px;
|
||||||
|
// left: -1px;
|
||||||
|
// padding: 8px 18px;
|
||||||
|
padding: 0 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graph-content {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
padding: 22px 12px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-bottom-width: 2px;
|
||||||
|
border-top: none;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graph-content::after,
|
||||||
|
.graph-content::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: 3px;
|
||||||
|
height: 80%;
|
||||||
|
background: #fff;
|
||||||
|
right: -1px;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graph-content::before {
|
||||||
|
right: unset;
|
||||||
|
left: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graph-item,
|
||||||
|
.graph-item-fixed {
|
||||||
|
// height: 88px;
|
||||||
|
// width: 24px;
|
||||||
|
flex: 1;
|
||||||
|
// border: 1px solid #ccc;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graph-item-fixed {
|
||||||
|
flex: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graph-item::before,
|
||||||
|
.graph-item-fixed::before {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -16px;
|
||||||
|
left: 0;
|
||||||
|
content: attr(data-time);
|
||||||
|
// font-size - js
|
||||||
|
// rotate - js
|
||||||
|
// color - js, default:
|
||||||
|
color: #777;
|
||||||
|
transform-origin: left top;
|
||||||
|
transform: rotate(12deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.graph-item-fixed::after,
|
||||||
|
.graph-item::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: -3px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graph-item.tick::after,
|
||||||
|
.graph-item-fixed.tick::after {
|
||||||
|
width: 1px;
|
||||||
|
height: 6px;
|
||||||
|
border-left: 1px solid #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
.running {
|
||||||
|
background-color: #5ad8a6;
|
||||||
|
// background-color: #84f04e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.waiting {
|
||||||
|
background-color: #5ad8a6;
|
||||||
|
// background-color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fault {
|
||||||
|
// background-color: #ea5b5b;
|
||||||
|
background-color: #fc9c91;
|
||||||
|
}
|
||||||
|
|
||||||
|
.full {
|
||||||
|
// background-color: #e6a23c;
|
||||||
|
background-color: #598fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lack {
|
||||||
|
// background-color: #a69c8d;
|
||||||
|
background-color: #7585a2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stop {
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-row {
|
||||||
|
margin: 6px 0;
|
||||||
|
padding-right: 12px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
> .legend:not(:last-child) {
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 2px;
|
||||||
|
margin-right: 4px;
|
||||||
|
margin-top: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.blue-title {
|
||||||
|
position: relative;
|
||||||
|
padding: 4px 0;
|
||||||
|
padding-left: 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 6px;
|
||||||
|
height: 16px;
|
||||||
|
width: 4px;
|
||||||
|
border-radius: 1px;
|
||||||
|
background: #0b58ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.echarts__status-chart {
|
||||||
|
background: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.echarts__status-chart > div {
|
||||||
|
height: 100% !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
</style>
|
@ -6,31 +6,19 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div class="status-timegraph-container" style="background: #f2f4f9; flex: 1; display: flex; flex-direction: column">
|
||||||
class="status-timegraph-container"
|
<el-row class="" style="
|
||||||
style="background: #f2f4f9; flex: 1; display: flex; flex-direction: column">
|
|
||||||
<el-row
|
|
||||||
class=""
|
|
||||||
style="
|
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 16px 16px 0;
|
padding: 16px 16px 0;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
">
|
">
|
||||||
<div class="blue-title">生产节拍时序图</div>
|
<div class="blue-title">生产节拍时序图</div>
|
||||||
<!-- <h1>设备状态时序图</h1> -->
|
<SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" :remove-blue="true"
|
||||||
<!-- 搜索工作栏 -->
|
@select-changed="handleSearchBarSelectChange" @headBtnClick="handleSearchBarBtnClick" />
|
||||||
<SearchBar
|
|
||||||
:formConfigs="searchBarFormConfig"
|
|
||||||
ref="search-bar"
|
|
||||||
:remove-blue="true"
|
|
||||||
@select-changed="handleSearchBarSelectChange"
|
|
||||||
@headBtnClick="handleSearchBarBtnClick" />
|
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row
|
<el-row class="" style="
|
||||||
class=""
|
|
||||||
style="
|
|
||||||
height: 1px;
|
height: 1px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
@ -49,58 +37,27 @@
|
|||||||
<div class="icon running"></div>
|
<div class="icon running"></div>
|
||||||
<div>运行中</div>
|
<div>运行中</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="legend">
|
|
||||||
<div class="icon waiting"></div>
|
|
||||||
<div>待机</div>
|
|
||||||
</div> -->
|
|
||||||
<div class="legend">
|
<div class="legend">
|
||||||
<div class="icon fault"></div>
|
<div class="icon fault"></div>
|
||||||
<div>故障</div>
|
<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="legend">
|
||||||
<div class="icon stop"></div>
|
<div class="icon stop"></div>
|
||||||
<div>计划停机</div>
|
<div>计划停机</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<div
|
<div class="main-area" style="flex: 1; background: lightyellow; display: flex; flex-direction: column">
|
||||||
class="main-area"
|
<div class="graphs" v-show="graphList.length" id="status-chart" style="height: 1px; flex: 1"></div>
|
||||||
style="flex: 1; display: flex; flex-direction: column">
|
|
||||||
<div
|
|
||||||
class="graphs"
|
|
||||||
v-show="graphList.length"
|
|
||||||
id="status-chart"
|
|
||||||
style="height: 1px; flex: 1"></div>
|
|
||||||
<h2 v-if="!graphList || graphList.length == 0" class="no-data-bg"></h2>
|
<h2 v-if="!graphList || graphList.length == 0" class="no-data-bg"></h2>
|
||||||
</div>
|
</div>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<!-- 对话框(添加 / 修改) -->
|
<!-- 对话框(添加 / 修改) -->
|
||||||
<base-dialog
|
<base-dialog dialogTitle="添加设备" :dialogVisible="open" width="500px" @close="open = false" @cancel="open = false"
|
||||||
dialogTitle="添加设备"
|
|
||||||
:dialogVisible="open"
|
|
||||||
width="500px"
|
|
||||||
@close="open = false"
|
|
||||||
@cancel="open = false"
|
|
||||||
@confirm="submitForm">
|
@confirm="submitForm">
|
||||||
<el-select
|
<el-select v-if="open" style="width: 100%" v-model="queryParams.equipmentId" placeholder="请选择一个设备">
|
||||||
v-if="open"
|
<el-option v-for="eq in eqList" :key="eq.id" :value="eq.id" :label="eq.name"></el-option>
|
||||||
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>
|
</el-select>
|
||||||
</base-dialog>
|
</base-dialog>
|
||||||
</div>
|
</div>
|
||||||
@ -108,7 +65,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
// import * as echarts from 'echarts';
|
// import * as echarts from 'echarts';
|
||||||
import Gantt from './gantt';
|
import Gantt from './demo';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SGStatus',
|
name: 'SGStatus',
|
||||||
@ -208,9 +165,16 @@ export default {
|
|||||||
handler(val) {
|
handler(val) {
|
||||||
if (val && val.length) {
|
if (val && val.length) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
if (!this.chart) this.initChart();
|
// if (!this.chart) this.initChart();
|
||||||
this.setInitialConfig();
|
// this.setInitialConfig();
|
||||||
this.handleGraphList();
|
// this.handleGraphList();
|
||||||
|
if (!this.gantt) {
|
||||||
|
this.gantt = new Gantt(null, this.startTime);
|
||||||
|
this.gantt.init('#status-chart');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.gantt.update(val);
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -385,7 +349,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.startTime = new Date(payload.recordTime).getTime();
|
this.startTime = new Date(payload.recordTime).getTime();
|
||||||
|
console.log("startTime", new Date(payload.recordTime).getTime());
|
||||||
this.queryParams.lineId = payload.lineId || null;
|
this.queryParams.lineId = payload.lineId || null;
|
||||||
this.queryParams.sectionId = payload.sectionId || null;
|
this.queryParams.sectionId = payload.sectionId || null;
|
||||||
this.queryParams.equipmentId = payload.equipmentId || null;
|
this.queryParams.equipmentId = payload.equipmentId || null;
|
||||||
|
Loading…
Reference in New Issue
Block a user