|
|
@@ -12,39 +12,149 @@ |
|
|
|
|
|
|
|
<script src="./echarts.js"></script> |
|
|
|
<script> |
|
|
|
function getStartTime(timestamp) { |
|
|
|
return new Date(new Date(timestamp).toLocaleDateString()).getTime(); |
|
|
|
} |
|
|
|
|
|
|
|
function renderItem(params, api) { |
|
|
|
var categoryIndex = api.value(0); |
|
|
|
var start = api.coord([api.value(1), categoryIndex]); |
|
|
|
var end = api.coord([api.value(2), categoryIndex]); |
|
|
|
console.log(` |
|
|
|
categoryIndex: ${categoryIndex}, |
|
|
|
start: ${start}, |
|
|
|
end: ${end}, |
|
|
|
api.value0: ${api.value(0)} |
|
|
|
api.value1: ${api.value(1)} |
|
|
|
api.value2: ${api.value(2)} |
|
|
|
params.coordSys: ${JSON.stringify(params.coordSys)} |
|
|
|
api.size: ${api.size([0, 1])} |
|
|
|
api.style(): ${JSON.stringify(api.style())} |
|
|
|
`); |
|
|
|
|
|
|
|
var height = api.size([0, 1])[1] * 2; |
|
|
|
// 用一个矩形去截取另一个矩形 |
|
|
|
var rectShape = echarts.graphic.clipRectByRect( |
|
|
|
// 被截取矩形 |
|
|
|
{ |
|
|
|
x: start[0], |
|
|
|
y: start[1] - height / 2, |
|
|
|
width: end[0] - start[0], |
|
|
|
height: height, |
|
|
|
}, |
|
|
|
// 截取矩形 |
|
|
|
{ |
|
|
|
// 截取掉grid以外的部分,实质是计算方块的偏移量 |
|
|
|
x: params.coordSys.x, // {number} grid rect 的 x |
|
|
|
// y: params.coordSys.y, // {number} grid rect 的 y |
|
|
|
y: params.coordSys.y - 16, // {number} grid rect 的 y,并多减掉 16 个单位 |
|
|
|
width: params.coordSys.width, // {number} grid rect 的 width |
|
|
|
height: params.coordSys.height, // {number} grid rect 的 height |
|
|
|
} |
|
|
|
); |
|
|
|
console.log(`------------- ${JSON.stringify(rectShape)} -------------- `) |
|
|
|
return ( |
|
|
|
rectShape && { |
|
|
|
type: 'rect', |
|
|
|
transition: ['shape'], |
|
|
|
shape: rectShape, |
|
|
|
style: api.style(), |
|
|
|
} |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
function getXaxisRange(startTime) { |
|
|
|
return Array(24) |
|
|
|
.fill(startTime) |
|
|
|
.map((item, index) => { |
|
|
|
return new Date(item + index * 3600 * 1000) |
|
|
|
.toLocaleTimeString() |
|
|
|
.split(':') |
|
|
|
.slice(0, 2) |
|
|
|
.join(':'); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
function getTodayStart(today) { |
|
|
|
const [y, m, d] = [ |
|
|
|
today.getFullYear(), |
|
|
|
today.getMonth(), |
|
|
|
today.getDate(), |
|
|
|
]; |
|
|
|
return new Date(y, m, d).getTime(); |
|
|
|
} |
|
|
|
|
|
|
|
/** 颜色配置 */ |
|
|
|
const types = [ |
|
|
|
{ name: '运行', color: '#288AFF' }, |
|
|
|
{ name: '故障', color: '#FC9C91' }, |
|
|
|
{ name: '计划停机', color: '#FFDC94' }, |
|
|
|
{ name: '空白', color: '#F2F4F9' }, |
|
|
|
]; |
|
|
|
|
|
|
|
const option = { |
|
|
|
tooltip: { |
|
|
|
trigger: 'axis', |
|
|
|
axisPointer: { |
|
|
|
type: 'line', |
|
|
|
label: { |
|
|
|
backgroundColor: '#6a7985', |
|
|
|
}, |
|
|
|
type: 'none', |
|
|
|
// label: { |
|
|
|
// backgroundColor: '#6a7985', |
|
|
|
// }, |
|
|
|
}, |
|
|
|
formatter: (params) => { |
|
|
|
// console.log('formatter', params) |
|
|
|
// return ` |
|
|
|
// <div>${new Date(params[0].value[1]).toLocaleString()} ~ ${new Date(params[0].value[2]).toLocaleString()}</div> |
|
|
|
// <div style="display: flex; justify-content: space-between; min-width: 128px; align-items: center;"> |
|
|
|
// <span>${params[0].seriesName}</span> |
|
|
|
// <span>${params[0].name}</span> |
|
|
|
// </div> |
|
|
|
// ` |
|
|
|
return ` |
|
|
|
<h1 style="font-size: 18px; font-weight: 600; letter-spacing: 1px;">${params[0].name} <span style="display: inline-block; margin-left: 8px; width: 12px; height: 12px; border-radius: 50%; background: ${params[0].color} "></span></h1> |
|
|
|
<div>${new Date(params[0].value[1]).toLocaleString()} ~ ${new Date(params[0].value[2]).toLocaleString()}</div> |
|
|
|
` |
|
|
|
} |
|
|
|
}, |
|
|
|
grid: [ |
|
|
|
{ |
|
|
|
id: 0, |
|
|
|
top: 10, |
|
|
|
height: 40, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 1, |
|
|
|
top: 80, |
|
|
|
height: 40, |
|
|
|
left: 128, |
|
|
|
right: 64, |
|
|
|
height: 56, |
|
|
|
}, |
|
|
|
// { |
|
|
|
// id: 1, |
|
|
|
// top: 80, |
|
|
|
// height: 56, |
|
|
|
// }, |
|
|
|
], |
|
|
|
xAxis: [ |
|
|
|
{ |
|
|
|
id: 0, |
|
|
|
gridIndex: 0, |
|
|
|
type: 'category', |
|
|
|
axisTick: { |
|
|
|
alignWithLabel: true, |
|
|
|
inside: true, |
|
|
|
}, |
|
|
|
type: 'time', |
|
|
|
min: getTodayStart(new Date()), // <=== |
|
|
|
max: getStartTime(new Date().getTime() + 3600 * 24 * 1000), // <=== |
|
|
|
splitNumber: 10, |
|
|
|
axisLabel: { |
|
|
|
margin: 12, |
|
|
|
// rotate: -15, |
|
|
|
formatter: function (val) { |
|
|
|
return new Date(val) |
|
|
|
.toLocaleTimeString() |
|
|
|
.split(':') |
|
|
|
.slice(0, 2) |
|
|
|
.join(':'); |
|
|
|
}, |
|
|
|
}, |
|
|
|
boundaryGap: false, |
|
|
|
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], |
|
|
|
// data: getXaxisRange(getTodayStart(new Date())), |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 1, |
|
|
@@ -52,23 +162,6 @@ |
|
|
|
axisLabel: { show: false }, |
|
|
|
axisLine: { show: false }, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 2, |
|
|
|
gridIndex: 1, |
|
|
|
type: 'category', |
|
|
|
axisTick: { |
|
|
|
alignWithLabel: true, |
|
|
|
inside: true, |
|
|
|
}, |
|
|
|
boundaryGap: 10, |
|
|
|
data: ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'], |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 3, |
|
|
|
gridIndex: 1, |
|
|
|
axisLabel: { show: false }, |
|
|
|
axisLine: { show: false }, |
|
|
|
}, |
|
|
|
], |
|
|
|
yAxis: [ |
|
|
|
// 主y轴 |
|
|
@@ -91,7 +184,7 @@ |
|
|
|
axisLabel: { show: false }, |
|
|
|
axisTick: { show: false }, |
|
|
|
}, |
|
|
|
// 辅y轴 |
|
|
|
// 辅y轴 |
|
|
|
{ |
|
|
|
id: 1, |
|
|
|
gridIndex: 0, |
|
|
@@ -100,34 +193,79 @@ |
|
|
|
axisLabel: { show: false }, |
|
|
|
axisTick: { show: false }, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 2, |
|
|
|
gridIndex: 1, |
|
|
|
type: 'value', |
|
|
|
axisLine: {}, |
|
|
|
splitLine: { show: false }, |
|
|
|
name: '设备2', |
|
|
|
nameLocation: 'center', |
|
|
|
nameGap: 56, |
|
|
|
nameRotate: 0, |
|
|
|
nameTextStyle: { |
|
|
|
fontSize: 18, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ id: 3, gridIndex: 1 }, |
|
|
|
], |
|
|
|
series: [ |
|
|
|
{ |
|
|
|
name: '设备1', |
|
|
|
xAxisIndex: 0, |
|
|
|
yAxisIndex: 0, |
|
|
|
data: [1, 2, 3, 4, 5], |
|
|
|
type: 'line', |
|
|
|
}, |
|
|
|
{ |
|
|
|
xAxisIndex: 2, |
|
|
|
yAxisIndex: 2, |
|
|
|
data: [1, 2, 3, 4, 5], |
|
|
|
type: 'line', |
|
|
|
type: 'custom', |
|
|
|
renderItem: renderItem, |
|
|
|
itemStyle: { |
|
|
|
opacity: 0.8, |
|
|
|
}, |
|
|
|
encode: { |
|
|
|
x: [1, 2], |
|
|
|
y: 0, |
|
|
|
}, |
|
|
|
//function getTimestamp(point) { |
|
|
|
// const t = new Date(); |
|
|
|
// const [y,m,d] = [t.getFullYear(),t.getMonth(),t.getDate()] |
|
|
|
// const [h,M] = point.split(':') |
|
|
|
// return new Date(y,m,d,h,M,0,0).getTime() |
|
|
|
//} |
|
|
|
data: [ |
|
|
|
{ |
|
|
|
// 01:00 ~ 05:00 |
|
|
|
name: '运行', |
|
|
|
value: [0, 1695747600000, 1695762000000, 0], |
|
|
|
itemStyle: { |
|
|
|
normal: { |
|
|
|
color: types[0].color, |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
// 5:00 ~ 8:00 |
|
|
|
name: '故障', |
|
|
|
value: [0, 1695762000000, 1695772800000, 0], |
|
|
|
itemStyle: { |
|
|
|
normal: { |
|
|
|
color: types[1].color, |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
// 8:00 ~ 8:39 |
|
|
|
name: '计划停机', |
|
|
|
value: [0, 1695772800000, 1695775140000, 0], |
|
|
|
itemStyle: { |
|
|
|
normal: { |
|
|
|
color: types[2].color, |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
// 08:39 ~ 18:00 |
|
|
|
name: '运行', |
|
|
|
value: [0, 1695775140000, 1695808800000, 0], |
|
|
|
itemStyle: { |
|
|
|
normal: { |
|
|
|
color: types[0].color, |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
// 18:00 ~ 23:30 |
|
|
|
name: '计划停机', |
|
|
|
value: [0, 1695808800000, 1695828600000, 0], |
|
|
|
itemStyle: { |
|
|
|
normal: { |
|
|
|
color: types[2].color, |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
], |
|
|
|
}, |
|
|
|
], |
|
|
|
}; |
|
|
|