生产监控看板
This commit is contained in:
parent
2c1e1845f4
commit
446fa9a0d1
@ -21,6 +21,7 @@ import {
|
||||
handleTree,
|
||||
addBeginAndEndTime,
|
||||
divide,
|
||||
formatThousands
|
||||
} from '@/utils/ruoyi';
|
||||
import Pagination from '@/components/Pagination';
|
||||
// 自定义表格工具扩展
|
||||
@ -45,6 +46,7 @@ Vue.prototype.resetForm = resetForm;
|
||||
Vue.prototype.getDictDatas = getDictDatas;
|
||||
Vue.prototype.getDictDatas2 = getDictDatas2;
|
||||
Vue.prototype.getDictDataLabel = getDictDataLabel;
|
||||
Vue.prototype.formatThousands = formatThousands;
|
||||
Vue.prototype.DICT_TYPE = DICT_TYPE;
|
||||
Vue.prototype.handleTree = handleTree;
|
||||
Vue.prototype.addBeginAndEndTime = addBeginAndEndTime;
|
||||
|
@ -295,3 +295,15 @@ export function getPath(path) {
|
||||
}
|
||||
return Math.floor(divisor/dividend*100)/100;
|
||||
}
|
||||
|
||||
// 通用千分位格式化函数
|
||||
export function formatThousands(value) {
|
||||
if (value === null || value === undefined) return '0'
|
||||
|
||||
// 清理已有逗号并转为数字
|
||||
const numValue = Number(String(value).replace(/,/g, ''))
|
||||
if (isNaN(numValue)) return '0'
|
||||
|
||||
// 支持小数处理
|
||||
return numValue.toLocaleString('en-US')
|
||||
}
|
@ -7,18 +7,20 @@
|
||||
<div class='dataBox' style='top:50px'>
|
||||
<p>
|
||||
<span class='text'>总投入片数</span>
|
||||
<span class='precent precentG'>-18%</span>
|
||||
<img src="../../../../assets/images/dataBoard/arrDown.png" alt="" width='5' height='15'>
|
||||
<span class='precent' :class='{precentR:monthData?.inputNumChange>=0,precentG:monthData?.inputNumChange<0}'>{{monthData?.inputNumChange || '-'}}%</span>
|
||||
<img v-show='monthData?.inputNumChange<0' src="../../../../assets/images/dataBoard/arrDown.png" alt="" width='5' height='15'>
|
||||
<img v-show='monthData?.inputNumChange>=0' src="../../../../assets/images/dataBoard/arrUp.png" alt="" width='5' height='15'>
|
||||
</p>
|
||||
<p class='num'>261,938,984</p>
|
||||
<p class='num'>{{monthData?.inputNum ? formatThousands(monthData.inputNum) : '-'}}</p>
|
||||
</div>
|
||||
<div class='dataBox'style='top:180px'>
|
||||
<p>
|
||||
<span class='text'>总生产片数</span>
|
||||
<span class='precent precentR'>+18%</span>
|
||||
<img src="../../../../assets/images/dataBoard/arrUp.png" alt="" width='5' height='15'>
|
||||
<span class='precent' :class='{precentR:monthData?.outputNumChange>=0,precentG:monthData?.outputNumChange<0}'>{{monthData?.outputNumChange || '-'}}%</span>
|
||||
<img v-show='monthData?.outputNumChange<0' src="../../../../assets/images/dataBoard/arrDown.png" alt="" width='5' height='15'>
|
||||
<img v-show='monthData?.outputNumChange>=0' src="../../../../assets/images/dataBoard/arrUp.png" alt="" width='5' height='15'>
|
||||
</p>
|
||||
<p class='num'>82,261,938,984</p>
|
||||
<p class='num'>{{monthData?.outputNum ? formatThousands(monthData.outputNum) : '-'}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -26,8 +28,25 @@
|
||||
<script>
|
||||
export default {
|
||||
name: 'CenterBottomL',
|
||||
props: {
|
||||
dataObj: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
dataObj(val) {
|
||||
val.monthAndLastMonth && val.monthAndLastMonth.forEach(item => {
|
||||
if (item.dataType === "本月") {
|
||||
this.monthData = item
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
return {
|
||||
monthData:{}
|
||||
}
|
||||
},
|
||||
methods: {}
|
||||
}
|
||||
|
@ -8,13 +8,13 @@
|
||||
<p>
|
||||
<span class='text'>总投入片数</span>
|
||||
</p>
|
||||
<p class='num'>261,938,984</p>
|
||||
<p class='num'>{{lastMonthData?.inputNum ? formatThousands(lastMonthData.inputNum) : '-'}}</p>
|
||||
</div>
|
||||
<div class='dataBox'style='top:180px'>
|
||||
<p>
|
||||
<span class='text'>总生产片数</span>
|
||||
</p>
|
||||
<p class='num'>82,261,938,984</p>
|
||||
<p class='num'>{{lastMonthData?.outputNum ? formatThousands(lastMonthData.outputNum) : '-'}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -22,8 +22,25 @@
|
||||
<script>
|
||||
export default {
|
||||
name: 'CenterBottomR',
|
||||
props: {
|
||||
dataObj: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
dataObj(val) {
|
||||
val.monthAndLastMonth && val.monthAndLastMonth.forEach(item => {
|
||||
if (item.dataType === "上月") {
|
||||
this.lastMonthData = item
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
return {
|
||||
lastMonthData:{}
|
||||
}
|
||||
},
|
||||
methods: {}
|
||||
}
|
||||
|
@ -10,8 +10,20 @@
|
||||
<p><span class='eqTipTitle'>设备名称:</span><span class='eqTipNum'>{{eqTipMsg.name}}</span></p>
|
||||
<p><span class='eqTipTitle'>进口数量:</span><span class='eqTipNum'>{{eqTipMsg.input}}</span></p>
|
||||
<p><span class='eqTipTitle'>出口数量:</span><span class='eqTipNum'>{{eqTipMsg.output}}</span></p>
|
||||
<p><span class='eqTipTitle'>报警状态:</span><span class='eqTipNum'><img :src='dotY' width='16'/>{{eqTipMsg.alarm}}</span></p>
|
||||
<p><span class='eqTipTitle'>在线状态:</span><span class='eqTipNum'><img :src='dotR' width='16'/>{{eqTipMsg.status}}</span></p>
|
||||
<p><span class='eqTipTitle'>报警状态:</span>
|
||||
<span class='eqTipNum'>
|
||||
<img v-show='eqTipMsg.alarm' :src='dotY' width='16'/>
|
||||
<img v-show='!eqTipMsg.alarm' :src='dotG' width='16'/>
|
||||
{{eqTipMsg.alarm?'报警':'未报警'}}
|
||||
</span>
|
||||
</p>
|
||||
<p><span class='eqTipTitle'>在线状态:</span>
|
||||
<span class='eqTipNum'>
|
||||
<img v-show='eqTipMsg.status' :src='dotG' width='16'/>
|
||||
<img v-show='!eqTipMsg.status' :src='dotR' width='16'/>
|
||||
{{eqTipMsg.status?'在线':'离线'}}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<!-- 设备 -->
|
||||
<div class='eqBox'>
|
||||
@ -28,22 +40,22 @@
|
||||
<div class='centerTopTopBox'>
|
||||
<div style='display: inline-block;'>
|
||||
<img src="../../../../assets/images/dataBoard/centerNumB.png" alt="" width='203'>
|
||||
<p class='num'>88%</p>
|
||||
<p class='num'>{{dataObj?.productRate || '-'}}%</p>
|
||||
<p class='title'>成品率</p>
|
||||
</div>
|
||||
<div style='display: inline-block;'>
|
||||
<img src="../../../../assets/images/dataBoard/centerNumY.png" alt="" width='261'>
|
||||
<p class='num' style='width: 260px;padding-left: 20px;'>8,984</p>
|
||||
<p class='num' style='width: 260px;padding-left: 20px;'>{{dataObj?.todayProduct ? formatThousands(dataObj.todayProduct) : '-'}}</p>
|
||||
<p class='title' style='color:#FFB625'>今日产量</p>
|
||||
</div>
|
||||
<div style='display: inline-block;'>
|
||||
<img src="../../../../assets/images/dataBoard/centerNumY.png" alt="" width='261'>
|
||||
<p class='num' style='width: 260px;padding-left: 20px;'>12,948,984</p>
|
||||
<p class='num' style='width: 260px;padding-left: 20px;'>{{dataObj?.monthProduct ? formatThousands(dataObj.monthProduct) : '-'}}</p>
|
||||
<p class='title' style='color:#FFB625'>本月产量</p>
|
||||
</div>
|
||||
<div style='display: inline-block;'>
|
||||
<img src="../../../../assets/images/dataBoard/centerNumB.png" alt="" width='203'>
|
||||
<p class='num'>59</p>
|
||||
<p class='num'>{{dataObj?.alarmNum ? formatThousands(dataObj.alarmNum) : '-'}}</p>
|
||||
<p class='title'>设备报警数</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -59,7 +71,6 @@ export default {
|
||||
left: 0,
|
||||
top: 0
|
||||
},
|
||||
scaleNum:1,
|
||||
dotY:require('../../../../assets/images/dataBoard/dotY.png'),
|
||||
dotR:require('../../../../assets/images/dataBoard/dotR.png'),
|
||||
dotG:require('../../../../assets/images/dataBoard/dotG.png'),
|
||||
@ -192,11 +203,29 @@ export default {
|
||||
scaleNum: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
dataObj: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
scaleNum(val) {
|
||||
this.scaleNum = val
|
||||
},
|
||||
dataObj(val) {
|
||||
val.equipmentDets && val.equipmentDets.forEach(item => {
|
||||
this.eqList.forEach(eq => {
|
||||
if (eq.id == item.id) {
|
||||
eq.name = item.name
|
||||
eq.input = item.input
|
||||
eq.output = item.output
|
||||
eq.alarm = item.isError
|
||||
eq.status = item.isRun
|
||||
}
|
||||
})
|
||||
})
|
||||
console.log(this.eqList)
|
||||
}
|
||||
},
|
||||
mounted() {},
|
||||
@ -205,10 +234,10 @@ export default {
|
||||
handleMouseEnter(item, event) {
|
||||
this.showTooltip = true;
|
||||
this.eqTipMsg.name = item.name;
|
||||
// this.eqTipMsg.input = item.input;
|
||||
// this.eqTipMsg.output = item.output;
|
||||
// this.eqTipMsg.alarm = item.alarm;
|
||||
// this.eqTipMsg.status = item.status;
|
||||
this.eqTipMsg.input = item.input;
|
||||
this.eqTipMsg.output = item.output;
|
||||
this.eqTipMsg.alarm = item.alarm;
|
||||
this.eqTipMsg.status = item.status;
|
||||
this.updateTooltipPosition(event);
|
||||
},
|
||||
handleMouseLeave() {
|
||||
@ -288,7 +317,7 @@ p{
|
||||
.eqBox {
|
||||
span{
|
||||
display: inline-block;
|
||||
border: 1px solid red;
|
||||
// border: 1px solid red;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<header class="dataBoardHeader">
|
||||
<div class='topTitle'></div>
|
||||
<div class='time-chsoose'>
|
||||
<!-- <div class='time-chsoose'>
|
||||
<span class='title'>时间选择</span>
|
||||
<span class='time-show'>{{time}}</span>
|
||||
<el-date-picker
|
||||
@ -12,7 +12,7 @@
|
||||
style='position: absolute;right: 0px;width: 119px;top:-2px;opacity: 0;'
|
||||
>
|
||||
</el-date-picker>
|
||||
</div>
|
||||
</div> -->
|
||||
<div
|
||||
type="text"
|
||||
class="screen-btn"
|
||||
@ -26,7 +26,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment'
|
||||
// import moment from 'moment'
|
||||
export default {
|
||||
name: 'DataBoardHeader',
|
||||
props: {
|
||||
@ -39,7 +39,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
time: moment().format('YYYY-MM-DD')
|
||||
// time: moment().format('YYYY-MM-DD')
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
|
@ -4,28 +4,64 @@
|
||||
<svg-icon icon-class="dataBoard2" class='icon'/>
|
||||
<span>投入产出及良品率</span>
|
||||
</div>
|
||||
<div class="top_legend">
|
||||
<span class="chart_legend_icon1">投入</span>
|
||||
<span class="chart_legend_icon2">产出</span>
|
||||
<span><span class="chart_legend_icon3"></span>良品率</span>
|
||||
<div v-if='xData.length === 0' class='noData'>暂无数据</div>
|
||||
<div v-else>
|
||||
<div class="top_legend">
|
||||
<span class="chart_legend_icon1">投入</span>
|
||||
<span class="chart_legend_icon2">产出</span>
|
||||
<span><span class="chart_legend_icon3"></span>良品率</span>
|
||||
</div>
|
||||
<div id='inOutputChart' style='width: 400px;height: 290px;'></div>
|
||||
</div>
|
||||
<div id='inOutputChart' style='width: 400px;height: 290px;'></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import * as echarts from 'echarts';
|
||||
export default {
|
||||
name: 'LeftBottom',
|
||||
props: {
|
||||
dataObj: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
dataObj(val) {
|
||||
this.xData = []
|
||||
this.inputData = []
|
||||
this.outputData = []
|
||||
this.goodRateData = []
|
||||
val.monthBar && val.monthBar.forEach(item => {
|
||||
this.xData.push(item.dataType)
|
||||
this.inputData.push(item.inputNum)
|
||||
this.outputData.push(item.outputNum)
|
||||
this.goodRateData.push(item.goodRate)
|
||||
})
|
||||
this.initChart();
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
mounted() {
|
||||
this.initChart();
|
||||
return {
|
||||
chartDom: '',
|
||||
chart: '',
|
||||
xData:[],
|
||||
inputData:[],
|
||||
outputData:[],
|
||||
goodRateData:[],
|
||||
}
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
initChart() {
|
||||
var chartDom = document.getElementById('inOutputChart');
|
||||
var myChart = echarts.init(chartDom);
|
||||
if (
|
||||
this.chart !== null &&
|
||||
this.chart !== '' &&
|
||||
this.chart !== undefined
|
||||
) {
|
||||
this.chart.dispose() // 页面多次刷新会出现警告,Dom已经初始化了一个实例,这是销毁实例
|
||||
}
|
||||
this.chartDom = document.getElementById('inOutputChart')
|
||||
this.chart = echarts.init(this.chartDom)
|
||||
var option;
|
||||
option = {
|
||||
grid: { top: 40, right: 10, bottom: 5, left: 10, containLabel: true },
|
||||
@ -34,12 +70,12 @@ export default {
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
|
||||
data: this.xData,
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
fontSize: 10,
|
||||
interval: 0,
|
||||
rotate:20
|
||||
rotate:30
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLine: {
|
||||
@ -110,7 +146,7 @@ export default {
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: [1000,3000,2800,4200,5000,6000,7000,8000,9000,10000,11000,12000],
|
||||
data: this.inputData,
|
||||
type: "bar",
|
||||
barWidth: 10,
|
||||
barGap:0,
|
||||
@ -122,7 +158,7 @@ export default {
|
||||
},
|
||||
},
|
||||
{
|
||||
data:[800,2900,2700,4100,4800,4900,5900,6800,7900,8900,9900,10000],
|
||||
data:this.outputData,
|
||||
type: "bar",
|
||||
barWidth: 10,
|
||||
itemStyle: {
|
||||
@ -133,7 +169,7 @@ export default {
|
||||
},
|
||||
},
|
||||
{
|
||||
data: [98,97,99,96,98,99,98,97,98,99,98,99],
|
||||
data:this.goodRateData,
|
||||
type: "line",
|
||||
yAxisIndex: 1,
|
||||
symbol:'circle',
|
||||
@ -149,7 +185,7 @@ export default {
|
||||
}
|
||||
],
|
||||
}
|
||||
option && myChart.setOption(option);
|
||||
option && this.chart.setOption(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -230,6 +266,11 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
.noData {
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
padding-top: 100px;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.qhd-chart-tooltip {
|
||||
|
@ -19,12 +19,12 @@
|
||||
<div>总生产</div>
|
||||
</div>
|
||||
<div class='right-data' style="top:15px;">
|
||||
<p><span class='num'>932,261</span><span class='text'>片数</span></p>
|
||||
<p><span class='num'>894</span><span class='text'>面积/㎡</span></p>
|
||||
<p><span class='num'>{{todayData?.inputNum ? formatThousands(todayData.inputNum) : '-'}}</span><span class='text'>片数</span></p>
|
||||
<p><span class='num'>{{todayData?.inputArea ? formatThousands(todayData.inputArea) : '-'}}</span><span class='text'>面积/㎡</span></p>
|
||||
</div>
|
||||
<div class='right-data' style="top:132px;">
|
||||
<p><span class='num'>932,261</span><span class='text'>片数</span></p>
|
||||
<p><span class='num'>894</span><span class='text'>面积/㎡</span></p>
|
||||
<p><span class='num'>{{todayData?.outputNum ? formatThousands(todayData.outputNum) : '-'}}</span><span class='text'>片数</span></p>
|
||||
<p><span class='num'>{{todayData?.outputArea ? formatThousands(todayData.outputArea) : '-'}}</span><span class='text'>面积/㎡</span></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class='title-split'>
|
||||
@ -42,12 +42,12 @@
|
||||
<div>总生产</div>
|
||||
</div>
|
||||
<div class='right-data' style="top:15px;">
|
||||
<p><span class='num'>932,261</span><span class='text'>片数</span></p>
|
||||
<p><span class='num'>894</span><span class='text'>面积/㎡</span></p>
|
||||
<p><span class='num'>{{yesterdayData?.inputNum ? formatThousands(yesterdayData.inputNum) : '-'}}</span><span class='text'>片数</span></p>
|
||||
<p><span class='num'>{{yesterdayData?.inputArea ? formatThousands(yesterdayData.inputArea) : '-'}}</span><span class='text'>面积/㎡</span></p>
|
||||
</div>
|
||||
<div class='right-data' style="top:132px;">
|
||||
<p><span class='num'>932,261</span><span class='text'>片数</span></p>
|
||||
<p><span class='num'>894</span><span class='text'>面积/㎡</span></p>
|
||||
<p><span class='num'>{{yesterdayData?.outputNum ? formatThousands(yesterdayData.outputNum) : '-'}}</span><span class='text'>片数</span></p>
|
||||
<p><span class='num'>{{yesterdayData?.outputArea ? formatThousands(yesterdayData.outputArea) : '-'}}</span><span class='text'>面积/㎡</span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -55,8 +55,28 @@
|
||||
<script>
|
||||
export default {
|
||||
name: 'LeftTop',
|
||||
props: {
|
||||
dataObj: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
dataObj(val) {
|
||||
val.todayAndYesterday && val.todayAndYesterday.forEach(item => {
|
||||
if (item.dataType === "今日") {
|
||||
this.todayData = item
|
||||
} else {
|
||||
this.yesterdayData = item
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
return {
|
||||
todayData:{},
|
||||
yesterdayData:{}
|
||||
}
|
||||
},
|
||||
methods: {}
|
||||
}
|
||||
|
@ -7,25 +7,11 @@
|
||||
<div class='rankingLeft'>
|
||||
<div class='rankingLeftTitle'>产量</div>
|
||||
<div class='rankingTypeBox'>
|
||||
<div>
|
||||
<img src="../../../../assets//images//dataBoard/ranking1.png" alt="" width='50'>
|
||||
<div style='margin-bottom: 10px;' v-for='(item,index) in teamProductionRank' :key='index'>
|
||||
<img :src="require(`../../../../assets/images/dataBoard/ranking${index+1}.png`)" alt="" width="50">
|
||||
<div class='rankingTextBox'>
|
||||
<p class='text1'>班组1/片</p>
|
||||
<p class='text2'>261,938,984</p>
|
||||
</div>
|
||||
</div>
|
||||
<div style='margin: 10px 0;'>
|
||||
<img src="../../../../assets//images//dataBoard/ranking2.png" alt="" width='50'>
|
||||
<div class='rankingTextBox'>
|
||||
<p class='text1'>班组1/片</p>
|
||||
<p class='text2'>261,938,984</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<img src="../../../../assets//images//dataBoard/ranking3.png" alt="" width='50'>
|
||||
<div class='rankingTextBox'>
|
||||
<p class='text1'>班组1/片</p>
|
||||
<p class='text2'>261,938,984</p>
|
||||
<p class='text1'>{{item.name}}/片</p>
|
||||
<p class='text2'>{{item?.value ? formatThousands(item.value) : '-'}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -35,14 +21,14 @@
|
||||
成品率
|
||||
</div>
|
||||
<div class='rankingTypeBox' style='left: 120px;'>
|
||||
<div>
|
||||
<img src="../../../../assets//images//dataBoard/ranking1.png" alt="" width='50'>
|
||||
<div style='margin-bottom: 10px;' v-for='(item,index) in teamRateRank' :key='index'>
|
||||
<img :src="require(`../../../../assets/images/dataBoard/ranking${index+1}.png`)" alt="" width="50">
|
||||
<div class='rankingTextBox'>
|
||||
<p class='text1'>班组1</p>
|
||||
<p class='text2'>95<span style='font-size: 20px;'>.92%</span></p>
|
||||
<p class='text1'>{{item.name}}</p>
|
||||
<p class='text2'>{{Math.trunc(item.value)}}<span style='font-size: 20px;'>.{{item.value1}}%</span></p>
|
||||
</div>
|
||||
</div>
|
||||
<div style='margin: 10px 0;'>
|
||||
<!-- <div>
|
||||
<img src="../../../../assets//images//dataBoard/ranking2.png" alt="" width='50'>
|
||||
<div class='rankingTextBox'>
|
||||
<p class='text1'>班组1</p>
|
||||
@ -55,7 +41,7 @@
|
||||
<p class='text1'>班组1</p>
|
||||
<p class='text2'>90<span style='font-size: 20px;'>.42%</span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -63,11 +49,49 @@
|
||||
<script>
|
||||
export default {
|
||||
name: 'RightBottom',
|
||||
props: {
|
||||
dataObj: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
dataObj(val) {
|
||||
this.teamProductionRank = []
|
||||
this.teamRateRank = []
|
||||
val.teamProductionRank && val.teamProductionRank.forEach(item => {
|
||||
let obj = {
|
||||
name: item.name,
|
||||
value: item.value,
|
||||
rank: item.rank,
|
||||
}
|
||||
this.teamProductionRank.push(obj)
|
||||
})
|
||||
val.teamRateRank && val.teamRateRank.forEach(item => {
|
||||
let obj = {
|
||||
name: item.name,
|
||||
value: item.value,
|
||||
rank: item.rank,
|
||||
value1: this.getPositiveDecimal(item.value)
|
||||
}
|
||||
this.teamRateRank.push(obj)
|
||||
})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
return {
|
||||
teamProductionRank:[],
|
||||
teamRateRank:[]
|
||||
}
|
||||
},
|
||||
mounted() {},
|
||||
methods: {}
|
||||
methods: {
|
||||
getPositiveDecimal(num) {
|
||||
const str = Math.abs(num).toString();
|
||||
const [, decimal] = str.split('.');
|
||||
return decimal || '00';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='scss' scoped>
|
||||
|
@ -14,23 +14,26 @@
|
||||
<div class='box' style='width: 105px;'>
|
||||
<p class='name'>
|
||||
<span style='margin-right: 3px;'>当日</span>
|
||||
<img src="../../../../assets/images/dataBoard/arrUp.png" alt="" width='5' height='15'>
|
||||
<img v-show='nokSumDet.today >= nokSumDet.yesterday' src="../../../../assets/images/dataBoard/arrUp.png" alt="" width='5' height='15'>
|
||||
<img v-show='nokSumDet.today < nokSumDet.yesterday' src="../../../../assets/images/dataBoard/arrDown.png" alt="" width='5' height='15'>
|
||||
</p>
|
||||
<p class='num'>283</p>
|
||||
<p class='num'>{{nokSumDet?.today ? formatThousands(nokSumDet.today) : '-'}}</p>
|
||||
</div>
|
||||
<div class='box' style='width: 115px;'>
|
||||
<p class='name'>
|
||||
<span style='margin-right: 3px;'>本月</span>
|
||||
<img src="../../../../assets/images/dataBoard/arrDown.png" alt="" width='5' height='15'>
|
||||
<img v-show='nokSumDet.month >= nokSumDet.lastMonth' src="../../../../assets/images/dataBoard/arrUp.png" alt="" width='5' height='15'>
|
||||
<img v-show='nokSumDet.month < nokSumDet.lastMonth' src="../../../../assets/images/dataBoard/arrDown.png" alt="" width='5' height='15'>
|
||||
</p>
|
||||
<p class='num'>2,830</p>
|
||||
<p class='num'>{{nokSumDet?.month ? formatThousands(nokSumDet.month) : '-'}}</p>
|
||||
</div>
|
||||
<div class='box' style='width: 110px;'>
|
||||
<p class='name'>
|
||||
<span style='margin-right: 3px;'>本年</span>
|
||||
<img src="../../../../assets/images/dataBoard/arrDown.png" alt="" width='5' height='15'>
|
||||
<img v-show='nokSumDet.year >= nokSumDet.lastYear' src="../../../../assets/images/dataBoard/arrUp.png" alt="" width='5' height='15'>
|
||||
<img v-show='nokSumDet.year < nokSumDet.lastYear' src="../../../../assets/images/dataBoard/arrDown.png" alt="" width='5' height='15'>
|
||||
</p>
|
||||
<p class='num'>32,830</p>
|
||||
<p class='num'>{{nokSumDet?.year ? formatThousands(nokSumDet.year) : '-'}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class='row' style='padding-top: 5px;'>
|
||||
@ -38,19 +41,19 @@
|
||||
<p class='name'>
|
||||
<span>昨日</span>
|
||||
</p>
|
||||
<p class='num'>283</p>
|
||||
<p class='num'>{{nokSumDet?.yesterday ? formatThousands(nokSumDet.yesterday) : '-'}}</p>
|
||||
</div>
|
||||
<div class='box' style='width: 115px;'>
|
||||
<p class='name'>
|
||||
<span>上月</span>
|
||||
</p>
|
||||
<p class='num'>2,830</p>
|
||||
<p class='num'>{{nokSumDet?.lastMonth ? formatThousands(nokSumDet.lastMonth) : '-'}}</p>
|
||||
</div>
|
||||
<div class='box' style='width: 110px;'>
|
||||
<p class='name'>
|
||||
<span>上年</span>
|
||||
</p>
|
||||
<p class='num'>32,830</p>
|
||||
<p class='num'>{{nokSumDet?.lastYear ? formatThousands(nokSumDet.lastYear) : '-'}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -73,29 +76,51 @@ const colors = [
|
||||
];
|
||||
export default {
|
||||
name: 'RightTop',
|
||||
props: {
|
||||
dataObj: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
dataObj(val) {
|
||||
this.nokSumDet = val.nokSumDet
|
||||
this.dataProps = []
|
||||
val.nokPieDet && val.nokPieDet.forEach(item => {
|
||||
let obj = {
|
||||
value: item.num,
|
||||
name: item.type
|
||||
}
|
||||
this.dataProps.push(obj)
|
||||
})
|
||||
this.initChart()
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
nokSumDet:{},
|
||||
chartDom: '',
|
||||
chart: '',
|
||||
dataProps:[],
|
||||
rangArrValue:[],
|
||||
dataList:[],
|
||||
totalValue:0
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initChart();
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
initChart() {
|
||||
var chartDom = document.getElementById('defectSumChart');
|
||||
var myChart = echarts.init(chartDom);
|
||||
if (
|
||||
this.chart !== null &&
|
||||
this.chart !== '' &&
|
||||
this.chart !== undefined
|
||||
) {
|
||||
this.chart.dispose() // 页面多次刷新会出现警告,Dom已经初始化了一个实例,这是销毁实例
|
||||
}
|
||||
this.chartDom = document.getElementById('defectSumChart')
|
||||
this.chart = echarts.init(this.chartDom)
|
||||
var option;
|
||||
const dataProps = [
|
||||
{value: 14,name:'缺陷1'},
|
||||
{value: 20,name:'缺陷2'},
|
||||
{value: 22,name:'缺陷3'},
|
||||
{value: 14,name:'缺陷4'},
|
||||
{value: 30,name:'缺陷5'}
|
||||
]
|
||||
this.getPersonnelList(dataProps)
|
||||
this.getPersonnelList(this.dataProps)
|
||||
option = {
|
||||
color: colors,
|
||||
graphic: [
|
||||
@ -132,10 +157,6 @@ export default {
|
||||
type: "pie",
|
||||
radius: ["45%", "60%"],
|
||||
center: ["50%", "50%"],
|
||||
// label: {
|
||||
// formatter: "{d}%",
|
||||
// color: "#fff",
|
||||
// },
|
||||
label:{
|
||||
formatter:function(params){
|
||||
return `{color${params.dataIndex}|${params.percent}%}\n{style2|${params.name}}`
|
||||
@ -161,7 +182,7 @@ export default {
|
||||
},
|
||||
],
|
||||
}
|
||||
option && myChart.setOption(option);
|
||||
option && this.chart.setOption(option);
|
||||
},
|
||||
getCoordinates(startArc, endArc) {
|
||||
const posi = [
|
||||
|
@ -5,13 +5,13 @@
|
||||
:is-full-screen="isFullScreen"
|
||||
@screenfullChange="screenfullChange"
|
||||
/>
|
||||
<LeftTop />
|
||||
<LeftBottom />
|
||||
<CenterTop :scaleNum='scaleNum'/>
|
||||
<CenterBottomL />
|
||||
<CenterBottomR />
|
||||
<RightTop />
|
||||
<RightBottom />
|
||||
<LeftTop :dataObj='dataObj'/>
|
||||
<LeftBottom :dataObj='dataObj'/>
|
||||
<CenterTop :scaleNum='scaleNum' :dataObj='dataObj'/>
|
||||
<CenterBottomL :dataObj='dataObj'/>
|
||||
<CenterBottomR :dataObj='dataObj'/>
|
||||
<RightTop :dataObj='dataObj'/>
|
||||
<RightBottom :dataObj='dataObj'/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -27,6 +27,8 @@ import RightTop from './components/RightTop.vue';
|
||||
import RightBottom from './components/RightBottom.vue';
|
||||
import { debounce } from '@/utils/debounce';
|
||||
import screenfull from 'screenfull';
|
||||
import { getAccessToken } from '@/utils/auth';
|
||||
import store from "@/store";
|
||||
export default {
|
||||
name: 'DataBoard',
|
||||
components: { DataBoardHeader,LeftTop,LeftBottom,CenterTop,CenterBottomL,CenterBottomR,RightTop,RightBottom },
|
||||
@ -35,12 +37,14 @@ export default {
|
||||
return {
|
||||
isFullScreen: false,
|
||||
scaleNum: 0.8,
|
||||
dataObj:{}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.init()
|
||||
},
|
||||
mounted() {
|
||||
console.log('dataBoard mounted')
|
||||
this.boxReset = debounce(() => {
|
||||
this.resetSize()
|
||||
}, 300)
|
||||
@ -48,6 +52,10 @@ export default {
|
||||
window.addEventListener('resize', () => {
|
||||
this.boxReset()
|
||||
})
|
||||
this.getData()
|
||||
},
|
||||
destroyed() {
|
||||
console.log('dataBoard destroyed')
|
||||
},
|
||||
computed: {
|
||||
sidebarOpened() {
|
||||
@ -60,6 +68,53 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getData() {
|
||||
let _this = this;
|
||||
const url = process.env.VUE_APP_BASE_API+'/admin-api/monitoring/message/subscribe/'+store.getters.userId+'-'+Date.now();
|
||||
const token = getAccessToken()
|
||||
const headers = new Headers({
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'text/event-stream'
|
||||
});
|
||||
fetch(url, { headers })
|
||||
.then(response => {
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
const readStream = () => {
|
||||
reader.read().then(({ done, value }) => {
|
||||
if (done) {
|
||||
console.log('SSE 连接关闭');
|
||||
return;
|
||||
}
|
||||
const data = decoder.decode(value);
|
||||
console.log('收到消息:', data);
|
||||
if (_this.isValidData(data)){
|
||||
_this.upDateMsg(data);
|
||||
}
|
||||
readStream(); // 继续读取
|
||||
}).catch(error => {
|
||||
console.error('SSE 读取错误:', error);
|
||||
});
|
||||
};
|
||||
readStream();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('SSE 连接失败:', error);
|
||||
});
|
||||
},
|
||||
isValidData (data) {
|
||||
return data.trim().startsWith('data:{') && !data.includes('heartbeat');
|
||||
},
|
||||
upDateMsg(data) {
|
||||
const jsonStr = data.replace(/^data:/, '').trim();
|
||||
try {
|
||||
const dataObj = JSON.parse(jsonStr);
|
||||
this.dataObj = dataObj
|
||||
console.log('dataObj',this.dataObj)
|
||||
} catch (e) {
|
||||
console.error('JSON 解析失败:', e);
|
||||
}
|
||||
},
|
||||
change() {
|
||||
this.isFullScreen = screenfull.isFullscreen
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user