Commit 9d0fe1d7 by nningxx

tht合并到master

parents a7dce4c0 3d3bbfe2
# -*- coding: utf-8 -*-
from odoo import http, fields
from odoo import http, fields,SUPERUSER_ID
from odoo.http import request
from odoo.addons.roke_mes_three_colour_light.controller.main import RokeMesThreeColourLight
import os
import math
from datetime import datetime, time
from datetime import datetime, time, timedelta
from jinja2 import Environment, FileSystemLoader
import logging
import requests
......@@ -164,3 +164,46 @@ class ResMesBigScreen(http.Controller):
def get_lishibaozhuang_data(self):
body = http.request.jsonrequest
return self.common_dws_interface(body, '/get_real_time_device_data', cate="制袋包装机")
@http.route('/roke/tht/get_abnormal_alarm_list', type='json', auth="none", methods=['POST', 'OPTIONS'], csrf=False, cors='*')
def get_abnormal_alarm_list(self):
"""
获取异常表单列表
:return:
"""
jsonrequest = http.request.jsonrequest
domain = []
abnormal_alarm_id = jsonrequest.get('abnormal_alarm_id', False)
#表单id
if abnormal_alarm_id:
domain.append(('id', '=', abnormal_alarm_id))
abnormal_id = jsonrequest.get('abnormal_id', False)
#异常类型id
if abnormal_id:
domain.append(('abnormal_id', '=', abnormal_id))
page_size = int(http.request.jsonrequest.get('page_size', 20))
page_no = int(http.request.jsonrequest.get('page_no', 1))
abnormal_alarm_ids = http.request.env(user=SUPERUSER_ID)['roke.abnormal.alarm'].search(domain, limit=page_size, offset=(page_no - 1) * page_size, order="originating_time desc")
abnormal_alarm_list = []
for item in abnormal_alarm_ids:
note = ''
if item.abnormal_id.name == '设备异常':
note = f"{item.equipment_id.name or ''}发生了故障"
elif item.abnormal_id.name == '缺料断料':
note = f"{item.sponsor.name or item.create_uid.name or ''} 发起了缺料申请"
abnormal_alarm_list.append({
"id": item.id, # 异常表单id
"abnormal_name": item.abnormal_id.name, # 异常类型
"originating_time": (item.originating_time + timedelta(hours=8)).strftime("%Y-%m-%d %H:%M:%S") if item.originating_time else '', #发起时间
"note": note, #报警表述
})
total = http.request.env(user=SUPERUSER_ID)['roke.abnormal.alarm'].search_count(domain)
return {
"state": "success",
"msgs": "获取成功",
"total": total,
"abnormal_alarm_list": abnormal_alarm_list
}
......@@ -369,7 +369,7 @@
config = {},
errorMessage = "操作失败,请稍后重试",
contentType = "application/json",
baseurl="https://tht.dws.rokecloud.com"
baseurl=""
) {
return new Promise((resolve, reject) => {
if (!url) reject(null)
......
......@@ -2,10 +2,10 @@
<html lang="zh-CN">
<head>
<meta charset="UTF-8"/>
<meta charset="UTF-8" />
<title>预料工序</title>
<meta content="width=device-width,initial-scale=1.0, maximum-scale=1.0,user-scalable=0" name="viewport"/>
<link rel="stylesheet" href="/tht_project/static/html/big_screen/element-ui/index.css"/>
<meta content="width=device-width,initial-scale=1.0, maximum-scale=1.0,user-scalable=0" name="viewport" />
<link rel="stylesheet" href="/tht_project/static/html/big_screen/element-ui/index.css" />
<script src="/tht_project/static/html/big_screen/js/echarts.min.js"></script>
<script src="/tht_project/static/html/big_screen/js/moment.min.js"></script>
<script src="/tht_project/static/html/big_screen/js/vue.js"></script>
......@@ -14,156 +14,156 @@
</head>
<body id="bodyId" style="display: none">
<div id="app" v-loading.body.fullscreen.lock="loading" ref="fullScreenElement">
<div class="pageHeaderBox">
<div class="weatherInfo">
<span class="location">预料工序</span>
</div>
<img class="logo" src="/tht_project/static/html/big_screen/image/logo.png">
<div class="title">天合堂数据指挥中心可视化大屏</div>
<div class="dateTimeBox">
<i style="font-size: 30px;margin-right: 10px;" @click="toggleFullscreen"
:class="isFullscreen ? 'el-icon-close' : 'el-icon-full-screen'"></i>
<div class="time">[[currentTime]]</div>
<div class="dateBox">
<span>[[ currentDate ]]</span>
<span>[[ currentWeek ]]</span>
<div id="app" v-loading.body.fullscreen.lock="loading" ref="fullScreenElement">
<div class="pageHeaderBox">
<div class="weatherInfo">
<span class="location">预料工序</span>
</div>
</div>
</div>
<div class="pageContentBox">
<div class="pageContentBackgroundBox">
<img class="badgeIcon" src="/tht_project/static/html/big_screen/image/777.png" alt="" v-for="item in 4"
:key="item">
</div>
<div class="pageContentArea">
<div class="contentColumnBox one">
<div class="itemCardBox">
<div class="cardHeader">
<span>今日产量</span>
</div>
<div class="cardContentBox">
<div id="proportionChart" style="width: 100%; height: 100%;"></div>
</div>
</div>
<div class="itemCardBox">
<div class="cardHeader">
<span>今日投料情况</span>
</div>
<div class="cardContentBox">
<div id="mainMaterialChart" style="width: 100%; height: 100%;"></div>
</div>
</div>
<div class="itemCardBox">
<div class="cardHeader">
<span>设备实时运转情况</span>
</div>
<div class="cardContentBox">
<div id="seasonMaterialChart" style="width: 100%; height: 100%;"></div>
</div>
</div>
<div class="itemCardBox">
<div class="cardHeader">
<span>设备资源利用率</span>
</div>
<div class="cardContentBox">
<div id="rawMaterialChart" style="width: 100%; height: 100%;"></div>
</div>
<img class="logo" src="/tht_project/static/html/big_screen/image/logo.png">
<div class="title">天合堂数据指挥中心可视化大屏</div>
<div class="dateTimeBox">
<i style="font-size: 30px;margin-right: 10px;" @click="toggleFullscreen"
:class="isFullscreen ? 'el-icon-close' : 'el-icon-full-screen'"></i>
<div class="time">[[currentTime]]</div>
<div class="dateBox">
<span>[[ currentDate ]]</span>
<span>[[ currentWeek ]]</span>
</div>
</div>
<div class="contentColumnBox two">
<div class="itemCardBox">
<div class="cardHeader">
<span>片冰机</span>
</div>
<div class="cardContentBox">
<div id="sliceIceMachineChart" style="width: 100%; height: 100%;"></div>
</div>
</div>
<div class="itemCardBox">
<div class="cardHeader">
<span>解冻机组</span>
</div>
<div class="pageContentBox">
<div class="pageContentBackgroundBox">
<img class="badgeIcon" src="/tht_project/static/html/big_screen/image/777.png" alt="" v-for="item in 4"
:key="item">
</div>
<div class="pageContentArea">
<div class="contentColumnBox one">
<div class="itemCardBox">
<div class="cardHeader">
<span>今日产量</span>
</div>
<div class="cardContentBox">
<div id="proportionChart" style="width: 100%; height: 100%;"></div>
</div>
</div>
<div class="cardContentBox">
<div id="thawingUnitChart" style="width: 100%; height: 100%;"></div>
<div class="itemCardBox">
<div class="cardHeader">
<span>今日投料情况</span>
</div>
<div class="cardContentBox">
<div id="mainMaterialChart" style="width: 100%; height: 100%;"></div>
</div>
</div>
</div>
<div class="itemCardBox">
<div class="cardHeader">
<span>切丁机组</span>
<div class="itemCardBox">
<div class="cardHeader">
<span>设备实时运转情况</span>
</div>
<div class="cardContentBox">
<div id="seasonMaterialChart" style="width: 100%; height: 100%;"></div>
</div>
</div>
<div class="cardContentBox">
<div style="width: 100%; height: 100%; display: flex;">
<div id="dicingUnitLineChart" style="width: 65%; height: 100%;"></div>
<div id="dicingUnitGaugeChart" style="width: 35%; height: 100%;"></div>
<div class="itemCardBox">
<div class="cardHeader">
<span>设备资源利用率</span>
</div>
<div class="cardContentBox">
<div id="rawMaterialChart" style="width: 100%; height: 100%;"></div>
</div>
</div>
</div>
<div class="itemCardBox">
<div class="cardHeader">
<span>连续切块机</span>
</div>
<div class="cardContentBox">
<div style="width: 100%; height: 100%; display: flex;">
<div id="continuouSlabberLeftChart" style="width: 50%; height: 100%;"></div>
<div id="continuouSlabberRightChart" style="width: 50%; height: 100%;"></div>
<div class="contentColumnBox two">
<div class="itemCardBox">
<div class="cardHeader">
<span>片冰机</span>
</div>
<div class="cardContentBox">
<div id="sliceIceMachineChart" style="width: 100%; height: 100%;"></div>
</div>
</div>
</div>
<div class="itemCardBox" style="position: relative;">
<div class="cardHeader" style="position: absolute;top: 5px; width: 100%;">
<span>绞肉机</span>
<div class="itemCardBox">
<div class="cardHeader">
<span>解冻机组</span>
</div>
<div class="cardContentBox">
<div id="thawingUnitChart" style="width: 100%; height: 100%;"></div>
</div>
</div>
<div class="cardContentBox" style="z-index: 1;">
<div id="meatGrinderChart" style="width: 100%; height: 100%;"></div>
<div class="itemCardBox">
<div class="cardHeader">
<span>切丁机组</span>
</div>
<div class="cardContentBox">
<div style="width: 100%; height: 100%; display: flex;">
<div id="dicingUnitLineChart" style="width: 65%; height: 100%;"></div>
<div id="dicingUnitGaugeChart" style="width: 35%; height: 100%;"></div>
</div>
</div>
</div>
</div>
</div>
<div class="contentColumnBox three">
<div class="itemCardBox">
<div class="cardHeader">
<span>斩拌机</span>
<div class="itemCardBox">
<div class="cardHeader">
<span>连续切块机</span>
</div>
<div class="cardContentBox">
<div style="width: 100%; height: 100%; display: flex;">
<div id="continuouSlabberLeftChart" style="width: 50%; height: 100%;"></div>
<div id="continuouSlabberRightChart" style="width: 50%; height: 100%;"></div>
</div>
</div>
</div>
<div class="cardContentBox">
<div id="ZBY550ChopperMixerChart" style="width: 100%; height: 100%;"></div>
<div class="itemCardBox" style="position: relative;">
<div class="cardHeader" style="position: absolute;top: 5px; width: 100%;">
<span>绞肉机</span>
</div>
<div class="cardContentBox" style="z-index: 1;">
<div id="meatGrinderChart" style="width: 100%; height: 100%;"></div>
</div>
</div>
</div>
<div class="itemCardBox">
<div class="cardHeader">
<span>真空搅拌机</span>
</div>
<div class="cardContentBox">
<div style="width: 100%; height: 100%; display: flex;flex-wrap: wrap;">
<div id="vacuumMixerRotateSpeedChart" style="width: 50%; height: 50%;"></div>
<div id="vacuumMixerRunTimeChart" style="width: 50%; height: 50%;"></div>
<div id="vacuumMixerRemainTimeChart" style="width: 50%; height: 50%;"></div>
<div id="vacuumMixerCWVoltageChart" style="width: 50%; height: 50%;"></div>
<div class="contentColumnBox three">
<div class="itemCardBox">
<div class="cardHeader">
<span>斩拌机</span>
</div>
<div class="cardContentBox">
<div id="ZBY550ChopperMixerChart" style="width: 100%; height: 100%;"></div>
</div>
</div>
</div>
<div class="itemCardBox">
<div class="cardHeader">
<span>真空滚揉机</span>
<div class="itemCardBox">
<div class="cardHeader">
<span>真空搅拌机</span>
</div>
<div class="cardContentBox">
<div style="width: 100%; height: 100%; display: flex;flex-wrap: wrap;">
<div id="vacuumMixerRotateSpeedChart" style="width: 50%; height: 50%;"></div>
<div id="vacuumMixerRunTimeChart" style="width: 50%; height: 50%;"></div>
<div id="vacuumMixerRemainTimeChart" style="width: 50%; height: 50%;"></div>
<div id="vacuumMixerCWVoltageChart" style="width: 50%; height: 50%;"></div>
</div>
</div>
</div>
<div class="cardContentBox">
<div style="width: 100%; height: 100%; display: flex;flex-wrap: wrap;">
<div id="vacuumTumblingRotateSpeedChart" style="width: 50%; height: 50%;"></div>
<div id="vacuumTumblingRunTimeChart" style="width: 50%; height: 50%;"></div>
<div id="vacuumTumblingRemainTimeChart" style="width: 50%; height: 50%;"></div>
<div class="itemCardBox">
<div class="cardHeader">
<span>真空滚揉机</span>
</div>
<div class="cardContentBox">
<div style="width: 100%; height: 100%; display: flex;flex-wrap: wrap;">
<div id="vacuumTumblingRotateSpeedChart" style="width: 50%; height: 50%;"></div>
<div id="vacuumTumblingRunTimeChart" style="width: 50%; height: 50%;"></div>
<div id="vacuumTumblingRemainTimeChart" style="width: 50%; height: 50%;"></div>
</div>
</div>
</div>
</div>
</div>
<div class="contentColumnBox four">
<div class="itemCardBox">
<div class="cardHeader">
<span>报警中心</span>
</div>
<div class="cardContentBox tableBox">
<el-table class="tableClass" :data="alarmList" height="1" tooltip-effect="light"
:row-style="{height: '30px', backgroundColor: 'transparent'}"
:cell-style="{padding: '5px 0', borderBottom:'none'}"
:header-row-style="{ backgroundColor: 'transparent'}" :header-cell-style="{
<div class="contentColumnBox four">
<div class="itemCardBox">
<div class="cardHeader">
<span>报警中心</span>
</div>
<div class="cardContentBox tableBox">
<el-table class="tableClass" :data="alarmList" height="1" tooltip-effect="light"
:row-style="{height: '30px', backgroundColor: 'transparent'}"
:cell-style="{padding: '5px 0', borderBottom:'none'}"
:header-row-style="{ backgroundColor: 'transparent'}" :header-cell-style="{
backgroundColor: 'transparent',
color: '#01c4f9',
fontWeight: 'bold',
......@@ -173,36 +173,36 @@
padding: '5px 0',
borderBottom:'none'
}">
<el-table-column prop="device" label="报警类型">
<template slot-scope="scope">
<span style="color: #fff; font-size: 12px;">[[ scope.row.device ]]</span>
</template>
</el-table-column>
<el-table-column prop="time" label="报警时间" width="80">
<template slot-scope="scope">
<span style="color: #fff; font-size: 12px;">[[ scope.row.time ]]</span>
</template>
</el-table-column>
<el-table-column prop="detail" label="报警描述" show-overflow-tooltip>
<template slot-scope="scope">
<span style="color: #fff; font-size: 12px;">[[ scope.row.detail ]]</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="itemCardBox">
<div class="cardHeader">
<span>今日计划执行情况</span>
<el-table-column prop="device" label="报警类型">
<template slot-scope="scope">
<span style="color: #fff; font-size: 12px;">[[ scope.row.device ]]</span>
</template>
</el-table-column>
<el-table-column prop="time" label="报警时间" width="80">
<template slot-scope="scope">
<span style="color: #fff; font-size: 12px;">[[ scope.row.time ]]</span>
</template>
</el-table-column>
<el-table-column prop="detail" label="报警描述" show-overflow-tooltip>
<template slot-scope="scope">
<span style="color: #fff; font-size: 12px;">[[ scope.row.detail ]]</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="cardContentBox">
<div id="meatGrainAnalysisChart" style="width: 100%; height: 100%;"></div>
<div class="itemCardBox">
<div class="cardHeader">
<span>今日计划执行情况</span>
</div>
<div class="cardContentBox">
<div id="meatGrainAnalysisChart" style="width: 100%; height: 100%;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<script>
......@@ -347,7 +347,7 @@
method: "POST",
url: this.baseURL + url,
data: config,
headers: {"Content-Type": contentType},
headers: { "Content-Type": contentType },
}).then((result) => {
if (
result?.data?.result?.code == 0 ||
......@@ -374,7 +374,7 @@
config = {},
errorMessage = "操作失败,请稍后重试",
contentType = "application/json",
baseurl = "https://tht.dws.rokecloud.com"
baseurl = ""
) {
return new Promise((resolve, reject) => {
if (!url) reject(null)
......@@ -382,7 +382,7 @@
method: "POST",
url: baseurl + url,
data: config,
headers: {"Content-Type": contentType},
headers: { "Content-Type": contentType },
}).then((result) => {
if (
result?.data?.result?.success ||
......@@ -420,7 +420,7 @@
method: "POST",
url: this.dwsBaseUrl + url,
data: config,
headers: {"Content-Type": contentType},
headers: { "Content-Type": contentType },
}).then((result) => {
if (result?.data?.success) {
resolve(result.data)
......@@ -558,7 +558,7 @@
},
tooltip: {
trigger: 'axis',
axisPointer: {type: 'shadow'},
axisPointer: { type: 'shadow' },
formatter: (params) => {
console.log(params)
let tooltipHtml = `<div style="font-weight:bold;margin-bottom:5px">${params[0].name}</div>`
......@@ -588,24 +588,24 @@
xAxis: {
type: 'category',
data: xAxisData,
axisLine: {lineStyle: {color: '#0a73ff'}},
axisLabel: {color: '#fff', fontSize: 10}
axisLine: { lineStyle: { color: '#0a73ff' } },
axisLabel: { color: '#fff', fontSize: 10 }
},
yAxis: {
type: 'value',
splitNumber: 4,
min: 0,
max: max,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3}},
axisLabel: {color: '#fff', fontSize: 10}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3 } },
axisLabel: { color: '#fff', fontSize: 10 }
},
series: [{
type: 'bar',
barWidth: '40%',
barGap: '0%',
data: seriesData,
itemStyle: {color: '#5087ec'},
itemStyle: { color: '#5087ec' },
label: {
show: true,
position: 'top',
......@@ -663,18 +663,18 @@
type: 'category',
boundaryGap: false,
data: xAxisData,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
axisTick: {show: false},
axisLabel: {color: '#fff', fontSize: 10, interval: 0}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
axisTick: { show: false },
axisLabel: { color: '#fff', fontSize: 10, interval: 0 }
},
yAxis: {
type: 'value',
splitNumber: 4,
min: 0,
max: max,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed'}},
axisLabel: {color: '#fff', fontSize: 10, formatter: '{value}'}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed' } },
axisLabel: { color: '#fff', fontSize: 10, formatter: '{value}' }
},
series: [{
type: 'line',
......@@ -728,19 +728,19 @@
data: [{
value: data?.green || 0,
name: '运行',
itemStyle: {color: '#91cc75'},
itemStyle: { color: '#91cc75' },
}, {
value: data?.yellow || 0,
name: '等待',
itemStyle: {color: '#ffd700'},
itemStyle: { color: '#ffd700' },
}, {
value: data?.red || 0,
name: '故障',
itemStyle: {color: '#ee6666'},
itemStyle: { color: '#ee6666' },
}, {
value: data?.gray || 0,
name: '关机',
itemStyle: {color: '#787878'},
itemStyle: { color: '#787878' },
}]
}]
})
......@@ -788,24 +788,24 @@
xAxis: {
type: 'category',
data: xAxisData,
axisLine: {lineStyle: {color: '#0a73ff'}},
axisLabel: {color: '#fff', fontSize: 10}
axisLine: { lineStyle: { color: '#0a73ff' } },
axisLabel: { color: '#fff', fontSize: 10 }
},
yAxis: {
type: 'value',
splitNumber: 4,
min: 0,
max: max,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3}},
axisLabel: {color: '#fff', fontSize: 10, formatter: '{value}%'}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3 } },
axisLabel: { color: '#fff', fontSize: 10, formatter: '{value}%' }
},
series: [{
type: 'bar',
barWidth: '40%',
barGap: '0%',
data: seriesData,
itemStyle: {color: '#5087ec'},
itemStyle: { color: '#5087ec' },
label: {
show: true,
position: 'top',
......@@ -847,24 +847,24 @@
xAxis: {
type: 'category',
data: xAxisData,
axisLine: {lineStyle: {color: '#0a73ff'}},
axisLabel: {color: '#fff', fontSize: 10}
axisLine: { lineStyle: { color: '#0a73ff' } },
axisLabel: { color: '#fff', fontSize: 10 }
},
yAxis: {
type: 'value',
splitNumber: 4,
min: 0,
max: max,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3}},
axisLabel: {color: '#fff', fontSize: 10, formatter: '{value}℃'}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3 } },
axisLabel: { color: '#fff', fontSize: 10, formatter: '{value}℃' }
},
series: [{
type: 'bar',
barWidth: '40%',
barGap: '0%',
data: seriesData,
itemStyle: {color: '#5087ec'},
itemStyle: { color: '#5087ec' },
label: {
show: true,
position: 'top',
......@@ -897,22 +897,22 @@
startAngle: 200,
endAngle: -20,
splitNumber: 5,
itemStyle: {color: '#3a8fff'},
progress: {show: true, width: 5},
pointer: {show: false},
axisLine: {lineStyle: {width: 5}},
itemStyle: { color: '#3a8fff' },
progress: { show: true, width: 5 },
pointer: { show: false },
axisLine: { lineStyle: { width: 5 } },
axisTick: {
distance: -15,
length: 5,
splitNumber: 5,
lineStyle: {width: 1, color: '#999'}
lineStyle: { width: 1, color: '#999' }
},
splitLine: {
distance: -15,
length: 8,
lineStyle: {width: 1, color: '#999'}
lineStyle: { width: 1, color: '#999' }
},
axisLabel: {distance: -15, color: '#999', fontSize: 10,},
axisLabel: { distance: -15, color: '#999', fontSize: 10, },
detail: {
valueAnimation: true,
offsetCenter: [0, 0],
......@@ -939,22 +939,22 @@
seriesData.push(data)
}
chart.setOption({
grid: {left: '5%', right: '5%', top: '8%', bottom: '5%'},
grid: { left: '5%', right: '5%', top: '8%', bottom: '5%' },
graphic: [{
type: 'text',
left: '12%',
top: '80%',
style: {text: '当前库内温度', fill: '#fff', fontSize: 10}
style: { text: '当前库内温度', fill: '#fff', fontSize: 10 }
}, {
type: 'text',
left: '45.5%',
top: '80%',
style: {text: '中心温度', fill: '#fff', fontSize: 10}
style: { text: '中心温度', fill: '#fff', fontSize: 10 }
}, {
type: 'text',
left: '75.5%',
top: '80%',
style: {text: '库内湿度', fill: '#fff', fontSize: 10}
style: { text: '库内湿度', fill: '#fff', fontSize: 10 }
}],
series: seriesData
})
......@@ -991,24 +991,24 @@
type: 'category',
boundaryGap: false,
data: xAxisData,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
axisTick: {show: false},
axisLabel: {color: '#fff', fontSize: 10, interval: 0}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
axisTick: { show: false },
axisLabel: { color: '#fff', fontSize: 10, interval: 0 }
},
yAxis: {
type: 'value',
splitNumber: 4,
min: 0,
max: max,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed'}},
axisLabel: {color: '#fff', fontSize: 10, formatter: '{value}' + unit}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed' } },
axisLabel: { color: '#fff', fontSize: 10, formatter: '{value}' + unit }
},
series: [{
type: 'line',
data: seriesData,
smooth: true,
lineStyle: {type: 'dashed'},
lineStyle: { type: 'dashed' },
label: {
show: true,
position: 'top',
......@@ -1018,8 +1018,8 @@
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{offset: 0, color: 'rgba(58, 143, 255, 0.8)'},
{offset: 1, color: 'rgba(58, 143, 255, 0.1)'}
{ offset: 0, color: 'rgba(58, 143, 255, 0.8)' },
{ offset: 1, color: 'rgba(58, 143, 255, 0.1)' }
])
},
}]
......@@ -1033,22 +1033,22 @@
startAngle: 200,
endAngle: -20,
splitNumber: 5,
itemStyle: {color: '#3a8fff'},
progress: {show: false, width: 5},
pointer: {itemStyle: {color: '#fe827a',}, length: "60%", width: 3},
itemStyle: { color: '#3a8fff' },
progress: { show: false, width: 5 },
pointer: { itemStyle: { color: '#fe827a', }, length: "60%", width: 3 },
axisLine: {
roundCap: true,
lineStyle: {
width: 5,
color: [[1, {
type: 'linear', x: 0, y: 0, x2: 1, y2: 0,
colorStops: [{offset: 0, color: '#91cc75'}, {offset: 1, color: '#ff4b4b'}]
colorStops: [{ offset: 0, color: '#91cc75' }, { offset: 1, color: '#ff4b4b' }]
}]]
}
},
axisTick: {show: false},
splitLine: {show: false},
axisLabel: {show: false},
axisTick: { show: false },
splitLine: { show: false },
axisLabel: { show: false },
detail: {
valueAnimation: true,
width: '40%',
......@@ -1058,8 +1058,8 @@
fontWeight: 'bold',
offsetCenter: [0, '40%']
},
data: [{value: 50, name: "加速时间"}],
title: {color: "#FFF", fontSize: 10, valueAnimation: false, offsetCenter: ['0', '70%']}
data: [{ value: 50, name: "加速时间" }],
title: { color: "#FFF", fontSize: 10, valueAnimation: false, offsetCenter: ['0', '70%'] }
}]
})
},
......@@ -1104,24 +1104,24 @@
xAxis: {
type: 'category',
data: xAxisData,
axisLine: {lineStyle: {color: '#0a73ff'}},
axisLabel: {color: '#fff', fontSize: 10}
axisLine: { lineStyle: { color: '#0a73ff' } },
axisLabel: { color: '#fff', fontSize: 10 }
},
yAxis: {
type: 'value',
splitNumber: 4,
min: 0,
max: runFrequencyMax,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3}},
axisLabel: {color: '#fff', fontSize: 10, formatter: '{value}Hz'}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3 } },
axisLabel: { color: '#fff', fontSize: 10, formatter: '{value}Hz' }
},
series: [{
type: 'bar',
barWidth: '40%',
barGap: '0%',
data: runFrequencyData,
itemStyle: {color: '#5087ec'},
itemStyle: { color: '#5087ec' },
label: {
show: true,
position: 'top',
......@@ -1152,8 +1152,8 @@
xAxis: {
type: 'category',
data: xAxisData,
axisLine: {lineStyle: {color: '#0a73ff'}},
axisLabel: {color: '#fff', fontSize: 10}
axisLine: { lineStyle: { color: '#0a73ff' } },
axisLabel: { color: '#fff', fontSize: 10 }
},
yAxis: {
type: 'value',
......@@ -1161,16 +1161,16 @@
splitNumber: 4,
min: 0,
max: cuttingSpeedMax,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3}},
axisLabel: {color: '#fff', fontSize: 10, formatter: '{value}ppm'}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3 } },
axisLabel: { color: '#fff', fontSize: 10, formatter: '{value}ppm' }
},
series: [{
type: 'bar',
barWidth: '40%',
barGap: '0%',
data: cuttingSpeedData,
itemStyle: {color: '#5087ec'},
itemStyle: { color: '#5087ec' },
label: {
show: true,
position: 'top',
......@@ -1214,31 +1214,31 @@
top: '0%',
itemWidth: 10,
itemHeight: 10,
textStyle: {color: "#fff", fontSize: 10}
textStyle: { color: "#fff", fontSize: 10 }
},
xAxis: {
type: 'category',
boundaryGap: false,
data: xAxisData,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
axisTick: {show: false},
axisLabel: {color: '#fff', fontSize: 10, interval: 0}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
axisTick: { show: false },
axisLabel: { color: '#fff', fontSize: 10, interval: 0 }
},
yAxis: {
type: 'value',
splitNumber: 4,
min: 0,
max: max,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed'}},
axisLabel: {color: '#fff', fontSize: 10, formatter: '{value}' + unit}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed' } },
axisLabel: { color: '#fff', fontSize: 10, formatter: '{value}' + unit }
},
series: [{
name: '设备A',
type: 'line',
data: deviceA,
smooth: true,
lineStyle: {type: 'dashed'},
lineStyle: { type: 'dashed' },
label: {
show: true,
position: 'top',
......@@ -1248,8 +1248,8 @@
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{offset: 0, color: 'rgba(58, 143, 255, 0.8)'},
{offset: 1, color: 'rgba(58, 143, 255, 0.1)'}
{ offset: 0, color: 'rgba(58, 143, 255, 0.8)' },
{ offset: 1, color: 'rgba(58, 143, 255, 0.1)' }
])
},
}, {
......@@ -1257,7 +1257,7 @@
type: 'line',
data: deviceB,
smooth: true,
lineStyle: {type: 'dashed'},
lineStyle: { type: 'dashed' },
label: {
show: true,
position: 'top',
......@@ -1305,18 +1305,18 @@
type: 'category',
boundaryGap: false,
data: xAxisData,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
axisTick: {show: false},
axisLabel: {color: '#fff', fontSize: 10, interval: 0}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
axisTick: { show: false },
axisLabel: { color: '#fff', fontSize: 10, interval: 0 }
},
yAxis: {
type: 'value',
splitNumber: 4,
min: 0,
max: max,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed'}},
axisLabel: {color: '#ccc', fontSize: 10, formatter: '{value}' + unit}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed' } },
axisLabel: { color: '#ccc', fontSize: 10, formatter: '{value}' + unit }
},
series: [{
type: 'line',
......@@ -1374,24 +1374,24 @@
xAxis: {
type: 'category',
data: xAxisData,
axisLine: {lineStyle: {color: '#0a73ff'}},
axisLabel: {color: '#fff', fontSize: 10, interval: 0}
axisLine: { lineStyle: { color: '#0a73ff' } },
axisLabel: { color: '#fff', fontSize: 10, interval: 0 }
},
yAxis: {
type: 'value',
splitNumber: 4,
min: 0,
max: max,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3}},
axisLabel: {color: '#fff', fontSize: 10, formatter: '{value}ppm'}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3 } },
axisLabel: { color: '#fff', fontSize: 10, formatter: '{value}ppm' }
},
series: [{
type: 'bar',
barWidth: '40%',
barGap: '0%',
data: seriesData,
itemStyle: {color: '#5087ec'},
itemStyle: { color: '#5087ec' },
label: {
show: true,
position: 'top',
......@@ -1426,18 +1426,18 @@
type: 'category',
boundaryGap: false,
data: xAxisData,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
axisTick: {show: false},
axisLabel: {color: '#fff', fontSize: 10, interval: 0}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
axisTick: { show: false },
axisLabel: { color: '#fff', fontSize: 10, interval: 0 }
},
yAxis: {
type: 'value',
splitNumber: 4,
min: 0,
max: max,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed'}},
axisLabel: {color: '#ccc', fontSize: 10, formatter: '{value}' + 'min'}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed' } },
axisLabel: { color: '#ccc', fontSize: 10, formatter: '{value}' + 'min' }
},
series: [{
type: 'line',
......@@ -1476,18 +1476,18 @@
type: 'category',
boundaryGap: false,
data: xAxisData,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
axisTick: {show: false},
axisLabel: {color: '#fff', fontSize: 10, interval: 0}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
axisTick: { show: false },
axisLabel: { color: '#fff', fontSize: 10, interval: 0 }
},
yAxis: {
type: 'value',
splitNumber: 4,
min: 0,
max: max,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed'}},
axisLabel: {color: '#ccc', fontSize: 10, formatter: '{value}' + 'min'}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed' } },
axisLabel: { color: '#ccc', fontSize: 10, formatter: '{value}' + 'min' }
},
series: [{
type: 'line',
......@@ -1526,18 +1526,18 @@
type: 'category',
boundaryGap: false,
data: xAxisData,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
axisTick: {show: false},
axisLabel: {color: '#fff', fontSize: 10, interval: 0}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
axisTick: { show: false },
axisLabel: { color: '#fff', fontSize: 10, interval: 0 }
},
yAxis: {
type: 'value',
splitNumber: 4,
min: 0,
max: max,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed'}},
axisLabel: {color: '#ccc', fontSize: 10, formatter: '{value}' + 'kpa'}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed' } },
axisLabel: { color: '#ccc', fontSize: 10, formatter: '{value}' + 'kpa' }
},
series: [{
type: 'line',
......@@ -1593,24 +1593,24 @@
xAxis: {
type: 'category',
data: xAxisData,
axisLine: {lineStyle: {color: '#0a73ff'}},
axisLabel: {color: '#fff', fontSize: 10, interval: 0}
axisLine: { lineStyle: { color: '#0a73ff' } },
axisLabel: { color: '#fff', fontSize: 10, interval: 0 }
},
yAxis: {
type: 'value',
splitNumber: 4,
min: 0,
max: max,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3}},
axisLabel: {color: '#fff', fontSize: 10, formatter: '{value}ppm'}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3 } },
axisLabel: { color: '#fff', fontSize: 10, formatter: '{value}ppm' }
},
series: [{
type: 'bar',
barWidth: '40%',
barGap: '0%',
data: seriesData,
itemStyle: {color: '#5087ec'},
itemStyle: { color: '#5087ec' },
label: {
show: true,
position: 'top',
......@@ -1645,18 +1645,18 @@
type: 'category',
boundaryGap: false,
data: xAxisData,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
axisTick: {show: false},
axisLabel: {color: '#fff', fontSize: 10, interval: 0}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
axisTick: { show: false },
axisLabel: { color: '#fff', fontSize: 10, interval: 0 }
},
yAxis: {
type: 'value',
splitNumber: 4,
min: 0,
max: max,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed'}},
axisLabel: {color: '#ccc', fontSize: 10, formatter: '{value}' + 'min'}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed' } },
axisLabel: { color: '#ccc', fontSize: 10, formatter: '{value}' + 'min' }
},
series: [{
type: 'line',
......@@ -1695,18 +1695,18 @@
type: 'category',
boundaryGap: false,
data: xAxisData,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
axisTick: {show: false},
axisLabel: {color: '#fff', fontSize: 10, interval: 0}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
axisTick: { show: false },
axisLabel: { color: '#fff', fontSize: 10, interval: 0 }
},
yAxis: {
type: 'value',
splitNumber: 4,
min: 0,
max: max,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed'}},
axisLabel: {color: '#ccc', fontSize: 10, formatter: '{value}' + 'min'}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3, type: 'dashed' } },
axisLabel: { color: '#ccc', fontSize: 10, formatter: '{value}' + 'min' }
},
series: [{
type: 'line',
......@@ -1757,13 +1757,13 @@
legend: {
top: '-2%',
right: '5%',
textStyle: {color: '#fff', fontSize: 10},
textStyle: { color: '#fff', fontSize: 10 },
itemWidth: 20,
itemHeight: 10,
},
tooltip: {
trigger: 'axis',
axisPointer: {type: 'shadow'},
axisPointer: { type: 'shadow' },
formatter: (params) => {
let tooltipHtml = `<div style="font-weight:bold;margin-bottom:5px">${params[0].name}</div>`
......@@ -1802,17 +1802,17 @@
xAxis: {
type: 'category',
data: xAxisData,
axisLine: {lineStyle: {color: '#0a73ff'}},
axisLabel: {color: '#fff', fontSize: 10}
axisLine: { lineStyle: { color: '#0a73ff' } },
axisLabel: { color: '#fff', fontSize: 10 }
},
yAxis: {
type: 'value',
splitNumber: 5,
min: 0,
max: max,
axisLine: {show: true, lineStyle: {color: '#0a73ff'}},
splitLine: {lineStyle: {color: '#0a73ff', width: 0.5, opacity: 0.3}},
axisLabel: {color: '#fff', fontSize: 10}
axisLine: { show: true, lineStyle: { color: '#0a73ff' } },
splitLine: { lineStyle: { color: '#0a73ff', width: 0.5, opacity: 0.3 } },
axisLabel: { color: '#fff', fontSize: 10 }
},
series: [{
name: '投产数量',
......@@ -1820,7 +1820,7 @@
barWidth: '40%',
barGap: '0%',
data: operationData,
itemStyle: {color: '#5087ec'},
itemStyle: { color: '#5087ec' },
label: {
show: true,
position: 'top',
......@@ -1834,7 +1834,7 @@
barWidth: '40%',
barGap: '0%',
data: quantityData,
itemStyle: {color: '#68bbc4'},
itemStyle: { color: '#68bbc4' },
label: {
show: true,
position: 'top',
......@@ -1985,14 +1985,6 @@
border-right: 2px solid #cbdbf8;
background: transparent;
border-radius: 10px;
<<<<<<< HEAD
animation: rainbow-glow 5s linear infinite;
box-shadow: -10px 0 10px -10px #ff0000,
10px 0 10px -10px #ff0000,
inset -10px 0 10px -10px #ff0000,
inset 10px 0 10px -10px #ff0000;
background-color: transparent;
.badgeIcon {
position: absolute;
......@@ -2105,7 +2097,7 @@
width: 100%;
background-color: transparent;
.el-table__body tr:hover > td.el-table__cell {
.el-table__body tr:hover>td.el-table__cell {
background-color: rgba(10, 115, 255, 0.3);
}
}
......@@ -2178,63 +2170,63 @@
@keyframes rainbow-glow {
0% {
box-shadow: -10px 0 10px -10px #ff0000,
10px 0 10px -10px #ff0000,
inset -10px 0 10px -10px #ff0000,
inset 10px 0 10px -10px #ff0000;
10px 0 10px -10px #ff0000,
inset -10px 0 10px -10px #ff0000,
inset 10px 0 10px -10px #ff0000;
border-left-color: #ff0000;
border-right-color: #ff0000;
}
16% {
box-shadow: -10px 0 10px -10px #ff9900,
10px 0 10px -10px #ff9900,
inset -10px 0 10px -10px #ff9900,
inset 10px 0 10px -10px #ff9900;
10px 0 10px -10px #ff9900,
inset -10px 0 10px -10px #ff9900,
inset 10px 0 10px -10px #ff9900;
border-left-color: #ff9900;
border-right-color: #ff9900;
}
33% {
box-shadow: -10px 0 10px -10px #ffff00,
10px 0 10px -10px #ffff00,
inset -10px 0 10px -10px #ffff00,
inset 10px 0 10px -10px #ffff00;
10px 0 10px -10px #ffff00,
inset -10px 0 10px -10px #ffff00,
inset 10px 0 10px -10px #ffff00;
border-left-color: #ffff00;
border-right-color: #ffff00;
}
50% {
box-shadow: -10px 0 10px -10px #33cc33,
10px 0 10px -10px #33cc33,
inset -10px 0 10px -10px #33cc33,
inset 10px 0 10px -10px #33cc33;
10px 0 10px -10px #33cc33,
inset -10px 0 10px -10px #33cc33,
inset 10px 0 10px -10px #33cc33;
border-left-color: #33cc33;
border-right-color: #33cc33;
}
66% {
box-shadow: -10px 0 10px -10px #0099ff,
10px 0 10px -10px #0099ff,
inset -10px 0 10px -10px #0099ff,
inset 10px 0 10px -10px #0099ff;
10px 0 10px -10px #0099ff,
inset -10px 0 10px -10px #0099ff,
inset 10px 0 10px -10px #0099ff;
border-left-color: #0099ff;
border-right-color: #0099ff;
}
83% {
box-shadow: -10px 0 10px -10px #6633ff,
10px 0 10px -10px #6633ff,
inset -10px 0 10px -10px #6633ff,
inset 10px 0 10px -10px #6633ff;
10px 0 10px -10px #6633ff,
inset -10px 0 10px -10px #6633ff,
inset 10px 0 10px -10px #6633ff;
border-left-color: #6633ff;
border-right-color: #6633ff;
}
100% {
box-shadow: -10px 0 10px -10px #ff0066,
10px 0 10px -10px #ff0066,
inset -10px 0 10px -10px #ff0066,
inset 10px 0 10px -10px #ff0066;
10px 0 10px -10px #ff0066,
inset -10px 0 10px -10px #ff0066,
inset 10px 0 10px -10px #ff0066;
border-left-color: #ff0066;
border-right-color: #ff0066;
}
......
......@@ -23,7 +23,7 @@
alt="header background" />
<span class="header-text">设备实时看板</span>
<span class="hintText">
<i style="font-size: 30px;" @click="toggleFullscreen"
<i style="font-size: 30px;" @click="toggleFullscreen"
:class="isFullscreen ? 'el-icon-close' : 'el-icon-full-screen'"></i>
<span> [[currentTime ]]</span>
</span>
......@@ -31,10 +31,7 @@
</div>
<div class="workshop-filter" style="text-align: center; margin: 10px 0">
<el-radio-group
v-model="selectedWorkshop"
@change="onWorkshopChange"
size="medium">
<el-radio-group v-model="selectedWorkshop" @change="onWorkshopChange" size="medium">
<el-radio label="">
<span style="font-size: 18px;">全部<span></el-radio>
<el-radio label="预料车间">
......@@ -43,45 +40,46 @@
<el-radio label="蒸煮车间">
<span style="font-size: 18px">成型车间<span>
</el-radio>
<el-radio label="包装车间" >
<el-radio label="包装车间">
<span style="font-size: 18px">包装车间<span>
</el-radio>
</el-radio-group>
</div>
<!-- 设备状态卡片区域 - 新设计 -->
<div class="device-cards-container">
<div v-for="(device, index) in deviceList" :key="index" class="device-card new-design"
:class="getCardClass(device.status)">
<!-- 设备名称 - 左上角 -->
<div class="device-name">[[truncateText(device.name, 12)]]</div>
<!-- 设备状态 - 右上角 -->
<div class="device-status-tag" :class="getStatusClass(device.status)">
[[getStatusText(device.status)]]
</div>
<!-- 设备状态水波纹 - 中间 -->
<div class="device-wave-container">
<!-- v-if="device.status === 'running' || device.status === 'waiting'" -->
<div class="oee-text">
OEE
<div class="scrollBoxClass">
<div class="device-cards-container">
<div v-for="(device, index) in deviceList" :key="index" class="device-card new-design"
:class="getCardClass(device.status)">
<!-- 设备名称 - 左上角 -->
<div class="device-name">[[truncateText(device.name, 12)]]</div>
<!-- 设备状态 - 右上角 -->
<div class="device-status-tag" :class="getStatusClass(device.status)">
[[getStatusText(device.status)]]
</div>
<!-- <div class="err-text" v-if="device.status === 'error'" :class="getErrClass(device.status)">
<!-- 设备状态水波纹 - 中间 -->
<div class="device-wave-container">
<!-- v-if="device.status === 'running' || device.status === 'waiting'" -->
<div class="oee-text">
OEE
</div>
<!-- <div class="err-text" v-if="device.status === 'error'" :class="getErrClass(device.status)">
ERR
</div>
<div class="off-text" v-if="device.status === 'off'" :class="getOffClass(device.status)">
OFF
</div> -->
<!-- v-if="device.status === 'running' || device.status === 'waiting'" -->
<div class="percentage-text">
[[ device.percentage > 100 ? 100 : device.percentage ]]%
</div>
<!-- v-if="device.status === 'running' || device.status === 'waiting'" -->
<div class="percentage-text">
[[ device.percentage > 100 ? 100 : device.percentage ]]%
</div>
<!-- 圆形容器 -->
<div class="circle-container" :class="getBorderClass(device.status)">
<!-- 水波纹效果 - 通过内联样式直接控制高度百分比 -->
<div class="water-wave" :class="getWaveClass(device.status)" :style="{
<!-- 圆形容器 -->
<div class="circle-container" :class="getBorderClass(device.status)">
<!-- 水波纹效果 - 通过内联样式直接控制高度百分比 -->
<div class="water-wave" :class="getWaveClass(device.status)" :style="{
'height': getWaveHeight(device.status, device.percentage) + '%',
'bottom': '0',
'left': '0',
......@@ -89,35 +87,36 @@
'width': '100%',
'overflow': 'hidden'
}">
<div class="water-wave-content">
<div class="water-wave-ripple"></div>
<div class="water-wave-content">
<div class="water-wave-ripple"></div>
</div>
</div>
</div>
</div>
</div>
<!-- 设备状态信息 - 底部 -->
<div class="device-status-info">
<span>已持续 [[device.duration]]</span>
</div>
<div style="width: 100%; display: flex;margin-left: 13px;">
<div class="flxe_sty">
<div class="flxe_label_sty" style=" background-color: #00aa00;">开机</div>
[[ device.run_seconds ]]
<!-- 设备状态信息 - 底部 -->
<div class="device-status-info">
<span>已持续 [[device.duration]]</span>
</div>
<div class="flxe_sty">
<div class="flxe_label_sty" style=" background-color: #ffaa00;">加工</div>
[[ device.green_seconds ]]
</div>
</div>
<div style="width: 100%;display: flex;margin-left: 13px;">
<div class="flxe_sty">
<div class="flxe_label_sty" style=" background-color: #797979;">空闲</div>
[[ device.yellow_seconds ]]
<div style="width: 100%; display: flex;margin-left: 13px;">
<div class="flxe_sty">
<div class="flxe_label_sty" style=" background-color: #00aa00;">开机</div>
[[ device.run_seconds ]]
</div>
<div class="flxe_sty">
<div class="flxe_label_sty" style=" background-color: #ffaa00;">加工</div>
[[ device.green_seconds ]]
</div>
</div>
<div class="flxe_sty">
<div class="flxe_label_sty" style=" background-color: #f87171;">故障</div>
[[ device.red_seconds ]]
<div style="width: 100%;display: flex;margin-left: 13px;">
<div class="flxe_sty">
<div class="flxe_label_sty" style=" background-color: #797979;">空闲</div>
[[ device.yellow_seconds ]]
</div>
<div class="flxe_sty">
<div class="flxe_label_sty" style=" background-color: #f87171;">故障</div>
[[ device.red_seconds ]]
</div>
</div>
</div>
</div>
......@@ -201,20 +200,20 @@
<script>
// 发送消息给父页面(关闭odoo的菜单弹窗)
document.addEventListener("click", () => {
document.addEventListener("click", function () {
window.parent.postMessage("hidePopover", "*");
});
let vue = new Vue({
el: "#app",
delimiters: ["[[", "]]"], // 替换原本vue的[[ key ]]取值方式(与odoo使用的jinja2冲突问题)
data() {
data: function () {
return {
isFullscreen: false, // 全屏状态
currentTime: null, // 当前时间
timer: null, // 定时器
windowHeight: window.innerHeight, // 窗口高度
// dwsURL: "https://workstation.rokeris.com", // 基地址
dwsURL: "", // 基地址
dwsURL: "https://tht.dws.rokecloud.com", // 基地址
// dwsURL: "", // 基地址
baseURL: "https://dws-platform.xbg.rokeris.com/dev-api", // 基地址
loading: false, // 全局加载效果
deviceList: [], // 设备列表
......@@ -230,7 +229,7 @@
selectedWorkshop: "", // 新增字段:当前选中的车间
};
},
created() {
created: function () {
if (this.getUrlSearch("factory_code")) {
this.factoryCode = this.getUrlSearch("factory_code"); //截取url后面的参数
}
......@@ -238,13 +237,13 @@
},
computed: {
// 选中设备的信息
selDeviceInfo() {
return this.deviceList.find((item) => item.id == this.selectedDevice);
selDeviceInfo: function () {
return this.deviceList.find(function (item) { return item.id == this.selectedDevice; }.bind(this));
},
},
async mounted() {
window.addEventListener("resize", this.handleResize);
this.$nextTick(() => {
this.$nextTick(function () {
document.getElementById("bodyId").style.display = "block";
});
......@@ -258,26 +257,26 @@
this.dateList = this.getLastAssignDays();
// 设置定时刷新(每分钟刷新一次,静默模式)
this.refreshInterval = setInterval(() => {
this.refreshInterval = setInterval(function () {
this.initData(true); // 传入true表示静默刷新,不显示加载提示
}, 60000);
}.bind(this), 60000);
// 设置设备信息的title属性
this.$nextTick(() => {
document.querySelectorAll(".device-info").forEach((el) => {
this.$nextTick(function () {
document.querySelectorAll(".device-info").forEach(function (el) {
el.title = el.dataset.fullTitle;
});
});
},
updated() {
updated: function () {
// 在数据更新后也设置title属性
this.$nextTick(() => {
document.querySelectorAll(".device-info").forEach((el) => {
this.$nextTick(function () {
document.querySelectorAll(".device-info").forEach(function (el) {
el.title = el.dataset.fullTitle;
});
});
},
beforeDestroy() {
beforeDestroy: function () {
// 清除定时器
if (this.refreshInterval) {
clearInterval(this.refreshInterval);
......@@ -290,7 +289,7 @@
},
methods: {
// 全屏icon点击事件
toggleFullscreen() {
toggleFullscreen: function () {
if (!this.isFullscreen) {
this.enterFullScreen()
} else {
......@@ -298,7 +297,7 @@
}
},
// 全屏方法
enterFullScreen() {
enterFullScreen: function () {
// 获取需要全屏的元素
const elem = this.$refs.fullScreenElement
if (elem.requestFullscreen) {
......@@ -315,7 +314,7 @@
}
this.isFullscreen = true
},
exitFullScreen() {
exitFullScreen: function () {
if (document.exitFullscreen) {
document.exitFullscreen()
} else if (document.mozCancelFullScreen) {
......@@ -330,12 +329,12 @@
}
this.isFullscreen = false
},
onWorkshopChange() {
onWorkshopChange: function () {
this.initData(); // 触发重新加载数据
},
// 初始化当前时间
initCurrentTimeFn() {
this.timer = setInterval(() => {
initCurrentTimeFn: function () {
this.timer = setInterval(function () {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
......@@ -344,10 +343,10 @@
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
this.currentTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}, 1000)
}.bind(this), 1000)
},
// 通过网址跳转过来的页面,截取后面的参数
getUrlSearch(name) {
getUrlSearch: function (name) {
// 未传参,返回空
if (!name) return "";
// 查询参数:先通过search取值,如果取不到就通过hash来取
......@@ -365,7 +364,7 @@
return r[2];
},
// 初始化数据
async initData(silent = false, workshopName = this.selectedWorkshop) {
async initData(silent = false, workshopName = this.selectedWorkshop) {
try {
// 只有在非静默模式下才显示加载提示
if (!silent) {
......@@ -412,8 +411,8 @@
const end_working_time = response.data.result.end_working_time || [];
const wait_time = response.data.result.wait_time || [];
if (this.factoryCode) {
// 调用设备状态接口
await this.getDeviceStateList(start_working_time, end_working_time, wait_time);
// 调用设备状态接口
await this.getDeviceStateList(start_working_time, end_working_time, wait_time);
}
else {
await this.getFactoryCode(start_working_time, end_working_time, wait_time);
......@@ -439,7 +438,7 @@
method: "post",
url: this.dwsURL + "/roke/workstation/equipment/get_equipment_data",
data: {
plant_name: workshopName,
plant_name: workshopName,
},
headers: {
"Content-Type": "application/json",
......@@ -522,33 +521,33 @@
},
// 处理设备状态数据
processDeviceStateData(deviceStateData) {
processDeviceStateData: function (deviceStateData) {
if (!deviceStateData || !Array.isArray(deviceStateData)) {
return;
}
const codeToSeqMap = {};
this.allEquipmentData.forEach(equip => {
var codeToSeqMap = {};
this.allEquipmentData.forEach(function (equip) {
codeToSeqMap[equip.code] = equip.sequence;
});
// 获取当前车间下的设备 code 列表
const validCodes = this.allEquipmentData
.filter(e => !this.selectedWorkshop || e.plant_name === this.selectedWorkshop)
.map(e => e.code);
// 获取当前车间下的设备 code 列表
var validCodes = this.allEquipmentData
.filter(function (e) { return !this.selectedWorkshop || e.plant_name === this.selectedWorkshop; }.bind(this))
.map(function (e) { return e.code; });
// 过滤掉不属于当前车间的设备
const filteredDevices = deviceStateData.filter(d =>
!this.selectedWorkshop || validCodes.includes(d.code)
).map(device => ({
...device,
seq: codeToSeqMap[device.code] || Number.MAX_SAFE_INTEGER // 如果找不到 seq,默认排最后
}));
var filteredDevices = deviceStateData.filter(function (d) {
return !this.selectedWorkshop || validCodes.includes(d.code);
}.bind(this)).map(function (device) {
var newDevice = Object.assign({}, device);
newDevice.seq = codeToSeqMap[device.code] || Number.MAX_SAFE_INTEGER; // 如果找不到 seq,默认排最后
return newDevice;
});
// 将API返回的数据转换为页面所需的格式
this.deviceList = filteredDevices.map((device) => {
this.deviceList = filteredDevices.map(function (device) {
// 根据API返回的状态确定前端显示的状态
let status = "off";
var status = "off";
if (device.state === "green") {
status = "running";
} else if (device.state === "yellow") {
......@@ -559,33 +558,30 @@
status = "off";
}
// 计算持续时间的显示格式
let durationText = "0"
var durationText = "0"
if (device.duration_hours !== undefined) {
durationText = this.formatTime(Number(device.duration_hours * 3600))
}
let run_seconds = "0"
var run_seconds = "0"
if (device.run_seconds !== undefined) run_seconds = this.formatTime(Number(device.run_seconds))
let green_seconds = "0"
var green_seconds = "0"
if (device.green_seconds !== undefined) green_seconds = this.formatTime(Number(device.green_seconds))
let yellow_seconds = "0"
var yellow_seconds = "0"
if (device.yellow_seconds !== undefined) yellow_seconds = this.formatTime(Number(device.yellow_seconds))
let red_seconds = "0"
if (device.red_seconds !== undefined) yellow_seconds = this.formatTime(Number(device.yellow_seconds))
var red_seconds = "0"
if (device.red_seconds !== undefined) red_seconds = this.formatTime(Number(device.red_seconds))
// 计算利用率百分比,确保有效值
const percentage = device.utilization_rate !== undefined ? Math.round(device
.utilization_rate) : 0
var percentage = device.utilization_rate !== undefined ? Math.round(device.utilization_rate) : 0
// 从所有设备列表中获取准确的设备名称
let deviceName = device.name || device.code // 默认使用API返回的名称或编码
var deviceName = device.name || device.code // 默认使用API返回的名称或编码
// 在所有设备列表中查找匹配的设备
if (this.allEquipmentData && this.allEquipmentData.length > 0) {
const matchedDevice = this.allEquipmentData.find(
(equip) => equip.code === device.code
)
var matchedDevice = this.allEquipmentData.find(function (equip) { return equip.code === device.code; });
// 如果找到匹配的设备,使用其名称
if (matchedDevice && matchedDevice.name) {
deviceName = device.name ? matchedDevice.name : device.code
......@@ -605,28 +601,28 @@
yellow_seconds: yellow_seconds,
red_seconds: red_seconds
}
}).sort((a, b) => (codeToSeqMap[a.code] || Number.MAX_SAFE_INTEGER)
- (codeToSeqMap[b.code] || Number.MAX_SAFE_INTEGER));
this.deviceList = this.deviceList.filter((device) => device)
}.bind(this)).sort(function (a, b) {
return (codeToSeqMap[a.code] || Number.MAX_SAFE_INTEGER) - (codeToSeqMap[b.code] || Number.MAX_SAFE_INTEGER);
});
},
formatTime(seconds) {
formatTime: function (seconds) {
if (seconds < 60) {
return `0min`; // 不足 1 分钟显示 0min
} else if (seconds < 3600) {
const minutes = Math.floor(seconds / 60); // 转换为分钟
var minutes = Math.floor(seconds / 60); // 转换为分钟
return `${minutes}min`; // 显示分钟
} else if (seconds < 86400) { // 小于 1 天
const hours = Math.floor(seconds / 3600); // 转换为小时
var hours = Math.floor(seconds / 3600); // 转换为小时
return `${hours}h`; // 只返回小时
} else {
const days = Math.floor(seconds / 86400); // 转换为天数
var days = Math.floor(seconds / 86400); // 转换为天数
return `${days}d`; // 只返回天
}
},
// 初始化模拟数据 (保留原有的模拟数据方法,作为备用)
initMockData() {
initMockData: function () {
// 模拟设备数据 - 添加不同状态和明显不同百分比的测试数据
this.deviceList = [
// {
......@@ -668,7 +664,7 @@
},
// 获取卡片的CSS类名
getCardClass(status) {
getCardClass: function (status) {
switch (status) {
case "running":
return "card-running";
......@@ -683,7 +679,7 @@
},
// 获取边框的CSS类名
getBorderClass(status) {
getBorderClass: function (status) {
switch (status) {
case "running":
return "border-running";
......@@ -698,7 +694,7 @@
},
// 获取设备状态对应的CSS类名
getStatusClass(status) {
getStatusClass: function (status) {
switch (status) {
case "running":
return "status-running";
......@@ -713,7 +709,7 @@
},
// 获取波浪效果的类名
getWaveClass(status) {
getWaveClass: function (status) {
switch (status) {
case "running":
return "wave-running";
......@@ -728,23 +724,16 @@
},
// 获取波浪高度
getWaveHeight(status, percentage) {
getWaveHeight: function (status, percentage) {
// 将百分比限制在10%-100%之间,确保即使是低百分比也有一定的水位可见
let height = percentage;
// 如果是故障或停机状态,固定显示50%
// if (status === "error" || status === "off") {
// height = 50;
// }
var height = percentage;
// 确保最小高度为10%,最大为100%
height = Math.min(Math.max(height, 10), 100);
return height;
},
// 获取设备状态对应的文本
getStatusText(status) {
getStatusText: function (status) {
switch (status) {
case "running":
return "运行中";
......@@ -759,10 +748,11 @@
},
// 处理小数位数方法
toFixedHandle(value, num = 4) {
toFixedHandle: function (value, num) {
if (num === undefined) num = 4;
if (value) {
let strValue = String(value);
if (strValue.split(".").length > 1 || strValue.split(".")[1]?.length > num) {
var strValue = String(value);
if (strValue.split(".").length > 1 || (strValue.split(".")[1] && strValue.split(".")[1].length > num)) {
strValue = Number(strValue).toFixed(num);
}
return Number(strValue);
......@@ -772,26 +762,26 @@
},
// 计算高度百分比
calculateHeight(hours) {
calculateHeight: function (hours) {
// 24小时对应整个高度(100%)
// 每4小时对应一个刻度区间,总共6个区间
// 计算每小时占的百分比:100% / 24 ≈ 4.167%
const heightPerHour = 100 / 24;
const percentage = hours * heightPerHour;
var heightPerHour = 100 / 24;
var percentage = hours * heightPerHour;
// 确保高度在0-100%之间
return Math.min(Math.max(percentage, 0), 100);
},
// 获取最后指定天数的日期
getLastAssignDays(num = 10) {
const dates = [];
for (let i = num - 1; i >= 0; i--) {
const date = new Date();
getLastAssignDays: function (num) {
if (num === undefined) num = 10;
var dates = [];
for (var i = num - 1; i >= 0; i--) {
var date = new Date();
date.setDate(date.getDate() - i);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
var year = date.getFullYear();
var month = String(date.getMonth() + 1).padStart(2, "0");
var day = String(date.getDate()).padStart(2, "0");
dates.push(`${year}-${month}-${day}`);
}
this.start_time = dates[0]; // 第一天
......@@ -800,25 +790,25 @@
},
// 处理窗口大小变化
handleResize() {
handleResize: function () {
// 窗口大小变化时的处理逻辑
},
// 文本截断方法
truncateText(text, maxLength) {
truncateText: function (text, maxLength) {
if (!text) return "";
if (text.length <= maxLength) return text;
return text.substring(0, maxLength) + "...";
},
// 显示完整标题
showFullTitle(event, device) {
const fullTitle = device.name + " | " + device.code;
showFullTitle: function (event, device) {
var fullTitle = device.name + " | " + device.code;
event.target.setAttribute("title", fullTitle);
},
// 获取ERR文字的CSS类名
getErrClass(status) {
getErrClass: function (status) {
if (status === "error") {
return "err-error";
}
......@@ -826,7 +816,7 @@
},
// 获取OFF文字的CSS类名
getOffClass(status) {
getOffClass: function (status) {
if (status === "off") {
return "off-status";
}
......@@ -901,7 +891,7 @@
z-index: 1;
}
.hintText {
.hintText {
position: absolute;
font-size: 14px;
bottom: -5px;
......@@ -912,6 +902,12 @@
gap: 10px;
}
.scrollBoxClass {
height: 1px;
flex: auto;
overflow-y: auto;
}
/* 设备卡片容器 */
.device-cards-container {
display: grid;
......@@ -1300,20 +1296,20 @@
font-size: 10px;
color: #fff;
margin-top: 5px;
}
.flxe_label_sty {
margin-right: 2px;
font-weight: bold;
color: #000;
display: flex;
justify-content: center;
align-items: center;
font-size: 10px;
width: 30px;
height: auto;
border-radius: 2px;
margin-left: 10px;
}
.flxe_label_sty {
margin-right: 2px;
font-weight: bold;
color: #000;
display: flex;
justify-content: center;
align-items: center;
font-size: 10px;
width: 30px;
height: auto;
border-radius: 2px;
margin-left: 10px;
}
</style>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment