This commit is contained in:
hzz 2025-04-18 17:13:51 +08:00
parent ad569425b6
commit 79b6f1d141
17 changed files with 689 additions and 161 deletions

View File

@ -30,6 +30,12 @@ export function getdeviceInfo() {
//获取设备信息
export function device(obj) {
return request({
@ -39,6 +45,15 @@ export function device(obj) {
})
}
//获取缝纫工作记录
export function getSewingList(obj) {
return request({
url: '/pms/device/getSewingList',
method: 'get',
params: obj
})
}
//获取裁片视觉检测工作记录
export function getOKOrNGList(obj) {
@ -48,7 +63,31 @@ export function getOKOrNGList(obj) {
params: obj
})
}
//获取缝纫,冲孔机工作记录
export function abnormalShutdown(obj) {
return request({
url: '/pms/device/abnormalShutdown',
method: 'get',
params: obj
})
}
//获取平板扫描工作记录
export function getScanList(obj) {
return request({
url: '/pms/device/getScanList',
method: 'get',
params: obj
})
}
//OEE
export function oee(obj) {
return request({
url: '/pms/device/oee',
method: 'get',
params: obj
})
}

View File

@ -473,5 +473,23 @@ export default {
"本周": "The Week",
"本月": "The Month",
"故障": "Fault",
'停机中':'stop',
'运行中':'Running',
'待机中':'Waiting',
'故障中':'faulting',
'总产量':'Total Output',
'设备转速':'Device Speed',
'综合设备效率':'Comprehensive Device Efficiency',
'实时报警':'Real-time alarm',
'全部清除':'Clear all',
'忽略':'Ignore',
'暂无报警':'No alarm',
'可用率':'Availability',
'性能率':'Performance',
'机架号':'Rack Number',
'最后保养':'Last Maintenance',
'异常停机分类统计':'Exceptional Stop Classification',
'次':'times',
'报警':'Alarm',
}
}

View File

@ -468,5 +468,23 @@ export default {
"本周":"本周",
"本月":"本月",
'故障':'故障',
'停机中':'停机中',
'运行中':'运行中',
'待机中':'待机中',
'故障中':'故障中',
'总产量':'总产量',
'设备转速':'设备转速',
'综合设备效率':'综合设备效率',
'实时报警':'实时报警',
'全部清除':'全部清除',
'忽略':'忽略',
'暂无报警':'暂无报警',
'可用率':'可用率',
'性能率':'性能率',
'机架号':'机架号',
'最后保养':'最后保养',
'异常停机分类统计':'异常停机分类统计',
'次':'次',
'报警':'报警',
}
}

View File

@ -116,17 +116,18 @@ onMounted(() => {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 12px;
.left-title {
margin-left: 10px;
font-size: 20px;
font-size: 16px;
color: #fff;
font-weight: bold;
}
.right-items {
height: 48px;
width: 60%;
width: 65%;
display: flex;
justify-content: flex-end;
align-items: center;

View File

@ -0,0 +1,98 @@
<template>
<div class="lb-container">
<div class="title">{{ tLang('message', '检测结果') }}</div>
<div class="content">
<BottomTable v-tableAutoScroll="{ delay: 30 }" :columns="prop.column" :tableData="prop.data.accessData">
<template #checkResult="scope">
<span v-if="scope.row.checkResult == 'NG'" style="color: red">{{ scope.row.checkResult }}</span>
<span v-else style="color: #17C27B;">{{ scope.row.checkResult }}</span>
</template>
</BottomTable>
</div>
<div class="ok-ng">
<div class="total">检测总数: {{ prop.data.total }}</div>
<div class="ok">OK总数: {{ prop.data.okNum }}</div>
<div class="ng">NG总数: {{ prop.data.ngNum }}</div>
</div>
</div>
</template>
<script setup>
import BottomTable from './bottomTable.vue'
const prop = defineProps({
column: {
type: Array,
default: () => {
return [
{
prop: 'name',
label: '名称',
width: '100px'
},
{
prop: 'value',
label: '值',
width: '100px'
}
]
}
},
data: {
type: Object,
default: () => {
return {
total: 0,
okNum: 0,
ngNum: 0,
accessData: []
}
}
}
})
</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);
}
.lb-container {
width: 100%;
height: 100%;
position: relative;
}
.ok-ng {
width: 70%;
height: 20px;
line-height: 20px;
position: absolute;
right: 0;
top: 0;
display: flex;
align-items: center;
div {
font-size: 12px;
margin-right: 15px;
}
.ok {
color: #17C27B;
}
.ng {
color: red;
}
}
</style>

View File

@ -0,0 +1,96 @@
<template>
<div class="lb-container">
<div class="title">{{ prop.title }}</div>
<div class="content">
<BottomTable v-tableAutoScroll="{ delay: 30 }" :columns="prop.column" :tableData="prop.data">
<template #workTime="scope">
{{ (scope.row.workTime / 60).toFixed(1) }} min
</template>
<template #totalTime="scope">
{{ (scope.row.totalTime / 60).toFixed(1) }} min
</template>
</BottomTable>
</div>
</div>
</template>
<script setup>
import BottomTable from './bottomTable.vue'
const prop = defineProps({
title: {
type: String,
default: ''
},
column: {
type: Array,
default: () => {
return [
{
prop: 'name',
label: '名称',
width: '100px'
},
{
prop: 'value',
label: '值',
width: '100px'
}
]
}
},
data: {
type: Object,
default: () => {
return []
}
}
})
</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);
}
.lb-container {
width: 100%;
height: 100%;
position: relative;
}
.ok-ng {
width: 70%;
height: 20px;
line-height: 20px;
position: absolute;
right: 0;
top: 0;
display: flex;
align-items: center;
div {
font-size: 12px;
margin-right: 15px;
}
.ok {
color: #17C27B;
}
.ng {
color: red;
}
}
</style>

View File

@ -40,6 +40,7 @@ let left_option = computed(() => {
series: [
{
type: 'gauge',
max:500,
axisLine: {
lineStyle: {
width: 10,

View File

@ -22,11 +22,14 @@
<Lcenter :totalElect="totalElect" :lineData="lineData"></Lcenter>
</div>
<div class="lb box-bg-color">
<Lbottom1 v-if="devStorage.devCode == codeList.cp" :column="columns" :data="cpData" :title="tableTitle"></Lbottom1>
<Lbottom2 v-else :column="columns" :data="bottomData" :title="tableTitle"></Lbottom2>
</div>
</div>
<div class="right">
<div class="rt box-bg-color">
<div class="title">{{ tLang('message', '报警维修记录') }}</div>
<div class="title">{{ tLang('message', '维修记录') }}</div>
<div class="content">
<BottomTable v-tableAutoScroll="{ delay: 15 }" :columns="repair_column" :tableData="repair_data">
</BottomTable>
@ -56,7 +59,9 @@ import StackBarChart from './components/stackBarChart.vue';
import Lcenter from './components/lcenter.vue';
import BottomTable from './components/bottomTable.vue';
import LineChart from './components/lineChart.vue';
import { checkRecord, deviceRepair, productionChartByDevice, deviceStatusChartByDevice,powerConsumptionTrend } from '@/api/pms/device'
import Lbottom1 from './components/lbottom1.vue';
import Lbottom2 from './components/lbottom2.vue';
import { checkRecord, deviceRepair, productionChartByDevice, deviceStatusChartByDevice, powerConsumptionTrend, getOKOrNGList, getSewingList,getScanList } from '@/api/pms/device'
const { proxy } = getCurrentInstance()
const route = useRoute()
let params = ref(route.params.timeFrame)
@ -64,23 +69,31 @@ let deviceStatusChartData = reactive({
xAxis: [],
series: []
})
let devStorage ={ "devCode": "33202006", "sn": "358284933"} //JSON.parse(localStorage.getItem('devStorage'))
let devStorage = { "devCode": "3051502", "sn": "358284933" } //JSON.parse(localStorage.getItem('devStorage'))
let codeList = {
cp: '3051903',//
pb: '3051502',//
ck: '33202006',//
fr: '334011' //
}
let repair_column = [
{ prop: 'devCode', label: '编码', width: '60px'},
{ prop: 'devCode', label: '编码', width: '60px' },
{ prop: 'name', label: '设备名称', },
{ prop: 'subject', label: '报警内容', },
{ prop: 'person', label: '负责人', width: '65px' },
{ prop: 'time', label: '报警时间', width: '80px'}
{ prop: 'time', label: '报警时间', width: '80px' }
]
let remind_column = [
{ prop: 'devCode', label: '编码', width: '60px'},
{ prop: 'devCode', label: '编码', width: '60px' },
{ prop: 'name', label: '设备名称', },
{ prop: 'subject', label: '保养内容', },
{ prop: 'person', label: '负责人', width: '65px' },
{ prop: 'time', label: '保养时间', width: '80px'}
{ prop: 'time', label: '保养时间', width: '80px' }
]
let tableTitle = ref('')
let columns = ref([])
let devTime = reactive({
workTime: 0,
waitTime: 0,
@ -125,7 +138,7 @@ function getCheckRecord() {
person: item.director,
time: item.deadline
}
})
})
})
}
@ -196,6 +209,49 @@ const getDeviceStatusChart = async () => {
})
}
let cpData = ref()
//
function reqOKOrNGList() {
getOKOrNGList({ devCode: devStorage.devCode, type: params.value }).then(res => {
columns.value = [
{ prop: 'productCode', label: '产品编码' },
{ prop: 'checkResult', label: '检查结果', slot: 'checkResult', width: '80px' },
{ prop: 'deviationValue', label: '偏差值' },
{ prop: 'ts', label: '检测时间' },
{ prop: 'checkNum', label: '检测数量' },
]
cpData.value = res.data
})
}
let bottomData = ref()
//
function reqSewingList() {
getSewingList({ devCode: devStorage.devCode, type: params.value }).then(res => {
bottomData.value = res.data
columns.value = [
{ prop: 'fileName', label: '花样名称' },
{ prop: 'patternCount', label: '针数'},
{ prop: 'workTime', label: '工作时长', slot: 'workTime' },
{ prop: 'total', label: '产量' },
]
})
}
//
function reqScanList() {
getScanList({ devCode: devStorage.devCode, type: params.value }).then(res => {
bottomData.value = res.data
columns.value = [
{ prop: 'fileName', label: '图片名称' },
{ prop: 'repeatOpen', label: '重新打开图片次数'},
{ prop: 'fileNameNew', label: '裁片名称'},
{ prop: 'cutNum', label: '识别数量'},
{ prop: 'totalTime', label: '总用时', slot: 'totalTime' },
{ prop: 'totalAlterNum', label: '修改次数' },
]
})
}
function init() {
@ -205,6 +261,16 @@ function init() {
getproductionChart()
getPowerConsumptionTrend()
if (devStorage.devCode == codeList.cp) {
reqOKOrNGList()
}
if (devStorage.devCode == codeList.fr|| devStorage.devCode == codeList.ck) {
reqSewingList()
}
if (devStorage.devCode == codeList.pb) {
reqScanList()
}
}
onMounted(() => {
init()
@ -288,7 +354,8 @@ onMounted(() => {
.status-name {
color: #999898;
}
span {
span {
text-align: left;
margin: 0 10px;
}

View File

@ -13,7 +13,7 @@
<script setup>
import { computed } from 'vue';
const {proxy} = getCurrentInstance();
let prop = defineProps({
data: {
type: Object,
@ -25,9 +25,9 @@ let prop = defineProps({
let infoList = computed(() => {
return [
{name: '设备名称', value: prop.data.name},
{name: '机架号', value: prop.data.devCode},
{name: '最后保养', value: prop.data.checkTime},
{name: proxy.tLang('device','设备名称'), value: prop.data.name},
{name: proxy.tLang('message','机架号'), value: prop.data.devCode},
{name: proxy.tLang('message','最后保养'), value: prop.data.checkTime},
]
})
</script>

View File

@ -2,25 +2,20 @@
<div class="imagecard-container">
<div class="title">{{ tLang('message', '设备视图') }}</div>
<div class="content">
<el-image style="width: 80%; height: 80%;max-width: 80%;max-height: 80%;" :src="fileUrl + props.bgimage"
<el-image style="width: 80%; height: 80%;max-width: 80%;max-height: 80%;" :src="fileUrl + props.data.file"
fit="contain">
</el-image>
<div class="data" v-if="props.isRate">
<div class="data-item" v-for="(item, index) in data" :key="index">{{ item.name }}{{ item.value }}</div>
<div class="data-item" v-for="(item, index) in list" :key="index">{{ item.name }}{{ item.value }}</div>
</div>
</div>
</div>
</template>
<script setup>
import bgimage from '@/assets/images/login-background.jpg'
let fileUrl = import.meta.env.VITE_APP_BASE_API
const props = defineProps({
bgimage: {
type: String,
default: ''
},
isRate: {
type: Boolean,
default: false
@ -28,18 +23,19 @@ const props = defineProps({
data: {
type: Object,
default: () => {
return [
{ name: '当前花版名称', value: 'A' },
{ name: '冲孔进度', value: '90%' },
]
return {
file: '',
schedule:'0',
fileName:''
}
}
}
})
let list = computed(() => {
return [
{ name: '当前花版名称', value: 'A' },
{ name: '冲孔进度', value: '90%' },
{ name: '花版名称', value: props.data.fileName },
{ name: '进度', value: props.data.schedule + '%' },
]
})
</script>

View File

@ -3,29 +3,30 @@
<div class="title">{{ tLang('message', '异常停机分类统计') }}</div>
<div class="content">
<div class="left-panel">
<v-chart :option="options" theme="dark" style="width: 100%;height: 100%;" />
<v-chart autoresize :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>
<span class="text1">{{ tLang('message','实时报警') }}<el-badge :show-zero="false" :value="props.errorList.length" class="item"><el-icon :size="20"><BellFilled /></el-icon></el-badge></span>
<span class="text2" @click="ignoreError({})">{{ tLang('message','全部清除') }}</span>
</div>
<div class="right-content">
<div class="card-item">
<div class="card-item" v-for="(item,index) of props.errorList" :key="item.key">
<div class="message-mine">
<div class="message-title">主轴旋转异常请检查机械部件</div>
<div class="message-title">{{ item.msg }}</div>
<div class="message-desc">
<span>{{ tLang('message', '机架号') }}: </span>
<span>SWM5015</span>
<span>2025-04-16 13:20:18</span>
<span>{{ item.devCode }}</span>
<span>{{ item.ts }}</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>
<el-button color="#e7e7e7" size="small" @click="ignoreError(item)">{{ tLang('message','忽略') }}</el-button>
</div>
</div>
<div v-if="props.errorList == 0" style="width: 100%;height: 100%;display: flex;justify-content: center;align-items: center;color: #65656D;">{{ tLang('message','暂无报警') }}</div>
</div>
</div>
</div>
@ -33,9 +34,28 @@
</template>
<script setup>
import { formatter } from 'element-plus';
const props = defineProps({
abnormalData: {
type: Object,
default: () => {
return {
alarm: 0,
check: 0,
repair: 0
}
}
},
errorList: {
type: Array,
default: () => {
return []
}
}
})
const emit = defineEmits(['ignoreError'])
const { proxy } = getCurrentInstance();
let options = computed(() => {
return {
@ -55,7 +75,7 @@ let options = computed(() => {
},
label: {
formatter:(params)=>{
return params.name + params.value + '次'
return params.name+ ' ' + params.value+ ' ' + proxy.tLang('message', '次')
}
},
// emphasis: {
@ -66,14 +86,19 @@ let options = computed(() => {
// }
// },
data: [
{ value: 1, name: proxy.tLang('home', '维修') },
{ value: 2, name: proxy.tLang('pms', '保养') },
{ value: 3, name: proxy.tLang('message', '故障') },
{ value: props.abnormalData.repair, name: proxy.tLang('home', '维修') },
{ value: props.abnormalData.check, name: proxy.tLang('pms', '保养') },
{ value: props.abnormalData.alarm, name: proxy.tLang('message', '报警') },
]
}
]
}
})
function ignoreError(item) {
emit('ignoreError',item)
}
</script>
<style lang="scss" scoped>
@ -151,15 +176,15 @@ let options = computed(() => {
.right-content {
width: 100%;
height: calc(100% - 40px);
display: flex;
flex-direction: column;
justify-content: flex-start;
overflow: auto;
/* 隐藏Y轴滚动条 */
scrollbar-width: none;
.card-item {
width: 95%;
height: 50px;
box-sizing: border-box;
border-left: #DC2626 4px solid;
margin-bottom: 6px;
background-color: #2D2023;
display: flex;
justify-content: space-between;

View File

@ -1,7 +1,7 @@
<template>
<div class="lc-container">
<div class="left-panel box-bg-color">
<div class="title">{{ tLang('message', 'OEE综合设备效率') }}</div>
<div class="title">OEE {{ tLang('message', '综合设备效率') }}</div>
<div class="content">
<div class="oee-chart">
<v-chart autoresize :option="oeeOption" theme="dark" style="width: 100%;height: 100%;" />
@ -9,56 +9,63 @@
<div class="progress">
<div class="progress-item">
<div class="progress-title">
<span>{{ tLang('message', '可用率') }}</span>
<span class="progress-value">{{ 70 }}%</span>
<span>{{ tLang('message', '可用率') }}: </span>
<span class="progress-value">{{ props.oeeData.availability }}%</span>
</div>
<div class="progress-bar">
<el-progress :percentage="70" status="warning" :stroke-width="16" :show-text="false" />
<el-progress :percentage="props.oeeData.availability" status="warning" :stroke-width="16" :show-text="false" />
</div>
<div class="progress-desc">
<!-- <div class="progress-desc">
<span>计划停机{{ '45分钟' }}</span>
<span>故障停机{{ '1小时' }}</span>
</div>
</div> -->
</div>
<div class="progress-item">
<div class="progress-title">
<span>{{ tLang('message', '性能率') }}</span>
<span class="progress-value">{{ 70 }}%</span>
<span>{{ tLang('message', '性能率') }}:</span>
<span class="progress-value">{{ props.oeeData.performanceRate }}%</span>
</div>
<div class="progress-bar">
<el-progress :percentage="70" status="success" :stroke-width="16" :show-text="false" />
<el-progress :percentage="props.oeeData.performanceRate" status="success" :stroke-width="16" :show-text="false" />
</div>
<div class="progress-desc">
<!-- <div class="progress-desc">
<span>计划停机{{ '45分钟' }}</span>
<span>故障停机{{ '1小时' }}</span>
</div>
</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">
<span class="text1">{{ tLang('message', '实时报警') }}<el-badge :show-zero="false"
:value="props.errorList.length" class="item"><el-icon :size="20">
<BellFilled />
</el-icon></el-badge></span>
<span class="text2">{{ tLang('message', '全部清除') }}</span>
<span class="text2" @click="ignoreError({})">{{ 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 class="card-box">
<div class="card-item" v-for="(item, index) of props.errorList" :key="item.key">
<div class="message-mine">
<div class="message-title">{{ item.msg }}</div>
<div class="message-desc">
<span>{{ tLang('message', '机架号') }}: </span>
<span>{{ item.devCode }}</span>
<span>{{ item.ts }}</span>
</div>
</div>
<div class="option">
<!-- <el-button color="#DC2626" size="small">{{ tLang('message','处理') }}</el-button> -->
<el-button color="#e7e7e7" size="small" @click="ignoreError(item)">{{ tLang('message', '忽略')
}}</el-button>
</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 v-if="props.errorList == 0"
style="width: 100%;height: 50px;display: flex;justify-content: center;align-items: center;color: #65656D;">
{{ tLang('message','暂无报警') }}</div>
</div>
<div class="error-chart">
@ -70,8 +77,39 @@
</template>
<script setup>
const props = defineProps({
oeeData:{
type: Object,
default: () => {
return {
}
}
},
abnormalData: {
type: Object,
default: () => {
return {
alarm: 0,
check: 0,
repair: 0
}
}
},
errorList: {
type: Array,
default: () => {
return []
}
}
})
const { proxy } = getCurrentInstance();
const emit = defineEmits(['ignoreError'])
function ignoreError(item) {
emit('ignoreError',item)
}
let options = computed(() => {
return {
title: {
@ -83,11 +121,6 @@ let options = computed(() => {
tooltip: {
trigger: 'item'
},
legend: {
top: '15%',
orient: 'vertical',
left: 'left'
},
backgroundColor: 'transparent',
series: [
{
@ -100,8 +133,9 @@ let options = computed(() => {
borderRadius: 10
},
label: {
show: false,
position: 'center'
formatter: (params) => {
return params.name + ' ' +params.value+ ' ' + proxy.tLang('message','次')
}
},
// emphasis: {
// label: {
@ -110,13 +144,10 @@ let options = computed(() => {
// fontWeight: 'bold'
// }
// },
labelLine: {
show: false
},
data: [
{ value: 1048, name: proxy.tLang('home', '维修') },
{ value: 735, name: proxy.tLang('pms', '保养') },
{ value: 580, name: proxy.tLang('message', '故障') },
{ value: props.abnormalData.repair, name: proxy.tLang('home', '维修') },
{ value: props.abnormalData.check, name: proxy.tLang('pms', '保养') },
{ value: props.abnormalData.alarm, name: proxy.tLang('message', '报警') },
]
}
]
@ -134,7 +165,7 @@ let oeeOption = computed(() => {
center: ['50%', '75%'],
radius: '90%',
min: 0,
max: 1,
max: 100,
axisLine: {
lineStyle: {
width: 2,
@ -171,9 +202,6 @@ let oeeOption = computed(() => {
color: '#f7f7f7',
distance: 3,
fontSize: 12,
formatter: function (value) {
return value * 100;
}
},
title: {
offsetCenter: [0, '-10%'],
@ -184,13 +212,13 @@ let oeeOption = computed(() => {
offsetCenter: [0, '-35%'],
valueAnimation: true,
formatter: function (value) {
return Math.round(value * 100) + '%';
return value + '%';
},
color: 'inherit'
},
data: [
{
value: 0.7,
value: props.oeeData.performanceRate,
name: 'OEE'
}
]
@ -330,49 +358,59 @@ let oeeOption = computed(() => {
justify-content: space-between;
overflow: hidden;
.card-item {
.card-box {
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;
margin-bottom: 5px;
.message-mine {
width: 65%;
height: 100%;
padding-left: 5px;
scrollbar-width: none;
overflow: auto;
.card-item {
width: 100%;
height: 50px;
box-sizing: border-box;
border-left: #DC2626 4px solid;
background-color: #2D2023;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: flex-start;
justify-content: space-between;
align-items: center;
margin-bottom: 5px;
.message-title {
font-size: 12px;
color: #fff;
}
.message-mine {
width: 65%;
height: 100%;
padding-left: 5px;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: flex-start;
.message-desc {
font-size: 10px;
color: #999898;
.message-title {
font-size: 12px;
color: #fff;
}
span {
margin-right: 10px;
.message-desc {
font-size: 10px;
color: #999898;
span {
margin-right: 10px;
}
}
}
.option {
width: 35%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
.option {
width: 35%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
.error-chart {
width: 100%;
height: calc(100% - 55px);

View File

@ -20,7 +20,7 @@
</div>
</div>
<div class="top-item">
<div class="title">{{ tLang('message', '运行时长') }}</div>
<div class="title">{{ tLang('device', '运行时长') }}</div>
<div class="content">
{{ props.data.runTime }} min
</div>

View File

@ -3,7 +3,7 @@
<div class="left">
<div class="left-content">
<div class="speed-box">
<div class="speed-value">250rpm</div>
<div class="speed-value"> {{props.data.speed}} rpm</div>
</div>
<div class="speed-title">{{ tLang('message', '扫描速度') }}</div>
</div>
@ -41,11 +41,11 @@ let devData = computed(() => {
return {
status: { 'label': proxy.tLang('home', '设备状态'), 'value': props.data.state, type: 'status' },
scansNum: { 'label': proxy.tLang('message', '扫描次数'), 'value': props.data.outputToday, type: '' },
runTime: { 'label': proxy.tLang('message', '运行时长'), 'value': props.data.runTime + ' min', type: '' },
runTime: { 'label': proxy.tLang('device', '运行时长'), 'value': props.data.runTime + ' min', type: '' },
consumption: { 'label': proxy.tLang('message', '耗电量'), 'value': props.data.electTotal + ' kW·h', type: '' },
identifyState: { 'label': proxy.tLang('message', '识别状态'), 'value': '0', type: 'status' },
identifyState: { 'label': proxy.tLang('message', '识别状态'), 'value': props.data.visionState, type: 'status' },
identifyNum: { 'label': proxy.tLang('message', '识别数量'), 'value': props.data.cutNum, type: '' },
identifyTime: { 'label': proxy.tLang('message', '总识别时长'), 'value': '00:34:22', type: '' },
identifyTime: { 'label': proxy.tLang('message', '总识别时长'), 'value': props.data.totalTime + ' min', type: '' },
ErrorNum: { 'label': proxy.tLang('message', '异常次数'), 'value': props.data.errorCount, type: '' },
}
})

View File

@ -40,7 +40,7 @@ const { proxy } = getCurrentInstance();
let devData = computed(() => {
return [
{ 'label': proxy.tLang('home', '设备状态'), 'value': props.data.state, type: 'status' },
{ 'label': proxy.tLang('message', '运行时长'), 'value': props.data.runTime + ' min', type: '' },
{ 'label': proxy.tLang('device', '运行时长'), 'value': props.data.runTime + ' min', type: '' },
{ 'label': proxy.tLang('message', '总产量'), 'value': props.data.outputToday, type: '' },
]
})

View File

@ -43,8 +43,9 @@ let rate = reactive({
})
let options = computed(() => {
let total = props.data.ok + props.data.ng
rate.okRate = ((props.data.ok / total) * 100).toFixed(1)
rate.ngRate = 100 - rate.okRate
rate.okRate = total == 0 ? 0 :((props.data.ok / total) * 100).toFixed(1)
rate.ngRate = total == 0 ? 0 :100 - rate.okRate
rate.total = total
return {
tooltip: {

View File

@ -7,8 +7,9 @@
<Ltop3 v-else :data="info"></Ltop3>
</div>
<div class="lc">
<Lcenter1 v-if="devCode == codeList.cp || devCode == codeList.pb"></Lcenter1>
<Lcenter2 v-else></Lcenter2>
<Lcenter1 v-if="devCode == codeList.cp || devCode == codeList.pb" :abnormalData="abnormalData"
:errorList="errorList" @ignoreError="ignoreError"></Lcenter1>
<Lcenter2 v-else :oeeData="oeeData" :abnormalData="abnormalData" :errorList="errorList" @ignoreError="ignoreError"></Lcenter2>
</div>
<div class="lb box-bg-color">
<bottomTable title="检测结果" v-if="devCode == codeList.cp" :columns="columns" :table-data="tableData">
@ -18,13 +19,21 @@
</template>
</bottomTable>
<bottomTable title="识别记录" v-else-if="devCode == codeList.pb" :columns="columns" :table-data="tableData">
<template #totalTime="scope">
{{ (scope.row.totalTime/60).toFixed(1) }} min
</template>
</bottomTable>
<bottomTable title="工作记录" v-else :columns="columns" :table-data="tableData">
<template #workTime="scope">
{{ (scope.row.workTime/60).toFixed(1) }} min
</template>
</bottomTable>
<bottomTable title="工作记录" v-else :columns="columns" :table-data="tableData"></bottomTable>
</div>
</div>
<div class="right">
<div class="rt box-bg-color">
<imageCard :bgimage="info.file" :isRate="is_rate"></imageCard>
<imageCard :data="info" :isRate="is_rate"></imageCard>
</div>
<div class="rc box-bg-color">
<devInfo :data="info"></devInfo>
@ -48,10 +57,11 @@ import bottomTable from './components/bottomTable.vue'
import imageCard from './components/imageCard.vue'
import devInfo from './components/devInfo.vue'
import Rbottom1 from './components/rbottom1.vue'
import { device, deviceCheck, getOKOrNGList } from '@/api/pms/device'
import { computed, reactive } from 'vue'
import { connectWebsocket, closeWebsocket } from "@/utils/websocket";
import { device, deviceCheck, getOKOrNGList, abnormalShutdown, getSewingList,oee,getScanList } from '@/api/pms/device'
import { computed, onUnmounted, reactive, ref } from 'vue'
let devCode = ref('3051903')
let devCode = ref('3051502')
let codeList = {
cp: '3051903',//
pb: '3051502',//
@ -59,15 +69,10 @@ let codeList = {
fr: '334011' //
}
let is_rate = ref(false)
const columns = [
// { type: 'selection' },
// { type: 'index', label: '' },
{ prop: 'productCode', label: '产品编码' },
{ prop: 'checkResult', label: '检查结果', slot: 'checkResult', width: '80px' },
{ prop: 'deviationValue', label: '偏差值' },
{ prop: 'ts', label: '检测时间' },
{ prop: 'checkNum', label: '检测数量' },
]
const columns = ref([])
let remind_column = [
{ prop: 'devCode', label: '编码', width: '60px' },
{ prop: 'name', label: '设备名称', },
@ -81,6 +86,7 @@ let tableData = ref([
{ code: '123456789', status: '正常', offset: '0.00', date: '2021-01-01', num: '100' }
])
let errorList = ref([])
let info = reactive({
name: '',
@ -95,7 +101,11 @@ let info = reactive({
speed: 0,
output: 0,
outputToday: 0,
cutNum: 0
cutNum: 0,
fileName:'',
schedule: 0,
totalTime: 0,
visionState:0
})
//
function getDevice() {
@ -112,31 +122,71 @@ function getDevice() {
info.output = res.data.output
info.outputToday = res.data.outputToday
info.cutNum = res.data.cutNum || 0
info.totalTime = res.data.totalTime ||0
info.visionState = res.data.state
})
}
let reqOKOrNGCount = computed(() => {
let ok = 0
let ng = 0
tableData.value.forEach(item => {
if (item.checkResult == 'OK') {
ok++
} else {
ng++
}
})
return {
ok,ng
}
let reqOKOrNGCount = reactive({
ok: 0,
ng: 0
})
//
function reqOKOrNGList() {
getOKOrNGList({ devCode: devCode.value }).then(res => {
getOKOrNGList({ devCode: devCode.value, type: 'd' }).then(res => {
columns.value = [
{ prop: 'productCode', label: '产品编码' },
{ prop: 'checkResult', label: '检查结果', slot: 'checkResult', width: '80px' },
{ prop: 'deviationValue', label: '偏差值' },
{ prop: 'ts', label: '检测时间' },
{ prop: 'checkNum', label: '检测数量' },
]
tableData.value = res.data.accessData
reqOKOrNGCount.ok = res.data.okNum
reqOKOrNGCount.ng = res.data.ngNum
})
}
//
function reqSewingList() {
getSewingList({ devCode: devCode.value, type: 'd' }).then(res => {
tableData.value = res.data
columns.value = [
{ prop: 'fileName', label: '花样名称' },
{ prop: 'patternCount', label: '针数'},
{ prop: 'workTime', label: '工作时长', slot: 'workTime' },
{ prop: 'total', label: '产量' },
]
})
}
//
function reqScanList() {
getScanList({ devCode: devCode.value, type: 'd' }).then(res => {
tableData.value = res.data
columns.value = [
{ prop: 'fileName', label: '图片名称' },
{ prop: 'repeatOpen', label: '重新打开图片次数'},
{ prop: 'fileNameNew', label: '裁片名称'},
{ prop: 'cutNum', label: '识别数量'},
{ prop: 'totalTime', label: '总用时', slot: 'totalTime' },
{ prop: 'totalAlterNum', label: '修改次数' },
]
})
}
let abnormalData = ref()
//
function getAbnormalShutdown() {
abnormalShutdown({ devCode: devCode.value }).then(res => {
abnormalData.value = res.data
})
}
@ -150,12 +200,87 @@ function getDeviceCheck() {
})
}
//
function ignoreError(item) {
//item
if (Object.keys(item).length == 0) {
errorList.value = []
} else {
errorList.value = errorList.value.filter(v => v.key != item.key)
}
}
let oeeData = ref({})
//OEE
function getOEE() {
oee({devCode: devCode.value}).then(res=>{
oeeData.value = res.data
})
}
//socket
function getWebsocket(val) {
try {
let data = JSON.parse(val);
if (data.type == "status" && data.msg.devCode == devCode.value) {
info.state = data.msg.status
if (data.msg.status == 0 ) {
info.visionState = 0
}
}
if (data.type == "visionState" && data.msg.devCode == devCode.value) {
info.visionState = data.msg.visionState
}
if (data.type == "speed" && data.msg.devCode == devCode.value) {
info.speed = data.msg.speed
}
if (data.type == "schedule" && data.msg.devCode == devCode.value) {
info.schedule = data.msg.schedule
info.fileName = data.msg.fileName
}
if (data.type == "errorCode" && data.msg.devCode == devCode.value) {
//
let key = Math.random().toString(36).substring(2);
errorList.value.push({
key: key,
msg: data.msg.errorMsg,
devCode: data.msg.devCode,
ts: data.msg.ts
})
abnormalData.value.alarm++
}
} catch (err) {
console.log(err);
}
}
function errWebsocket(val) {
// headerref.value.HeadererrWebsocket(val)
// console.log(val);
}
function init() {
getDevice()
getDeviceCheck()
getAbnormalShutdown()
if (devCode.value == codeList.cp) {
reqOKOrNGList()
}
if (devCode.value == codeList.fr|| devCode.value == codeList.ck) {
reqSewingList()
getOEE()
}
if (devCode.value == codeList.pb) {
reqScanList()
}
}
onMounted(() => {
@ -169,6 +294,11 @@ onMounted(() => {
} else {
is_rate.value = false
}
connectWebsocket('', '', getWebsocket, errWebsocket)
})
onUnmounted(() => {
closeWebsocket()
})
</script>