添加看板
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 197 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 499 B |
|
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div ref="chartRef" class="chart-container"></div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
const chartRef = ref(null);
|
||||
let chart = null;
|
||||
|
||||
const setOption = (option) => {
|
||||
if (!chart) return;
|
||||
chart.setOption(option);
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
if (!chartRef.value) return;
|
||||
|
||||
const { width, height } = chartRef.value.getBoundingClientRect();
|
||||
if (width === 0 || height === 0) return;
|
||||
|
||||
if (!chart) {
|
||||
chart = echarts.init(chartRef.value, null, { renderer: 'canvas' });
|
||||
}
|
||||
|
||||
if (optionCache.value) {
|
||||
chart.setOption(optionCache.value, true);
|
||||
}
|
||||
};
|
||||
|
||||
const optionCache = ref(null);
|
||||
|
||||
const setData = (opt) => {
|
||||
optionCache.value = opt;
|
||||
init();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
init();
|
||||
});
|
||||
|
||||
// 监听大小变化
|
||||
const ro = new ResizeObserver(() => {
|
||||
if (chart) chart.resize();
|
||||
});
|
||||
ro.observe(chartRef.value);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (chart) chart.dispose();
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
setData
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.chart-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<div class="deviceList">
|
||||
<div class="deviceItem" v-for="d in devices" :key="d.id">
|
||||
<div class="line"></div>
|
||||
<div class="title">
|
||||
{{ d.monitorCode }}
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="name">
|
||||
{{ d.monitorName }}
|
||||
</div>
|
||||
<div class="list" v-for="i in d.data">
|
||||
<div class="value">{{ i.value }}</div>
|
||||
<div class="units">{{ i.units }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DeviceList',
|
||||
props: ['devices'],
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.deviceList {
|
||||
display: flex;
|
||||
flex-direction: row; /* 横向排列设备 */
|
||||
gap: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
.line {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 100%;
|
||||
transform: translate(100%, -50%);
|
||||
height: 1px;
|
||||
width: 20px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.deviceItem {
|
||||
padding: 6px 20px;
|
||||
color: #fff;
|
||||
border-radius: 6px;
|
||||
white-space: nowrap;
|
||||
min-width: 100px;
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
border: 1px solid #fff;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border: 1px solid #fff;
|
||||
|
||||
.name {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #fff;
|
||||
}
|
||||
|
||||
.list {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
white-space: nowrap;
|
||||
|
||||
.value {
|
||||
display: inline-block;
|
||||
min-width: 100px;
|
||||
margin-right: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.units {
|
||||
display: inline-block;
|
||||
min-width: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,293 @@
|
||||
<template>
|
||||
<div class="content">
|
||||
<div class="bg"></div>
|
||||
<div class="title">RFID中间件监控平台</div>
|
||||
<div class="topTitle" style="left: 13%">设备数量:</div>
|
||||
<div class="topTitle" style="left: 37.5%">在线数量:</div>
|
||||
<div class="topTitle" style="left: 62%">离线数量:</div>
|
||||
<div class="topTitle" style="left: 86.5%">告警数量:</div>
|
||||
<div class="topNum" style="left: 17%; color: #127feb">66</div>
|
||||
<div class="topNum" style="left: 41.5%; color: #49e1f5">66</div>
|
||||
<div class="topNum" style="left: 66%; color: #d8ee30">66</div>
|
||||
<div class="topNum" style="left: 90.5%; color: #901f43">66</div>
|
||||
<div class="successRate">
|
||||
<Chart ref="successRateRef"></Chart>
|
||||
</div>
|
||||
<div class="scrollTable">
|
||||
<div class="th" :style="{ backgroundImage: `url(${thbg})` }">
|
||||
<div class="td" style="width: 25%">时间</div>
|
||||
<div class="td" style="width: 15%">设备名称</div>
|
||||
<div class="td" style="width: 30%">位置</div>
|
||||
<div class="td" style="width: 10%">等级</div>
|
||||
<div class="td" style="width: 20%">告警行为</div>
|
||||
</div>
|
||||
<vue3ScrollSeamless
|
||||
:limitMoveNum="1"
|
||||
:step="1"
|
||||
:hover="true"
|
||||
:dataList="tableData"
|
||||
style="overflow: hidden; height: calc(100% - 3.5vw); margin-top: 0.2vw"
|
||||
>
|
||||
<div
|
||||
v-for="(item, index) in tableData"
|
||||
:key="index"
|
||||
class="tr"
|
||||
style="margin-top: 8px; line-height: 2.4vw"
|
||||
:style="{ backgroundImage: `url(${trbg})` }"
|
||||
>
|
||||
<div class="td" style="width: 25%; line-height: 2.4vw">{{ item.time }}</div>
|
||||
<div class="td" style="width: 15%; line-height: 2vw">{{ item.name }}</div>
|
||||
<div class="td" style="width: 30%; line-height: 2vw; font-size: 0.6vw">{{ item.lo }}</div>
|
||||
<div class="td" style="width: 10%; line-height: 2vw">{{ item.level }}</div>
|
||||
<div class="td" style="width: 20%; line-height: 2vw">{{ item.item1 }}</div>
|
||||
</div>
|
||||
</vue3ScrollSeamless>
|
||||
</div>
|
||||
<div class="center">
|
||||
<ListItem :isRoot="false" v-for="i in centerData" :key="i.name" :itemData="i" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import Chart from '@/components/Chart/chart.vue';
|
||||
import thbg from '@/assets/chart/thbg.png';
|
||||
import trbg from '@/assets/chart/trbg.png';
|
||||
import { vue3ScrollSeamless } from 'vue3-scroll-seamless';
|
||||
import ListItem from './listItem.vue';
|
||||
|
||||
const successRateRef = ref(null);
|
||||
const tableData = ref([
|
||||
{
|
||||
time: '2016-06-05',
|
||||
name: '带束层2',
|
||||
lo: '半钢成型A4机台',
|
||||
level: '次要',
|
||||
item1: '设备离线'
|
||||
},
|
||||
{
|
||||
time: '2016-06-05',
|
||||
name: '带束层2',
|
||||
lo: '半钢成型A4机台',
|
||||
level: '次要',
|
||||
item1: '设备离线'
|
||||
},
|
||||
{
|
||||
time: '2016-06-05',
|
||||
name: '带束层2',
|
||||
lo: '半钢成型A4机台',
|
||||
level: '次要',
|
||||
item1: '设备离线'
|
||||
},
|
||||
{
|
||||
time: '2016-06-05',
|
||||
name: '带束层2',
|
||||
lo: '半钢成型A4机台',
|
||||
level: '次要',
|
||||
item1: '设备离线'
|
||||
},
|
||||
{
|
||||
time: '2016-06-05',
|
||||
name: '带束层2',
|
||||
lo: '半钢成型A4机台',
|
||||
level: '次要',
|
||||
item1: '设备离线'
|
||||
},
|
||||
{
|
||||
time: '2016-06-05',
|
||||
name: '带束层2',
|
||||
lo: '半钢成型A4机台',
|
||||
level: '次要',
|
||||
item1: '设备离线'
|
||||
}
|
||||
]);
|
||||
const centerData = ref({
|
||||
isAmmeter: '1',
|
||||
monitorCode: '111',
|
||||
monitorName: '123',
|
||||
deviceData: [
|
||||
{
|
||||
value: '11',
|
||||
units: 'kg'
|
||||
}
|
||||
],
|
||||
children: [
|
||||
{
|
||||
isAmmeter: '1',
|
||||
monitorCode: '111',
|
||||
monitorName: '123',
|
||||
deviceData: [
|
||||
{
|
||||
value: '11',
|
||||
units: 'kg'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
onMounted(() => {
|
||||
successRateRef.value.setData({
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
backgroundColor: 'rgba(0,0,0,.6)',
|
||||
borderWidth: 0,
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
top: '',
|
||||
icon: 'path://M512.798285 0.399142C230.604561 0.399142 1.895927 229.107776 1.895927 511.301501s228.708634 510.902358 510.902358 510.902358 510.902358-228.708634 510.902358-510.902358S794.992009 0.399142 512.798285 0.399142z m0 878.712142C309.634769 879.111284 144.988501 714.465017 144.988501 511.301501S309.634769 143.491717 512.798285 143.491717s367.809784 164.646268 367.809784 367.809784-164.646268 367.809784-367.809784 367.809783z',
|
||||
itemWidth: 10,
|
||||
itemHeight: 10,
|
||||
itemGap: 10,
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 8
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: ['1/1', '1/2', '1/3', '1/4', '1/5', '1/6', '1/7', '1/8', '1/9', '1/10', '1/11', '1/12', '1/13', '1/14', '1/15', '1/16', '1/17', '1/18']
|
||||
},
|
||||
grid: {
|
||||
top: 30,
|
||||
left: 30,
|
||||
right: 30,
|
||||
bottom: 30
|
||||
},
|
||||
yAxis: {
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '需求数量',
|
||||
data: [9, 8, 6.5, 7.2, 6.7, 7.4, 8.2, 9, 8, 6.5, 7.2, 6.7, 7.4, 8.2, 9, 8, 6.5, 5],
|
||||
type: 'line',
|
||||
symbol: 'circle',
|
||||
symbolSize: 5,
|
||||
itemStyle: {
|
||||
color: '#368CDC'
|
||||
},
|
||||
lineStyle: {
|
||||
color: '#368CDC'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '缺陷数量',
|
||||
data: [3, 9, 4, 3, 11, 8, 10, 3, 9, 4, 3, 11, 8, 10, 3, 9, 4, 3],
|
||||
type: 'line',
|
||||
symbol: 'circle',
|
||||
symbolSize: 5,
|
||||
itemStyle: {
|
||||
color: '#39FFF4'
|
||||
},
|
||||
lineStyle: {
|
||||
color: '#39FFF4'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: 'Source Han Sans', 'Noto Sans CJK SC', '思源黑体', sans-serif;
|
||||
|
||||
.bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url('@/assets/chart/bg.jpg');
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.title {
|
||||
position: absolute;
|
||||
top: 2vw;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-size: 2.1vw;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.2vw;
|
||||
color: #7ae7f8;
|
||||
background: linear-gradient(to bottom, #ffffff 0%, #7ae7f8 100%);
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.topTitle {
|
||||
position: absolute;
|
||||
top: 16.7%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: #eee;
|
||||
font-size: 1.4vw;
|
||||
letter-spacing: 0.2vw;
|
||||
}
|
||||
|
||||
.topNum {
|
||||
position: absolute;
|
||||
top: 16.7%;
|
||||
transform: translateY(-50%);
|
||||
color: #eee;
|
||||
font-size: 1.5vw;
|
||||
letter-spacing: 0.2vw;
|
||||
}
|
||||
|
||||
.successRate {
|
||||
position: absolute;
|
||||
top: 30.7%;
|
||||
left: 75.6%;
|
||||
width: 20.6%;
|
||||
height: 28.5%;
|
||||
}
|
||||
|
||||
.scrollTable {
|
||||
position: absolute;
|
||||
top: 64.7%;
|
||||
left: 75.6%;
|
||||
width: 20.6%;
|
||||
height: 28.5%;
|
||||
}
|
||||
|
||||
.th {
|
||||
height: 3.3vw;
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
font-size: 1vw;
|
||||
}
|
||||
|
||||
.tr {
|
||||
height: 2.4vw;
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
font-size: 0.8vw;
|
||||
}
|
||||
|
||||
.td {
|
||||
display: inline-block;
|
||||
line-height: 3.3vw;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.center {
|
||||
position: absolute;
|
||||
top: 24.5%;
|
||||
left: 19.6%;
|
||||
width: 53%;
|
||||
height: 69%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||