This commit is contained in:
2025-03-10 16:32:02 +08:00
parent 1434eaa3ac
commit eaf00466db
49 changed files with 3454 additions and 28 deletions

View File

@@ -0,0 +1,307 @@
<template>
<div :class="className" :style="{ height: height, width: width }" />
</template>
<script>
import * as echarts from 'echarts';
require('echarts/theme/macarons'); // echarts theme
import resize from '../mixins/resize';
import { max } from 'moment';
const animationDuration = 6000;
export default {
mixins: [resize],
props: {
echartData: {
type: Array,
default: () => [],
},
className: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '100%',
},
height: {
type: String,
default: '380px',
},
},
data() {
return {
chart: null,
};
},
mounted() {
this.$nextTick(() => {
this.initChart();
});
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
initChart() {
var option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999',
},
},
},
grid: {
top: 100,
left: '2%',
right: '3%',
bottom: '3%',
containLabel: true,
},
legend: {
data: [
'产量',
{
name: '成本',
icon: 'path://M1255.570286 1024a512 512 0 1 0 0-1024 512 512 0 0 0 0 1024z m641.609143-512c0 37.376-3.072 74.020571-8.923429 109.714286h393.069714c59.611429 0 107.958857-49.152 107.958857-109.714286s-48.274286-109.714286-107.958857-109.714286h-393.069714c5.851429 35.693714 8.923429 72.338286 8.923429 109.714286zM156.745143 621.714286h453.12a672.914286 672.914286 0 0 1 0-219.428572H156.745143C97.133714 402.285714 48.786286 451.437714 48.786286 512s48.274286 109.714286 107.958857 109.714286z',
},
{
name: '良品率',
icon: 'path://M1255.570286 1024a512 512 0 1 0 0-1024 512 512 0 0 0 0 1024z m641.609143-512c0 37.376-3.072 74.020571-8.923429 109.714286h393.069714c59.611429 0 107.958857-49.152 107.958857-109.714286s-48.274286-109.714286-107.958857-109.714286h-393.069714c5.851429 35.693714 8.923429 72.338286 8.923429 109.714286zM156.745143 621.714286h453.12a672.914286 672.914286 0 0 1 0-219.428572H156.745143C97.133714 402.285714 48.786286 451.437714 48.786286 512s48.274286 109.714286 107.958857 109.714286z',
},
],
itemWidth: 18,
itemHeight: 18,
textStyle: {
fontSize: 18,
color: '#DFF1FE',
},
top: 15,
right: 20,
},
xAxis: [
{
type: 'category',
data: this.echartData.map((item) => {
return item.time;
}),
axisPointer: {
type: 'shadow',
},
axisLine: {
lineStyle: {
type: 'solid',
color: '#97B3FF', // 左边线的颜色
width: '1', // 坐标线的宽度
},
},
},
],
yAxis: [
{
type: 'value',
name: '单位/片',
min: 0,
position: 'left',
alignTicks: true,
axisLabel: {
color: 'white',
},
nameTextStyle: {
color: 'white',
},
axisLine: {
show: true,
lineStyle: {
type: 'solid',
color: '#97B3FF', // 左边线的颜色
width: '1', // 坐标线的宽度
},
},
splitLine: {
lineStyle: {
color: '#b6c1e1',
},
},
splitArea: {
show: false,
},
},
{
type: 'value',
name: '%',
max: 100,
min: 0,
minInterval: 1,
position: 'right',
axisLabel: {
color: 'white',
},
nameTextStyle: {
color: 'white',
},
axisLine: {
show: true,
lineStyle: {
type: 'solid',
color: '#97B3FF', // 左边线的颜色
width: '1', // 坐标线的宽度
},
},
splitLine: {
lineStyle: {
color: '#b6c1e1',
},
},
splitArea: {
show: false,
},
},
{
type: 'value',
name: '万元',
min: 0,
position: 'right',
alignTicks: true,
offset: 40,
axisLabel: {
color: 'white',
},
nameTextStyle: {
color: 'white',
},
axisLine: {
show: true,
lineStyle: {
type: 'solid',
color: '#97B3FF', // 左边线的颜色
width: '1', // 坐标线的宽度
},
},
splitLine: {
lineStyle: {
color: '#b6c1e1',
},
},
splitArea: {
show: false,
},
},
],
series: [
{
name: '产量',
type: 'bar',
barWidth: '14px',
data: this.echartData.map((item) => {
return Number(item.out).toFixed(1);
}),
animationDuration,
tooltip: {
valueFormatter: function (value) {
return value + ' 片';
},
},
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#5CB7FF' },
{ offset: 1, color: '#364BFE' },
]),
},
},
{
name: '成本',
type: 'line',
symbol: 'circle',
symbolSize: 8,
yAxisIndex: 2,
data: this.echartData.map((item) => {
return Number(item.price).toFixed(1);
}),
animationDuration,
tooltip: {
valueFormatter: function (value) {
return value + ' 万元';
},
},
lineStyle: {
color: '#FF1295',
},
itemStyle: {
color: '#FF1295',
borderWidth: 1, // 圆点边框宽度(可选)
},
areaStyle: {
opacity: 0.2,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: '#FF1295',
},
{
offset: 1,
color: 'transparent',
},
]),
},
},
{
name: '良品率',
type: 'line',
symbol: 'circle',
symbolSize: 8,
yAxisIndex: 1,
data: this.echartData.map((item) => {
return Number(item.ratio).toFixed(1);
}),
animationDuration,
tooltip: {
valueFormatter: function (value) {
return value + ' %';
},
},
lineStyle: {
color: '#12FFF5',
},
itemStyle: {
color: '#12FFF5',
borderWidth: 1, // 圆点边框宽度(可选)
},
areaStyle: {
opacity: 0.2,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: '#12FFF5',
},
{
offset: 1,
color: 'transparent',
},
]),
},
},
],
};
if (this.chart) {
this.chart.setOption(option);
} else {
this.chart = echarts.init(this.$el, 'macarons');
this.chart.setOption(option);
}
window.addEventListener('resize', () => {
this.chart.resize();
});
},
},
};
</script>

View File

@@ -0,0 +1,497 @@
<template>
<div
id="wholePlantContainerB"
ref="wholePlantContainerB"
style="width: 100%; height: 100%">
<div
id="wholePlantContainer"
ref="wholePlantContainer"
class="wholePlantBoard"
style="
position: absolute;
transform-origin: 16px 8px;
font-size: 16px;
top: 0px;
left: 0px;
width: 1920px;
height: 1080px;
display: flex;
flex-direction: column;
gap: 24px;
"
:style="{ transform: 'scale(' + scaleNum + ')' }">
<KHeader
:isFullScreen="isFullScreen"
@screenfullChange="screenfullChange"
topTitle="自贡深加工成本看板" />
<div class="main-body">
<div style="flex: 1" class="bz25-2 bz-top">
<div class="topNum">{{ Number(topData.yestodaySum).toFixed(1) }}</div>
<div class="topText">昨日总成本/万元</div>
</div>
<div style="flex: 1" class="bz25-3 bz-top">
<div class="topNum" style="margin-left: 50px">
{{ Number(topData.yestodayRatio).toFixed(1) }}%
</div>
<div class="topText">昨日良品率</div>
</div>
<div style="flex: 1" class="bz25-4 bz-top">
<div class="topNum">{{ Number(topData.yestodayOut).toFixed(1) }}</div>
<div class="topText">昨日深加工产量/万m²</div>
</div>
<div style="flex: 1" class="bz25-7 bz-top">
<div class="topNum">{{ Number(topData.monthSum).toFixed(1) }}</div>
<div class="topText">本月深加工成本/万元</div>
</div>
<div style="flex: 1" class="bz25-8 bz-top">
<div class="topNum">{{ Number(topData.monthAreaCost).toFixed(1) }}</div>
<div class="topText">本月每平米总成本/</div>
</div>
</div>
<div class="main-body">
<div style="flex: 2" class="middle middle1">
<div class="title">
<svg-icon icon-class="line" />
各产线产量及良品率
<span style="float: right">产量单位:万平方米</span>
</div>
<base-table
:id="'table3'"
style="margin: 5px 12px 12px 12px"
:table-props="tableProps3"
:table-data="tableData3"
:height="230"></base-table>
</div>
<div style="flex: 1" class="middle middle2">
<div class="title">
<svg-icon icon-class="energy" />
能源统计
</div>
<base-table
:id="'table1'"
style="margin: 5px 12px 12px 12px"
:table-props="tableProps1"
:table-data="tableData1"
:height="230"></base-table>
</div>
</div>
<div class="main-body">
<div style="flex: 2" class="footer footer1">
<div class="title">
<svg-icon icon-class="costchart" />
近12个月成本 · 产量趋势
</div>
<bar-chart
ref="chartRef"
style="margin-top: -50px"
:echart-data="echartData"></bar-chart>
</div>
<div style="flex: 1" class="footer footer2">
<div class="title">
<svg-icon icon-class="cost" />
成本及产量统计
</div>
<base-table
:id="'table2'"
style="margin: 5px 12px 12px 12px"
:table-props="tableProps2"
:table-data="tableData2"
:height="310"></base-table>
</div>
</div>
</div>
</div>
</template>
<script>
import KHeader from '../components/Header';
import screenfull from 'screenfull';
import { debounce } from '@/utils/debounce';
import baseTable from '../components/baseTable.vue';
import BarChart from './BarChart.vue';
import interval from './interval.vue';
const tableProps1 = [
{
prop: 'title',
label: '',
align: 'center',
},
{
prop: 'elec',
label: '电消耗量/kwh',
filter: (val) => (val != null ? Number(val).toFixed(1) : '-'),
},
{
prop: 'yure',
label: '余热发电量/kwh',
filter: (val) => (val != null ? Number(val).toFixed(1) : '-'),
},
{
prop: 'elecPrice',
label: '总价/万元',
filter: (val) => (val != null ? Number(val).toFixed(1) : '-'),
},
];
const tableProps2 = [
{
prop: 'title',
label: '',
align: 'center',
},
{
prop: 'priceD',
label: '成本/万元',
filter: (val) => (val != null ? Number(val).toFixed(1) : '-'),
},
{
prop: 'outD',
label: '产量/万m²',
filter: (val) => (val != null ? Number(val).toFixed(1) : '-'),
},
{
prop: 'ratioD',
label: '良品率',
filter: (val) => (val != null ? Number(val).toFixed(1) : '-'),
},
];
const tableProps3 = [
{
prop: 'title',
label: '',
align: 'center',
},
{
prop: '1',
label: '产线1',
subcomponent: interval,
align: 'center',
},
{
prop: '2',
label: '产线2',
subcomponent: interval,
align: 'center',
},
{
prop: '3',
label: '产线3',
subcomponent: interval,
align: 'center',
},
{
prop: '4',
label: '产线4',
subcomponent: interval,
align: 'center',
},
{
prop: '5',
label: '产线5',
subcomponent: interval,
align: 'center',
},
];
export default {
name: '',
components: {
KHeader,
baseTable,
BarChart,
},
// provide() {
// return {
// resizeChart: null,
// };
// },
data() {
return {
isFullScreen: false,
scaleNum: 0.8,
url: process.env.VUE_APP_WS_API,
websock: '',
topData: {},
imgUrl: {
o2: require('@/views/dashboard/assets/O2.png'),
no: require('@/views/dashboard/assets/NO.png'),
so2: require('@/views/dashboard/assets/SO2.png'),
no2: require('@/views/dashboard/assets/NO2.png'),
},
tableProps1,
tableData1: [],
tableProps2,
tableData2: [],
tableProps3,
tableData3: [],
echartData: []
};
},
created() {
this.init();
this.initWebSocket();
},
destroy() {
this.destroy();
},
mounted() {
this.boxReset();
window.addEventListener('resize', this.boxReset);
},
destroyed() {
window.removeEventListener('resize', this.boxReset);
},
methods: {
boxReset() {
debounce(() => {
this.resetSize();
}, 300)();
},
change() {
this.isFullScreen = screenfull.isFullscreen;
},
init() {
if (screenfull.isEnabled) {
screenfull.on('change', this.change);
}
},
destroy() {
if (screenfull.isEnabled) {
screenfull.off('change', this.change);
}
},
// 全屏
screenfullChange() {
if (!screenfull.isEnabled) {
this.$message({
message: 'you browser can not work',
type: 'warning',
});
return false;
}
screenfull.toggle(this.$refs.wholePlantContainerB);
},
resetSize() {
let wholePlantContainerBox = document.getElementById(
'wholePlantContainer'
);
let rw = parseFloat(window.innerWidth);
let rh = parseFloat(window.innerHeight);
let bw = parseFloat(wholePlantContainerBox.style.width);
let bh = parseFloat(wholePlantContainerBox.style.height);
let wx = 0;
let hx = 0;
if (screenfull.isFullscreen) {
wx = rw / bw;
hx = rh / bh;
} else {
if (this.$store.state.app.sidebar.opened) {
wx = (rw - 280) / bw;
hx = (rh - 116) / bh;
} else {
wx = (rw - 85) / bw;
hx = (rh - 116) / bh;
}
}
this.scaleNum = wx;
},
initWebSocket() {
// 初始化weosocket
const path = `${this.url}/websocket/message?userId=3`;
this.websock = new WebSocket(path);
this.websock.onmessage = this.websocketonmessage;
this.websock.onopen = this.websocketonopen;
this.websock.onerror = this.websocketonerror;
this.websock.onclose = this.websocketclose;
},
websocketonopen() {
// 连接建立之后执行send方法发送数据
this.websocketsend();
},
websocketonerror() {
// 连接建立失败重连
this.initWebSocket();
},
websocketonmessage(e) {
let dataJson = JSON.parse(e.data);
console.log(dataJson);
// 数据接收
if ('DeepState' in dataJson) {
this.topData = dataJson.DeepState;
}
if ('DeepEnergyTableList' in dataJson) {
this.tableData1 = dataJson.DeepEnergyTableList;
}
if ('DeepCostTableList' in dataJson) {
this.tableData2 = dataJson.DeepCostTableList;
}
if ('DeepPdTables' in dataJson) {
this.tableData3 = dataJson.DeepPdTables;
}
if ('DeepCostTrendList' in dataJson) {
this.echartData = dataJson.DeepCostTrendList;
this.$nextTick(() => {
this.$refs.chartRef.initChart();
});
}
},
websocketsend(val) {
// 数据发送
this.websock.send(val);
},
websocketclose(e) {
// 关闭
console.log('断开连接', e);
},
},
};
</script>
<style scoped lang="scss">
.wholePlantBoard {
background: url(../assets/bg1.png) no-repeat;
background-size: cover;
background-position: 0 0;
overflow: auto;
}
.main-body {
display: flex;
gap: 20px;
padding: 0px 16px;
}
.bz-top {
text-align: center;
}
.bz25-2 {
background: url(../assets/bz25-d-1.png) no-repeat;
background-size: 100% 100%;
border-radius: 5px;
overflow: auto;
height: 147px;
margin-top: -17px;
}
.bz25-3 {
background: url(../assets/bz25-d-2.png) no-repeat;
background-size: 100% 100%;
border-radius: 5px;
overflow: auto;
height: 147px;
margin-top: -17px;
}
.bz25-4 {
background: url(../assets/bz25-d-3.png) no-repeat;
background-size: 100% 100%;
border-radius: 5px;
overflow: auto;
height: 147px;
margin-top: -17px;
}
.bz25-7 {
background: url(../assets/bz25-d-4.png) no-repeat;
background-size: 100% 100%;
border-radius: 5px;
overflow: auto;
height: 147px;
margin-top: -17px;
}
.bz25-8 {
background: url(../assets/bz25-d-5.png) no-repeat;
background-size: 100% 100%;
border-radius: 5px;
overflow: auto;
height: 147px;
margin-top: -17px;
}
.topNum {
font-weight: 600;
font-size: 44px;
color: #ffffff;
line-height: 43px;
font-style: normal;
margin-top: 50px;
margin-left: 40px;
}
.topText {
font-weight: 400;
font-size: 18px;
color: #95caff;
line-height: 20px;
font-style: normal;
margin-top: 3px;
margin-left: 40px;
}
.title {
height: 50px;
line-height: 50px;
font-weight: 400;
font-size: 22px;
color: #ffffff;
padding: 0 20px;
}
.middle {
height: 322px;
}
.middle1 {
background: url(../assets/1.png) no-repeat;
background-size: 100% 100%;
border-radius: 5px;
overflow: auto;
}
.middle2 {
background: url(../assets/2.png) no-repeat;
background-size: 100% 100%;
border-radius: 5px;
overflow: auto;
}
.yanqi {
width: 275px;
height: 108px;
background: url(../assets/yanqi.png) no-repeat;
background-size: 100% 100%;
border-radius: 5px;
overflow: auto;
text-align: center;
}
.content {
height: 108px;
}
.imageClass {
width: 40px;
height: 30px;
display: block;
margin: 8px auto;
}
.middle2-left {
font-size: 18px;
color: rgba(255, 255, 255, 0.9);
line-height: 17px;
letter-spacing: 5px;
width: 110px;
padding-top: 12px;
padding-left: 12px;
float: left;
}
.middle2-right {
font-weight: 600;
font-size: 38px;
color: #ffffff;
line-height: 106px;
}
.footer {
height: 410px;
}
.footer1 {
background: url(../assets/3.png) no-repeat;
background-size: 100% 100%;
border-radius: 5px;
overflow: auto;
}
.footer2 {
background: url(../assets/4.png) no-repeat;
background-size: 100% 100%;
border-radius: 5px;
overflow: auto;
height: 402px;
}
</style>

View File

@@ -0,0 +1,51 @@
<!--
* @Author: zwq
* @Date: 2023-08-03 14:09:18
* @LastEditors: zwq
* @LastEditTime: 2025-03-06 16:32:48
* @Description:
-->
<template>
<div class="tableInner" style="display: flex">
<div style="flex: 3; border-right: 2px solid #305887">
{{
list['out' + list.prop]
? Number(list['out' + list.prop]).toFixed(1)
: '-'
}}
</div>
<div style="flex: 2">
{{
list['ratio' + list.prop]
? Number(list['ratio' + list.prop]).toFixed(1)
: '-'
}}
</div>
</div>
</template>
<script>
export default {
props: {
injectData: {
type: Object,
default: () => ({}),
},
},
data() {
return {
list: this.injectData,
};
},
created() {},
methods: {},
};
</script>
<style scoped>
.tableInner {
border: none;
padding: 0;
height: 40px;
line-height: 40px;
text-align: center;
}
</style>