update
This commit is contained in:
309
src/views/equipment/timing-diagram/status/chart.js
Normal file
309
src/views/equipment/timing-diagram/status/chart.js
Normal file
@@ -0,0 +1,309 @@
|
||||
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(el, startTime) {
|
||||
this.el = el;
|
||||
this.gridIndex = -1;
|
||||
this.currentGraphIndex = -2;
|
||||
this.startTime = new Date(startTime);
|
||||
// this.startTime = new Date(new Date('2023/10/8').toLocaleDateString());
|
||||
// console.log('<> Gantt Created', this.startTime);
|
||||
}
|
||||
|
||||
// 构造一个新的 grid
|
||||
makeGrid() {
|
||||
this.gridIndex++;
|
||||
return {
|
||||
id: 'GRID_' + this.gridIndex,
|
||||
// top: 12 + 128 * this.gridIndex,
|
||||
top: 12 + 104 * this.gridIndex,
|
||||
right: 48,
|
||||
left: 88,
|
||||
height: 56
|
||||
}
|
||||
}
|
||||
|
||||
// 构造一个 xAxis
|
||||
makeXaxis() {
|
||||
const [id1, id2] = ['' + Math.random(), '' + Math.random()]
|
||||
return [
|
||||
{
|
||||
id: id1,
|
||||
gridIndex: this.gridIndex,
|
||||
axisTick: {
|
||||
alignWithLabel: true,
|
||||
inside: true,
|
||||
},
|
||||
type: 'time',
|
||||
min: getTodayStart(this.startTime),
|
||||
max: getStartTime(this.startTime.getTime() + 3600 * 24 * 1000),
|
||||
splitNumber: 10,
|
||||
axisLabel: {
|
||||
margin: 12,
|
||||
formatter: function (val) {
|
||||
return new Date(val)
|
||||
.toLocaleTimeString()
|
||||
.split(':')
|
||||
.slice(0, 2)
|
||||
.join(':');
|
||||
},
|
||||
},
|
||||
boundaryGap: false,
|
||||
// data: getXaxisRange(getTodayStart(new Date())),
|
||||
},
|
||||
{
|
||||
id: id2,
|
||||
gridIndex: this.gridIndex,
|
||||
axisLabel: { show: false },
|
||||
axisLine: { show: false },
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
// 构造一个 yAxis
|
||||
makeYaxis(equipmentName) {
|
||||
const [id1, id2] = ['' + Math.random(), '' + Math.random()]
|
||||
return [
|
||||
// 主y轴
|
||||
{
|
||||
id: id1,
|
||||
gridIndex: this.gridIndex,
|
||||
type: 'value',
|
||||
splitLine: { show: false },
|
||||
name: equipmentName,
|
||||
nameLocation: 'center',
|
||||
nameGap: 14,
|
||||
nameRotate: 0,
|
||||
nameTextStyle: {
|
||||
fontSize: 16,
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {},
|
||||
},
|
||||
axisLabel: { show: false },
|
||||
axisTick: { show: false },
|
||||
},
|
||||
// 辅y轴
|
||||
{
|
||||
id: id2,
|
||||
gridIndex: this.gridIndex,
|
||||
type: 'value',
|
||||
splitLine: { show: false },
|
||||
axisLabel: { show: false },
|
||||
axisTick: { show: false },
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
// 构造一个 series
|
||||
makeSeries({ equipmentName, arr }) {
|
||||
this.currentGraphIndex += 2;
|
||||
const bgStartTime = this.startTime.getTime();
|
||||
const bgEndTime = bgStartTime + 3600 * 24 * 1000;
|
||||
return [
|
||||
// 沉默的背景
|
||||
{
|
||||
xAxisIndex: this.currentGraphIndex,
|
||||
yAxisIndex: this.currentGraphIndex,
|
||||
type: 'custom',
|
||||
renderItem: renderItem,
|
||||
silent: true,
|
||||
itemStyle: {
|
||||
opacity: 0.8,
|
||||
},
|
||||
encode: {
|
||||
x: [1, 2],
|
||||
y: 0,
|
||||
},
|
||||
data: [
|
||||
{
|
||||
name: '无数据',
|
||||
value: [0, bgStartTime, bgEndTime, 0],
|
||||
tooltip: { show: false },
|
||||
itemStyle: {
|
||||
color: '#F2F4F9',
|
||||
// opacity: 0.3,
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
name: equipmentName,
|
||||
xAxisIndex: this.currentGraphIndex,
|
||||
yAxisIndex: this.currentGraphIndex,
|
||||
type: 'custom',
|
||||
renderItem: renderItem,
|
||||
itemStyle: {
|
||||
opacity: 0.8,
|
||||
},
|
||||
encode: {
|
||||
x: [1, 2],
|
||||
y: 0,
|
||||
},
|
||||
data: arr.map(item => ({
|
||||
name: ['运行', '故障', '计划停机'][item.status],
|
||||
value: [0, item.startTime, item.startTime + item.duration * 60 * 1000, 0],
|
||||
itemStyle: {
|
||||
color: types[item.status].color,
|
||||
}
|
||||
})),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
init(data) {
|
||||
if (!this.el) throw new Error('没有可供echarts初始化的容器')
|
||||
if (typeof this.el == 'string') {
|
||||
this.el = document.querySelector(this.el);
|
||||
}
|
||||
this.chart = echarts.init(this.el);
|
||||
this.handleProps(data);
|
||||
|
||||
setTimeout(() => {
|
||||
// debugger;
|
||||
this.chart.setOption(this.option);
|
||||
}, 200);
|
||||
}
|
||||
|
||||
update(data) {
|
||||
this.clear();
|
||||
this.init(data);
|
||||
}
|
||||
|
||||
resize() {
|
||||
this.chart.resize();
|
||||
}
|
||||
|
||||
get option() {
|
||||
return {
|
||||
tooltip: this.tooltip,
|
||||
grid: this.grid,
|
||||
xAxis: this.xAxis,
|
||||
yAxis: this.yAxis,
|
||||
series: this.series,
|
||||
}
|
||||
}
|
||||
|
||||
// 每次 graphList 刷新都会重新渲染整个所有图表
|
||||
// 可以改进的地方:添加一个 handleAdd() 方法,一次添加一个新的
|
||||
handleProps(props) {
|
||||
// props 是父组件的 graphList
|
||||
console.log('props: ', props);
|
||||
props.forEach(eqArr => {
|
||||
this.grid.push(this.makeGrid());
|
||||
this.xAxis.push(...this.makeXaxis());
|
||||
this.yAxis.push(...this.makeYaxis(eqArr.key));
|
||||
this.series.push(...this.makeSeries({ equipmentName: eqArr.key, arr: eqArr }))
|
||||
});
|
||||
}
|
||||
|
||||
// handleAdd
|
||||
handleAdd() { }
|
||||
|
||||
clear() {
|
||||
this.grid = [];
|
||||
this.xAxis = [];
|
||||
this.yAxis = [];
|
||||
this.series = [];
|
||||
this.currentGraphIndex = -2;
|
||||
this.gridIndex = -1;
|
||||
this.chart.dispose();
|
||||
}
|
||||
|
||||
// print option
|
||||
print() {
|
||||
console.log(JSON.stringify(this.option, null, 2));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user