This commit is contained in:
hzz 2025-04-14 17:10:30 +08:00
parent ce827a360c
commit bd8271dea7
11 changed files with 1017 additions and 8 deletions

View File

@ -471,6 +471,7 @@ export default {
"工业物联网监控平台": "Industrial Internet of Things Monitoring Platform", "工业物联网监控平台": "Industrial Internet of Things Monitoring Platform",
"今日":"Tody", "今日":"Tody",
"本周": "The Week", "本周": "The Week",
"本月": "The Month" "本月": "The Month",
"故障": "Fault",
} }
} }

View File

@ -466,6 +466,7 @@ export default {
"工业物联网监控平台": "工业物联网监控平台", "工业物联网监控平台": "工业物联网监控平台",
"今日":"今日", "今日":"今日",
"本周":"本周", "本周":"本周",
"本月":"本月" "本月":"本月",
'故障':'故障',
} }
} }

View File

@ -42,7 +42,7 @@ import {
CanvasRenderer CanvasRenderer
} from 'echarts/renderers' } from 'echarts/renderers'
import { import {
PieChart,LineChart,BarChart PieChart,LineChart,BarChart,GaugeChart
} from 'echarts/charts' } from 'echarts/charts'
import { import {
TitleComponent, TitleComponent,
@ -58,7 +58,8 @@ use([
GridComponent, GridComponent,
PieChart, PieChart,
LineChart, LineChart,
BarChart BarChart,
GaugeChart
]); ]);

View File

@ -1,10 +1,18 @@
<template> <template>
<div class="container"> <div class="container">
asasdasda asasdasda + {{ query }}
</div> </div>
</template> </template>
<script setup> <script setup>
import { watch } from 'vue';
import { useRoute } from 'vue-router';
const route = useRoute()
let query = ref(route.query.timeFrame)
watch(() => route.query.timeFrame, (newValue, oldValue) => {
query.value=newValue
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -0,0 +1,101 @@
<template>
<div class="table-container">
<div class="title">{{ props.title }}</div>
<div class="content">
<el-table v-bind="$attrs" :data="tableData" header-row-class-name="table_header" :border="border" :stripe="stripe"
style="width: 100%;height: 100%;"
@selection-change="handleSelectionChange">
<template v-for="item in columns" :key="item.prop">
<!-- 选择列 -->
<el-table-column v-if="item.type === 'selection'" type="selection" width="55" />
<!-- 序号列 -->
<el-table-column v-else-if="item.type === 'index'" type="index" :width="item.width || '80'"
:label="item.label || tLang('common', '序号')" />
<!-- 普通列 -->
<el-table-column v-else :prop="item.prop" :label="item.label" :width="item.width"
:min-width="item.minWidth" :align="item.align || 'center'">
<!-- 自定义列内容 -->
<template #default="scope" v-if="item.slot">
<slot :name="item.slot" :row="scope.row"></slot>
</template>
</el-table-column>
</template>
</el-table>
</div>
</div>
</template>
<script setup>
const props = defineProps({
title: {
type: String,
default: ''
},
columns: {
type: Array,
required: true
},
tableData: {
type: Array,
required: true
},
border: {
type: Boolean,
default: false
},
stripe: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['selection-change'])
const handleSelectionChange = (val) => {
emit('selection-change', val)
}
</script>
<style lang="scss" scoped>
::v-deep(.el-table) {
--el-table-border-color: transparent;
--el-table-border: none;
--el-table-text-color: #bdbdbe;
--el-table-header-text-color: #bdbdbe;
--el-table-row-hover-bg-color: transparent;
--el-table-current-row-bg-color: transparent;
--el-table-header-bg-color: transparent;
--el-table-bg-color: transparent;
--el-table-tr-bg-color: transparent;
--el-table-expanded-cell-bg-color: transparent;
}
::v-deep(.table_header th) {
background-color: transparent !important;
color: #fff;
text-align: center;
}
.title {
width: 100%;
height: 20px;
line-height: 20px;
font-size: 14px;
color: #cfcfcf;
}
.content {
width: 100%;
height: calc(100% - 20px);
display: flex;
justify-content: center;
align-items: center;
}
.table-container {
width: 100%;
height: 100%;
}
</style>

View File

@ -0,0 +1,204 @@
<template>
<div class="lc-container box-bg-color">
<div class="title">{{ tLang('message', '异常停机分类统计') }}</div>
<div class="content">
<div class="left-panel">
<v-chart :option="options" theme="dark" style="width: 100%;height: 100%;" />
</div>
<div class="right-panel">
<div class="right-title">
<span class="text1">{{ tLang('message','实时报警') }}<el-badge :show-zero="false" :value="1" class="item"><el-icon :size="20"><BellFilled /></el-icon></el-badge></span>
<span class="text2">{{ tLang('message','全部清除') }}</span>
</div>
<div class="right-content">
<div class="card-item">
<div class="message-mine">
<div class="message-title">主轴旋转异常请检查机械部件</div>
<div class="message-desc">
<span>{{ tLang('message', '设备ID') }}: </span>
<span>SWM5015</span>
<span>2025-04-16 13:20:18</span>
</div>
</div>
<div class="option">
<el-button color="#DC2626" size="small">{{ tLang('message','处理') }}</el-button>
<el-button color="#e7e7e7" size="small">{{ tLang('message','忽略') }}</el-button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
const { proxy } = getCurrentInstance();
let options = computed(() => {
return {
tooltip: {
trigger: 'item'
},
legend: {
top: '5%',
left: 'center'
},
backgroundColor: 'transparent',
series: [
{
name: '',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
padAngle: 5,
itemStyle: {
borderRadius: 10
},
label: {
show: false,
position: 'center'
},
// emphasis: {
// label: {
// show: true,
// fontSize: 40,
// fontWeight: 'bold'
// }
// },
labelLine: {
show: false
},
data: [
{ value: 1048, name: proxy.tLang('home', '维修') },
{ value: 735, name: proxy.tLang('pms', '保养') },
{ value: 580, name: proxy.tLang('message', '故障') },
]
}
]
}
})
</script>
<style lang="scss" scoped>
.box-bg-color {
background-color: #192124;
border-radius: 5px;
padding: 5px;
box-sizing: border-box;
overflow: hidden;
}
.title {
width: 100%;
height: 20px;
line-height: 20px;
font-size: 14px;
color: #cfcfcf;
}
.content {
width: 100%;
height: calc(100% - 20px);
display: flex;
justify-content: center;
align-items: center;
}
.lc-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
.content {
.left-panel {
width: 50%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.right-panel {
width: 50%;
height: 100%;
.right-title {
width: 100%;
height: 40px;
display: flex;
justify-content: space-between;
align-items: center;
span {
font-size: 14px;
color: #fff;
margin: 0 20px;
}
.text1 {
font-size: 18px;
display: flex;
justify-content: flex-start;
align-items: center;
}
.text2 {
font-size: 12px;
color: #cfcfcf;
margin-right: 25px;
cursor: pointer;
}
}
.right-content {
width: 100%;
height: calc(100% - 40px);
display: flex;
flex-direction: column;
justify-content: flex-start;
overflow: auto;
.card-item {
width: 95%;
height: 50px;
box-sizing: border-box;
border-left: #DC2626 4px solid;
background-color: #2D2023;
display: flex;
justify-content: space-between;
align-items: center;
.message-mine {
width: 60%;
height: 100%;
padding-left: 20px;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: flex-start;
.message-title {
font-size: 14px;
color: #fff;
}
.message-desc {
font-size: 10px;
color: #d5d5d5;
span {
margin-right: 15px;
}
}
}
.option {
width: 40%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,385 @@
<template>
<div class="lc-container">
<div class="left-panel box-bg-color">
<div class="title">{{ tLang('message', 'OEE综合设备效率') }}</div>
<div class="content">
<div class="oee-chart">
<v-chart :option="oeeOption" theme="dark" style="width: 100%;height: 100%;" />
</div>
<div class="progress">
<div class="progress-item">
<div class="progress-title">
<span>{{ tLang('message', '可用率') }}</span>
<span class="progress-value">{{ 70 }}%</span>
</div>
<div class="progress-bar">
<el-progress :percentage="70" status="warning" :stroke-width="16" :show-text="false" />
</div>
<div class="progress-desc">
<span>计划停机{{ '45分钟' }}</span>
<span>故障停机{{ '1小时' }}</span>
</div>
</div>
<div class="progress-item">
<div class="progress-title">
<span>{{ tLang('message', '性能率') }}</span>
<span class="progress-value">{{ 70 }}%</span>
</div>
<div class="progress-bar">
<el-progress :percentage="70" status="success" :stroke-width="16" :show-text="false" />
</div>
<div class="progress-desc">
<span>计划停机{{ '45分钟' }}</span>
<span>故障停机{{ '1小时' }}</span>
</div>
</div>
</div>
</div>
</div>
<div class="right-panel box-bg-color">
<div class="right-title">
<span class="text1">{{ tLang('message', '实时报警') }}<el-badge :show-zero="false" :value="1"
class="item"><el-icon :size="20">
<BellFilled />
</el-icon></el-badge></span>
<span class="text2">{{ tLang('message', '全部清除') }}</span>
</div>
<div class="right-content">
<div class="card-item">
<div class="message-mine">
<div class="message-title">主轴旋转异常请检查机械部件</div>
<div class="message-desc">
<span>{{ tLang('message', '设备ID') }}: </span>
<span>SWM5015</span>
<span>2025-04-16 13:20:18</span>
</div>
</div>
<div class="option">
<el-button color="#DC2626" size="small">{{ tLang('message', '处理') }}</el-button>
<el-button color="#e7e7e7" size="small">{{ tLang('message', '忽略') }}</el-button>
</div>
</div>
<div class="error-chart">
<v-chart :option="options" theme="dark" style="width: 100%;height: 100%;" />
</div>
</div>
</div>
</div>
</template>
<script setup>
const { proxy } = getCurrentInstance();
let options = computed(() => {
return {
title: {
text: proxy.tLang('message', '异常停机分类统计'),
textStyle: {
fontSize: 12,
}
},
tooltip: {
trigger: 'item'
},
legend: {
top: '15%',
orient: 'vertical',
left: 'left'
},
backgroundColor: 'transparent',
series: [
{
name: '',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
padAngle: 5,
itemStyle: {
borderRadius: 10
},
label: {
show: false,
position: 'center'
},
// emphasis: {
// label: {
// show: true,
// fontSize: 40,
// fontWeight: 'bold'
// }
// },
labelLine: {
show: false
},
data: [
{ value: 1048, name: proxy.tLang('home', '维修') },
{ value: 735, name: proxy.tLang('pms', '保养') },
{ value: 580, name: proxy.tLang('message', '故障') },
]
}
]
}
})
let oeeOption = computed(() => {
return {
backgroundColor: 'transparent',
series: [
{
type: 'gauge',
startAngle: 180,
endAngle: 0,
center: ['50%', '75%'],
radius: '90%',
min: 0,
max: 1,
axisLine: {
lineStyle: {
width: 2,
color: [
[0.25, '#FF6E76'],
[0.5, '#FDDD60'],
[0.75, '#58D9F9'],
[1, '#7CFFB2']
]
}
},
pointer: {
icon: 'path://M12.8,0.7l12,40.1H0.7L12.8,0.7z',
length: '12%',
width: 10,
offsetCenter: [0, '-60%'],
itemStyle: {
color: 'auto'
}
},
axisTick: {
length: 5,
distance: 3,
lineStyle: {
color: 'auto',
width: 1
}
},
splitLine: {
length: 10,
distance: 3,
},
axisLabel: {
color: '#f7f7f7',
distance: 3,
fontSize: 12,
formatter: function (value) {
return value * 100;
}
},
title: {
offsetCenter: [0, '-10%'],
fontSize: 12
},
detail: {
fontSize: 14,
offsetCenter: [0, '-35%'],
valueAnimation: true,
formatter: function (value) {
return Math.round(value * 100) + '%';
},
color: 'inherit'
},
data: [
{
value: 0.7,
name: 'OEE'
}
]
}
]
}
})
</script>
<style lang="scss" scoped>
.box-bg-color {
background-color: #192124;
border-radius: 5px;
padding: 5px;
box-sizing: border-box;
overflow: hidden;
}
.title {
width: 100%;
height: 20px;
line-height: 20px;
font-size: 14px;
color: #cfcfcf;
}
.content {
width: 100%;
height: calc(100% - 20px);
display: flex;
justify-content: center;
align-items: center;
}
.lc-container {
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
.left-panel {
width: 49%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.oee-chart {
width: 50%;
height: 100%;
}
.progress {
width: 50%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.progress-item {
height: 80px;
width: 100%;
padding: 5px;
box-sizing: border-box;
background-color: #1F2937;
border-radius: 5px;
margin: 10px 0;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: flex-start;
.progress-title {
font-size: 14px;
color: #999898;
}
.progress-bar {
width: 100%;
}
.progress-desc {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 10px;
color: #999898;
}
}
}
}
.right-panel {
width: 49%;
height: 100%;
.right-title {
width: 100%;
height: 40px;
display: flex;
justify-content: space-between;
align-items: center;
span {
font-size: 14px;
color: #fff;
margin: 0 20px;
}
.text1 {
font-size: 18px;
display: flex;
justify-content: flex-start;
align-items: center;
}
.text2 {
font-size: 12px;
color: #cfcfcf;
margin-right: 25px;
cursor: pointer;
}
}
.right-content {
width: 100%;
height: calc(100% - 40px);
display: flex;
flex-direction: column;
justify-content: space-between;
overflow: hidden;
.card-item {
width: 100%;
height: 50px;
box-sizing: border-box;
border-left: #DC2626 4px solid;
background-color: #2D2023;
display: flex;
justify-content: space-between;
align-items: center;
.message-mine {
width: 60%;
height: 100%;
padding-left: 20px;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: flex-start;
.message-title {
font-size: 14px;
color: #fff;
}
.message-desc {
font-size: 10px;
color: #999898;
span {
margin-right: 15px;
}
}
}
.option {
width: 40%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
.error-chart {
width: 100%;
height: calc(100% - 50px);
}
}
}
}
</style>

View File

@ -0,0 +1,142 @@
<template>
<div class="lt-container">
<div class="left">
<div class="left-content">
<div class="speed-box">
<div class="speed-value">250rpm</div>
</div>
<div class="speed-title">{{ tLang('message', '扫描速度') }}</div>
</div>
</div>
<div class="right">
<div class="right-item" v-for="item of devData">
<div class="title">{{ item['label'] }}</div>
<div class="content" v-if="item['type'] == 'status'">
<div class="status-box" :style="{ background: statusList[item.value]['color'] }"></div>
<div class="status-title">{{ statusList[item.value]['label'] }}</div>
</div>
<div class="content" v-else>
{{ item['value'] }}
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue';
const { proxy } = getCurrentInstance();
let devData = reactive({
status: { 'label': proxy.tLang('home', '设备状态'), 'value': '1', type: 'status' },
scansNum: { 'label': proxy.tLang('message', '扫描次数'), 'value': '22', type: '' },
runTime: { 'label': proxy.tLang('message', '运行时长'), 'value': '00:34:22', type: '' },
consumption: { 'label': proxy.tLang('message', '耗电量'), 'value': '22 kW·h', type: '' },
identifyState: { 'label': proxy.tLang('message', '识别状态'), 'value': '1', type: 'status' },
identifyNum: { 'label': proxy.tLang('message', '识别次数'), 'value': '22', type: '' },
identifyTime: { 'label': proxy.tLang('message', '总识别时长'), 'value': '00:34:22', type: '' },
ErrorNum: { 'label': proxy.tLang('message', '异常次数'), 'value': '22', type: '' },
})
let statusList = {
'0': { 'label': proxy.tLang('message', '停机中'), 'value': '1', 'color': '#f6f4f4' },
'1': { 'label': proxy.tLang('message', '待机中'), 'value': '1', 'color': '#fddd60' },
'2': { 'label': proxy.tLang('message', '运行中'), 'value': '1', 'color': '#7cffb2' },
'3': { 'label': proxy.tLang('message', '待机中'), 'value': '1', 'color': '#fddd60' },
'4': { 'label': proxy.tLang('message', '故障中'), 'value': '1', 'color': '#ff6e76' },
}
</script>
<style lang="scss" scoped>
.title {
width: 100%;
height: 20px;
line-height: 20px;
font-size: 14px;
color: #cfcfcf;
}
.content {
width: 100%;
height: calc(100% - 20px);
display: flex;
justify-content: center;
align-items: center;
}
.lt-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
.left {
width: 25%;
height: 100%;
.left-content {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.speed-box {
width: 120px;
height: 120px;
background: url('./../image/u65.png') no-repeat;
background-size: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 10px;
}
}
}
.right {
width: 75%;
height: 100%;
display: flex;
justify-content: space-around;
align-items: center;
flex-wrap: wrap;
.right-item {
width: 155px;
height: 74px;
padding: 5px;
box-sizing: border-box;
background: #1F2937;
.content {
display: flex;
justify-content: space-around;
align-items: center;
flex-direction: column;
.status-box {
width: 20px;
height: 20px;
border-radius: 50%;
margin-bottom: 5px;
}
.status-title {
font-size: 10px;
color: #e7e7e7;
}
}
}
}
}
</style>

View File

@ -0,0 +1,138 @@
<template>
<div class="lt-container">
<div class="left">
<div class="left-content">
<div class="speed-box">
<div class="speed-value">250rpm</div>
</div>
<div class="speed-title">{{ tLang('message', '设备转速') }}</div>
</div>
</div>
<div class="right">
<div class="right-item" v-for="item of devData">
<div class="title">{{ item['label'] }}</div>
<div class="content" v-if="item['type'] == 'status'">
<div class="status-box" :style="{ background: statusList[item.value]['color'] }"></div>
<div class="status-title">{{ statusList[item.value]['label'] }}</div>
</div>
<div class="content" v-else>
{{ item['value'] }}
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue';
const { proxy } = getCurrentInstance();
let devData = reactive({
status: { 'label': proxy.tLang('home', '设备状态'), 'value': '1', type: 'status' },
runTime: { 'label': proxy.tLang('message', '运行时长'), 'value': '00:34:22', type: '' },
prod: { 'label': proxy.tLang('message', '总产量'), 'value': '22', type: '' },
})
let statusList = {
'0': { 'label': proxy.tLang('message', '停机中'), 'value': '1', 'color': '#f6f4f4' },
'1': { 'label': proxy.tLang('message', '待机中'), 'value': '1', 'color': '#fddd60' },
'2': { 'label': proxy.tLang('message', '运行中'), 'value': '1', 'color': '#7cffb2' },
'3': { 'label': proxy.tLang('message', '待机中'), 'value': '1', 'color': '#fddd60' },
'4': { 'label': proxy.tLang('message', '故障中'), 'value': '1', 'color': '#ff6e76' },
}
</script>
<style lang="scss" scoped>
.title {
width: 100%;
height: 20px;
line-height: 20px;
font-size: 14px;
color: #cfcfcf;
}
.content {
width: 100%;
height: calc(100% - 20px);
display: flex;
justify-content: center;
align-items: center;
}
.lt-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
.left {
width: 25%;
height: 100%;
.left-content {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.speed-box {
width: 120px;
height: 120px;
background: url('./../image/u65.png') no-repeat;
background-size: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 10px;
}
}
}
.right {
width: 75%;
height: 100%;
display: flex;
justify-content: space-around;
align-items: center;
flex-wrap: wrap;
.right-item {
width: 200px;
height: 120px;
padding: 15px;
border-radius: 5px;
box-sizing: border-box;
background: #1F2937;
.content {
display: flex;
justify-content: space-around;
align-items: center;
flex-direction: column;
.status-box {
width: 30px;
height: 30px;
border-radius: 50%;
margin-bottom: 5px;
}
.status-title {
font-size: 12px;
color: #e7e7e7;
}
}
}
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -2,10 +2,17 @@
<div class="container"> <div class="container">
<div class="left"> <div class="left">
<div class="lt box-bg-color"> <div class="lt box-bg-color">
<Ltop1></Ltop1> <!-- <Ltop1></Ltop1> -->
<!-- <Ltop2></Ltop2> -->
<Ltop3></Ltop3>
</div>
<div class="lc">
<!-- <Lcenter1></Lcenter1> -->
<Lcenter2></Lcenter2>
</div>
<div class="lb box-bg-color">
<bottomTable title="检测结果" :columns="columns" :table-data="tableData"></bottomTable>
</div> </div>
<div class="lc box-bg-color"></div>
<div class="lb box-bg-color"></div>
</div> </div>
<div class="right"> <div class="right">
<div class="rt box-bg-color"></div> <div class="rt box-bg-color"></div>
@ -17,6 +24,27 @@
<script setup> <script setup>
import Ltop1 from './components/ltop1.vue' import Ltop1 from './components/ltop1.vue'
import Ltop2 from './components/ltop2.vue'
import Ltop3 from './components/ltop3.vue'
import Lcenter1 from './components/lcenter1.vue'
import Lcenter2 from './components/lcenter2.vue'
import bottomTable from './components/bottomTable.vue'
const columns = [
// { type: 'selection' },
// { type: 'index', label: '' },
{ prop: 'code', label: '产品编码' },
{ prop: 'status', label: '检查结果', slot: 'status' },
{ prop: 'offset', label: '偏差值' },
{ prop: 'date', label: '检测时间' },
{ prop: 'num', label: '检测数量' },
]
let tableData = ref([
{ code: '123456789', status: '正常', offset: '0.00', date: '2021-01-01', num: '100' },
{ code: '123456789', status: '正常', offset: '0.00', date: '2021-01-01', num: '100' }
])
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>