Compare commits

...

15 Commits

Author SHA1 Message Date
6cbabb7691 update 2023-09-10 19:53:15 +08:00
fd0985868c add websocket 2023-09-09 16:49:43 +08:00
2c0e0f8fd6 update fan runtime 2023-09-09 14:11:07 +08:00
ba68b34879 update 2023-09-09 13:28:34 +08:00
65055dd49c update 2023-09-09 13:20:49 +08:00
b3bae7b635 done 试试水温 2023-09-09 13:03:01 +08:00
1743bc24d3 add components 2023-09-09 12:04:59 +08:00
lb
8010b93fe9 update layout 2023-09-08 16:54:01 +08:00
lb
bfeec6db62 update 完成中部 2023-09-08 16:35:41 +08:00
lb
d23215c3d6 update press 2023-09-08 16:28:25 +08:00
lb
3b270eb50f add chart+tables 2023-09-08 14:16:17 +08:00
lb
30bd1f06ed add center widget 2023-09-08 13:48:40 +08:00
lb
86bc094b89 cleanup 2023-09-08 11:23:47 +08:00
lb
2c2790a473 update header 2023-09-08 11:12:58 +08:00
lb
168f4af5fc update basic layout 2023-09-08 10:30:40 +08:00
49 changed files with 3243 additions and 128 deletions

109
package-lock.json generated
View File

@ -17,13 +17,16 @@
"vuex": "^3.6.2" "vuex": "^3.6.2"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.6.0",
"@types/ws": "^8.5.5",
"@vue/cli-plugin-babel": "~5.0.0", "@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-router": "~5.0.0", "@vue/cli-plugin-router": "~5.0.0",
"@vue/cli-plugin-vuex": "~5.0.0", "@vue/cli-plugin-vuex": "~5.0.0",
"@vue/cli-service": "~5.0.0", "@vue/cli-service": "~5.0.0",
"sass": "^1.32.7", "sass": "^1.32.7",
"sass-loader": "^12.0.0", "sass-loader": "^12.0.0",
"vue-template-compiler": "^2.6.14" "vue-template-compiler": "^2.6.14",
"ws": "^8.14.1"
} }
}, },
"node_modules/@achrinza/node-ipc": { "node_modules/@achrinza/node-ipc": {
@ -2344,11 +2347,10 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.1.0", "version": "20.6.0",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-20.1.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.0.tgz",
"integrity": "sha512-O+z53uwx64xY7D6roOi4+jApDGFg0qn6WHcxe5QeqjMaTezBO/mxdfFXIVAVVyNWKx84OmPB3L8kbVYOTeN34A==", "integrity": "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==",
"dev": true, "dev": true
"license": "MIT"
}, },
"node_modules/@types/normalize-package-data": { "node_modules/@types/normalize-package-data": {
"version": "2.4.1", "version": "2.4.1",
@ -2435,11 +2437,10 @@
} }
}, },
"node_modules/@types/ws": { "node_modules/@types/ws": {
"version": "8.5.4", "version": "8.5.5",
"resolved": "https://registry.npmmirror.com/@types/ws/-/ws-8.5.4.tgz", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz",
"integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@types/node": "*" "@types/node": "*"
} }
@ -10108,6 +10109,27 @@
"node": ">= 10.13.0" "node": ">= 10.13.0"
} }
}, },
"node_modules/webpack-bundle-analyzer/node_modules/ws": {
"version": "7.5.9",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
"dev": true,
"engines": {
"node": ">=8.3.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/webpack-chain": { "node_modules/webpack-chain": {
"version": "6.5.1", "version": "6.5.1",
"resolved": "https://registry.npmmirror.com/webpack-chain/-/webpack-chain-6.5.1.tgz", "resolved": "https://registry.npmmirror.com/webpack-chain/-/webpack-chain-6.5.1.tgz",
@ -10356,28 +10378,6 @@
"url": "https://opencollective.com/webpack" "url": "https://opencollective.com/webpack"
} }
}, },
"node_modules/webpack-dev-server/node_modules/ws": {
"version": "8.13.0",
"resolved": "https://registry.npmmirror.com/ws/-/ws-8.13.0.tgz",
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/webpack-merge": { "node_modules/webpack-merge": {
"version": "5.8.0", "version": "5.8.0",
"resolved": "https://registry.npmmirror.com/webpack-merge/-/webpack-merge-5.8.0.tgz", "resolved": "https://registry.npmmirror.com/webpack-merge/-/webpack-merge-5.8.0.tgz",
@ -10498,17 +10498,16 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/ws": { "node_modules/ws": {
"version": "7.5.9", "version": "8.14.1",
"resolved": "https://registry.npmmirror.com/ws/-/ws-7.5.9.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.1.tgz",
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", "integrity": "sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">=8.3.0" "node": ">=10.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"bufferutil": "^4.0.1", "bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2" "utf-8-validate": ">=5.0.2"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"bufferutil": { "bufferutil": {
@ -12177,9 +12176,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "20.1.0", "version": "20.6.0",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-20.1.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.0.tgz",
"integrity": "sha512-O+z53uwx64xY7D6roOi4+jApDGFg0qn6WHcxe5QeqjMaTezBO/mxdfFXIVAVVyNWKx84OmPB3L8kbVYOTeN34A==", "integrity": "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==",
"dev": true "dev": true
}, },
"@types/normalize-package-data": { "@types/normalize-package-data": {
@ -12259,9 +12258,9 @@
} }
}, },
"@types/ws": { "@types/ws": {
"version": "8.5.4", "version": "8.5.5",
"resolved": "https://registry.npmmirror.com/@types/ws/-/ws-8.5.4.tgz", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz",
"integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/node": "*" "@types/node": "*"
@ -17479,6 +17478,15 @@
"opener": "^1.5.2", "opener": "^1.5.2",
"sirv": "^1.0.7", "sirv": "^1.0.7",
"ws": "^7.3.1" "ws": "^7.3.1"
},
"dependencies": {
"ws": {
"version": "7.5.9",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
"dev": true,
"requires": {}
}
} }
}, },
"webpack-chain": { "webpack-chain": {
@ -17639,13 +17647,6 @@
"ajv-formats": "^2.1.1", "ajv-formats": "^2.1.1",
"ajv-keywords": "^5.1.0" "ajv-keywords": "^5.1.0"
} }
},
"ws": {
"version": "8.13.0",
"resolved": "https://registry.npmmirror.com/ws/-/ws-8.13.0.tgz",
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
"dev": true,
"requires": {}
} }
} }
}, },
@ -17737,9 +17738,9 @@
"dev": true "dev": true
}, },
"ws": { "ws": {
"version": "7.5.9", "version": "8.14.1",
"resolved": "https://registry.npmmirror.com/ws/-/ws-7.5.9.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.1.tgz",
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", "integrity": "sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A==",
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },

View File

@ -4,7 +4,8 @@
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",
"build": "vue-cli-service build" "build": "vue-cli-service build",
"server": "ts-node ./src/components/yx-dark/socket-server/index.ts"
}, },
"dependencies": { "dependencies": {
"core-js": "^3.8.3", "core-js": "^3.8.3",
@ -16,12 +17,17 @@
"vuex": "^3.6.2" "vuex": "^3.6.2"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.6.0",
"@types/ws": "^8.5.5",
"@vue/cli-plugin-babel": "~5.0.0", "@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-router": "~5.0.0", "@vue/cli-plugin-router": "~5.0.0",
"@vue/cli-plugin-vuex": "~5.0.0", "@vue/cli-plugin-vuex": "~5.0.0",
"@vue/cli-service": "~5.0.0", "@vue/cli-service": "~5.0.0",
"sass": "^1.32.7", "sass": "^1.32.7",
"sass-loader": "^12.0.0", "sass-loader": "^12.0.0",
"vue-template-compiler": "^2.6.14" "ts-node": "^10.9.1",
"typescript": "^5.2.2",
"vue-template-compiler": "^2.6.14",
"ws": "^8.14.1"
} }
} }

View File

Before

Width:  |  Height:  |  Size: 6.3 MiB

After

Width:  |  Height:  |  Size: 6.3 MiB

BIN
src/assets/bottom-bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 KiB

BIN
src/assets/digit-bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 309 KiB

BIN
src/assets/icon-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
src/assets/icon-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
src/assets/icon-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
src/assets/icon-4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

BIN
src/assets/icon-gas.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

BIN
src/assets/left-top-bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
src/assets/main-area-bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 MiB

BIN
src/assets/rect-bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

BIN
src/assets/right-top-bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 KiB

View File

@ -1,27 +1,27 @@
<template> <template>
<header class="header relative"> <header class="header">
<div> <div>
<span class="header--logo"> <span class="header--logo">
<!-- <img src="../../assets/logo.png" alt="logo"> --> <!-- <img src="../../assets/logo.png" alt="logo"> -->
</span> </span>
<h1>凯盛晶华玻璃有限公司800t/d特种玻璃生产线大数据指挥中心</h1> <h1>宜兴三期生产线大数据指挥中心</h1>
</div> </div>
<span class="header--wing absolute company"></span> <span class="header--wing absolute company"></span>
<span class="header--wing absolute datetime"> <span class="header--wing absolute datetime">
{{ moment(today).format('YYYY.M.D dddd HH:mm:ss') }} {{ moment(today).format("YYYY.M.D dddd HH:mm:ss") }}
</span> </span>
</header> </header>
</template> </template>
<script> <script>
import moment from 'moment' import moment from "moment";
export default { export default {
name: "Header", name: "Header",
data() { data() {
return { return {
today: new Date(), today: new Date(),
time: "00:00:00", time: "00:00:00",
moment moment,
}; };
}, },
computed: { computed: {
@ -41,10 +41,10 @@ export default {
}, },
}, },
mounted() { mounted() {
moment.locale('zh-cn') moment.locale("zh-cn");
// this.time = this.getTime().join(":"); // this.time = this.getTime().join(":");
setInterval(() => { setInterval(() => {
this.today = new Date() this.today = new Date();
// this.time = this.getTime().join(":"); // this.time = this.getTime().join(":");
}, 1000); }, 1000);
}, },
@ -66,33 +66,37 @@ export default {
@import "../../assets/styles/variables"; @import "../../assets/styles/variables";
header { header {
background: url(../../assets/header.png) center/contain no-repeat; position: absolute;
background-size: 100%; width: 100%;
height: adjust(h(280px)); top: 0;
width: adjust($actual_width); left: 0;
z-index: 10000;
background: url(../../assets/header.png) no-repeat;
background-position: center;
background-size: contain;
// background-size: 100%;
height: 146px;
display: grid; display: grid;
place-items: center; place-content: center;
> div { > div {
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: adjust(10px); margin-bottom: 0;
.header--logo { .header--logo {
width: adjust(102px); margin-top: 12px;
height: adjust(56px); width: 64px;
height: 94px;
background: url(../../assets/logo.png) center/contain no-repeat; background: url(../../assets/logo.png) center/contain no-repeat;
} }
h1 { h1 {
margin-left: adjust(20px); margin-left: 36px;
font-size: adjust(35px); font-size: 72px;
// line-height: adjust(100px);
// background: #eee;
user-select: none; user-select: none;
letter-spacing: adjust(8px); letter-spacing: 14px;
font-weight: 600; font-weight: 400;
// color: #6bf2ff;
color: $main-color; color: $main-color;
font-family: "微软雅黑", sans-serif; font-family: "微软雅黑", sans-serif;
} }
@ -101,25 +105,26 @@ header {
.header--wing { .header--wing {
left: 0; left: 0;
bottom: adjust(10px); bottom: -20px;
height: adjust(h(78px)); height: 72px;
} }
.company { .company {
margin-left: adjust(w(1460px)); margin-left: 1458px;
width: adjust(w(1320px)); width: 768px;
height: adjust(h(48px)); height: 67px;
background: url("../../assets/company.png") center/cover no-repeat; background: url("../../assets/company.png") center/cover no-repeat;
} }
.datetime { .datetime {
color: $main-color; color: $main-color;
font-size: adjust(26px); font-size: 48px;
text-align: center; text-align: center;
// display: inline-block; // display: inline-block;
margin-left: adjust(w(6150px)); left: unset;
width: adjust(w(1320px)); right: 1573px;
height: adjust(h(48px)); width: 646px;
height: 67px;
background: url("../../assets/date.png") center/cover no-repeat; background: url("../../assets/date.png") center/cover no-repeat;
} }
</style> </style>

View File

@ -0,0 +1,169 @@
<template>
<div class="bar-chart" :id="id"></div>
</template>
<script>
import * as echarts from "echarts/core";
import { BarChart } from "echarts/charts";
import {
TitleComponent,
TooltipComponent,
GridComponent,
} from "echarts/components";
import { LabelLayout, UniversalTransition } from "echarts/features";
import { CanvasRenderer } from "echarts/renderers";
echarts.use([
TitleComponent,
TooltipComponent,
GridComponent,
BarChart,
LabelLayout,
UniversalTransition,
CanvasRenderer,
]);
export default {
name: "GradientChart",
props: {
series: {
type: Array,
default: () => [],
},
},
data() {
return {
id: Math.random().toString(),
chart: null,
};
},
mounted() {
this.init();
},
watch: {
series: {
deep: true,
handler: function () {
console.log("BarChart: series changed!");
this.init();
},
},
},
methods: {
updateXAxis() {
const hour = +new Date().getHours();
return Array(24)
.fill(1)
.map((_, index) => {
if (hour - index < 0) {
return 24 + hour - index + ":00";
}
return hour - index + ":00";
})
.reverse();
},
init() {
if (!this.chart)
this.chart = echarts.init(document.getElementById(this.id));
this.chart.setOption({
grid: {
top: 32,
left: 56,
bottom: 36,
right: 20,
},
xAxis: {
type: "category",
data: this.updateXAxis(),
axisLine: {
lineStyle: {
color: "#5982b2a0",
},
},
axisTick: {
show: false,
},
axisLabel: {
color: "#fff9",
fontSize: 16,
lineHeight: 2,
margin: 12,
rotate: 30,
},
},
yAxis: {
type: "value",
// name: "/",
// nameTextStyle: {
// color: "#fff9",
// fontSize: adjust(8),
// align: "right",
// },
axisLine: {
show: true,
lineStyle: {
color: "#5982b2a0",
},
},
axisTick: {
show: false,
},
axisLabel: {
formatter: "{value} ℃",
color: "#fff9",
fontSize: 16,
lineHeight: 2,
},
splitLine: {
lineStyle: {
color: "#5982b2a0",
},
},
// data: [100, 200, 300, 400, 500],
},
series: [
{
// data: this.series,
data: Array(24)
.fill(1)
.map(() => {
let v = Math.ceil(Math.random() * 100);
while (v < 60) {
v = Math.ceil(Math.random() * 100);
}
return v;
}),
type: "bar",
barWidth: 8,
label: {
show: true,
fontSize: 14,
color: "#eee8",
position: "topRight",
rotate: 90,
offset: [5, 0],
},
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#A0FF49" },
{ offset: 0.35, color: "#49FF9A" },
{ offset: 0.7, color: "#49F2FF" },
{ offset: 1, color: "#0D6FFF" },
]),
},
},
],
});
},
},
};
</script>
<style lang="scss" scoped>
.bar-chart {
height: 100%;
}
</style>

View File

@ -0,0 +1,70 @@
<!--
filename: chart.vue
author: liubin
date: 2023-09-08 13:53:04
description:
-->
<template>
<div class="yx-dark-chart">
<LineChart
key="1"
id="line-chart-1"
class="flex-1"
unit="单位 kg/h"
:legend="Object.keys(oilTable1)"
:series="oilTable1"
/>
<div class="vertical-line"></div>
<LineChart
key="2"
id="line-chart-2"
class="flex-1"
unit="单位 kg/h"
:legend="Object.keys(oilTable2)"
:series="oilTable2"
/>
</div>
</template>
<script>
import LineChart from "./components/LineChart.vue";
import { mapState } from "vuex";
export default {
name: "YxDarkChart",
components: { LineChart },
props: ["data-source"],
data() {
return {};
},
computed: {
...mapState(["oilTable1", "oilTable2"]),
},
methods: {},
};
</script>
<style scoped lang="scss">
.yx-dark-chart {
height: 100%;
display: flex;
}
.flex-1 {
width: 1px;
flex: 1;
}
.vertical-line {
margin: 0 6px;
width: 6px;
background: radial-gradient(
ellipse at center,
#6fe2ff,
#52cbef80,
transparent,
transparent
);
}
</style>

View File

@ -0,0 +1,364 @@
<template>
<!-- line chart -->
<div class="line-chart__wrapper">
<div class="line-chart__custom-legend flex" v-if="legend.length">
<!-- <span>产线1 - 产线5</span> -->
<ul style="" class="flex">
<li v-for="(v, i) in legend" :key="i">{{ v }}</li>
</ul>
</div>
<div :id="id" style="width: 100%; height: 100%"></div>
<div
v-show="legend.length === 0"
style="
position: absolute;
top: 0;
left: 0;
background: #eee0;
width: 100%;
height: 100%;
display: grid;
place-items: center;
font-size: 24px;
color: #eee8;
user-select: none;
"
>
无数据
</div>
</div>
</template>
<script>
import * as echarts from "echarts/core";
import { LineChart } from "echarts/charts";
import {
TitleComponent,
TooltipComponent,
GridComponent,
} from "echarts/components";
import { LabelLayout, UniversalTransition } from "echarts/features";
import { CanvasRenderer } from "echarts/renderers";
echarts.use([
TitleComponent,
TooltipComponent,
GridComponent,
LineChart,
LabelLayout,
UniversalTransition,
CanvasRenderer,
]);
export default {
name: "LineChart",
props: {
id: {
type: String,
default: "line-chart",
},
config: {
type: Object,
default: () => ({
title: { text: "default chart" },
}),
},
unit: {
type: String,
default: "单位/m³",
},
legend: {
type: Array,
default: () => [],
},
series: {
type: Object,
default: () => ({}),
},
},
data() {
return {
chart: null,
colors: [
"#18c7f3",
"#FFD160",
"#F31868",
"#30E89A",
"#2760FF",
"#7138FF",
"#F318D8",
"#C0F318",
"#f77",
"#19f",
"#98f",
],
data: [],
legendtext: [
"asdfsadf",
"asdfsadf",
"asdfsadf",
"asdfsadf",
"asdfsadf",
"asdfsadf",
"asdfsadf",
"asdfsadf",
],
};
},
mounted() {
this.init();
},
watch: {
series: {
deep: true,
handler: function () {
console.log("LineChart: series changed!");
this.init();
},
},
},
methods: {
updateXAxis() {
const hour = +new Date().getHours();
return Array(24)
.fill(1)
.map((_, index) => {
if (hour - index < 0) {
return 24 + hour - index + ":00";
}
return hour - index + ":00";
})
.reverse();
},
init() {
if (!this.chart)
this.chart = echarts.init(document.getElementById(this.id));
this.chart.setOption({
grid: {
top: 54,
left: 54,
bottom: 48,
right: 24,
},
xAxis: {
data: this.updateXAxis(),
axisLine: {
lineStyle: {
color: "#5982b2a0",
},
},
axisTick: {
show: false,
},
axisLabel: {
color: "#fff9",
fontSize: 14,
lineHeight: 2,
margin: 16,
rotate: 30,
},
},
yAxis: {
type: "value",
name: this.unit,
nameTextStyle: {
color: "#fff9",
fontSize: 18,
align: "",
},
axisLine: {
show: true,
lineStyle: {
// width: 1,
color: "#5982b2a0",
},
},
axisTick: {
show: false,
},
axisLabel: {
color: "#fff9",
fontSize: 16,
lineHeight: 2,
},
splitLine: {
lineStyle: {
color: "#5982b2a0",
},
},
// data: [100, 200, 300, 400, 500],
},
color: this.colors,
// series: Array(5)
// .fill(1)
// .map((_, index) => ({
// name: Math.random(),
// type: "line",
// symbol: "circle",
// symbolSize: adjust(3),
// lineStyle: {
// width: adjust(1),
// },
// areaStyle: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// { offset: 0, color: this.colors[index] + "33" },
// { offset: 1, color: "transparent" },
// ]),
// },
// data: Array(31)
// .fill(1)
// .map(() => {
// let v = Math.floor(Math.random() * 5000);
// while (v < 3000) v = Math.floor(Math.random() * 5000);
// return v;
// }),
// })),
series: Array(this.legend.length)
.fill(1)
.map((_, index) => {
let lgd = this.legend[index];
// console.log("series: ", lgd, index, this.series[lgd]);
return {
name: lgd,
type: "line",
symbol: "circle",
symbolSize: 6,
lineStyle: {
width: 2,
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: this.colors[index] + "33" },
{ offset: 1, color: "transparent" },
]),
},
data: this.series[lgd],
};
}),
});
},
},
};
</script>
<style scoped lang="scss">
::-webkit-scrollbar {
// display: none;
height: 4px;
}
::-webkit-scrollbar-thumb {
height: 4px;
border-radius: 4px;
background: #ccc3;
}
// ::-webkit-scrollbar-track {
// height: adjust(1px);
// background: blue;
// }
ul,
li {
margin: 0;
padding: 0;
list-style: none;
min-width: 40px;
}
ul {
// padding: 0 16px;
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
align-items: center;
height: 56px;
// background: #eeec;
// overflow-x: hidden;
white-space: pre-wrap;
padding-bottom: 4px;
}
li {
text-align: right;
position: relative;
min-width: 40px;
margin-right: 18px;
padding: 0 4px;
}
li:not(:last-child) {
// margin-right: adjust(16px);
}
.line-chart__custom-legend {
position: absolute;
top: -64px;
right: 0;
font-size: 18px;
font-family: Ubuntu, sans-serif;
padding: 0;
// max-width: 100%;
width: 65%;
align-items: flex-start;
justify-content: flex-end;
}
li::before {
content: "";
position: absolute;
top: 4px;
left: -16px;
width: 16px;
height: 16px;
border-radius: 2px;
background: #eee6;
}
li:nth-child(1)::before {
background: #18c7f3;
}
li:nth-child(2)::before {
background: #ffd160;
}
li:nth-child(3)::before {
background: #f31868;
}
li:nth-child(4)::before {
background: #30e89a;
}
li:nth-child(5)::before {
background: #2760ff;
}
li:nth-child(6)::before {
background: #7138ff;
}
li:nth-child(7)::before {
background: #f318d8;
}
li:nth-child(8)::before {
background: #c0f318;
}
li:nth-child(9)::before {
background: #f77;
}
li:nth-child(10)::before {
background: #19f;
}
li:nth-child(11)::before {
background: #98f;
}
.line-chart__wrapper {
position: relative;
background: #7771;
border-radius: 6px;
backdrop-filter: blur(4px);
box-shadow: inset 0 0 20px 4px rgba($color: #fff, $alpha: 0.1);
height: 100%;
width: 2px;
}
</style>

View File

@ -0,0 +1,32 @@
<template>
<div class="table-frequence" :class="cls">{{ value }}</div>
</template>
<script>
export default {
name: "TableFrequence",
props: {
value: {
type: String,
default: '未运行'
}
},
data() {
return {
cls: {
'valid': this.value !== '未运行'
}
};
}
};
</script>
<style scoped>
.table-frequence {
font-family: Ubuntu, sans-serif !important;
}
.valid {
color: #30e89a;
}
</style>

View File

@ -0,0 +1,53 @@
<template>
<div class="table-status" :class="cls">{{ value }}</div>
</template>
<script>
export default {
name: "TableFrequence",
props: {
value: {
type: String,
default: "正常",
},
},
data() {
return {
cls: {
invalid: this.value !== "正常",
},
};
},
};
</script>
<style scoped lang="scss">
.table-status {
/* font-family: Ubuntu, sans-serif !important; */
color: #3984ff;
padding-left: 20px;
position: relative;
}
.table-status::after {
content: "";
position: absolute;
left: 2px;
top: 4px;
display: inline-block;
width: 8px;
height: 8px;
border-radius: 200px;
background: #3984ff;
box-shadow: 0px 0px 4px 4px rgba(39, 96, 255, 0.5);
}
.invalid {
color: #ff0c0c;
}
.invalid::after {
background: #ff0c0c;
box-shadow: 0px 0px 4px 4px rgba(255, 39, 39, 0.5);
}
</style>

View File

@ -0,0 +1,100 @@
<!--
filename: rect.vue
author: liubin
date: 2023-09-08 10:02:48
description:
-->
<template>
<div class="rect-container">
<section class="title" v-if="title">
<span class="icon" v-if="icon" :class="icon"></span>
<span class="title__value">{{ title }}</span>
</section>
<section class="content">
<slot />
</section>
</div>
</template>
<script>
export default {
name: "RectContainer",
components: {},
props: ["icon", "title"],
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
span {
display: inline-block;
}
.rect-container {
// background: url(../../../assets/rect-bg.png) no-repeat 100% / contain; // rgba(45, 230, 196, 0.8);
padding: 24px;
// width: 624px;
// height: 304px;
display: flex;
flex-direction: column;
}
section.title {
display: flex;
align-items: center;
margin-bottom: 12px;
}
.title__value {
font-size: 24px;
letter-spacing: 1px;
line-height: 1;
color: #7ffff5;
}
section.content {
height: 1px;
flex: 1;
overflow: visible;
}
.icon {
width: 28px;
height: 28px;
margin-right: 8px;
}
.icon-left-middle {
background: url(../../../assets/icon-left-middle.png) no-repeat 100% / contain;
}
.icon-left-bottom {
background: url(../../../assets/icon-left-bottom.png) no-repeat 100% / contain;
}
.icon-gas {
background: url(../../../assets/icon-gas.png) no-repeat 100% / contain;
}
.icon-kiln-top {
background: url(../../../assets/icon-kiln-top.png) no-repeat 100% / contain;
}
.icon-kiln-bottom {
background: url(../../../assets/icon-kiln-bottom.png) no-repeat 100% / contain;
}
.icon-right-bottom {
background: url(../../../assets/icon-right-bottom.png) no-repeat 100% /
contain;
}
.icon-right-top {
background: url(../../../assets/icon-right-top.png) no-repeat 100% / contain;
}
</style>

View File

@ -0,0 +1,237 @@
<!--
filename: table.vue
author: liubin
date: 2023-09-08 13:52:12
description:
-->
<template>
<div class="yx-dark-tables">
<div class="tables flex" style="height: 100%">
<div class="table-wrapper flex-1 align-start">
<div
v-if="tableData1 && tableData1.length === 0"
style="
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #eee1;
display: grid;
place-items: center;
font-size: 24px;
color: #eee9;
"
>
无数据
</div>
<table class="table-1">
<thead>
<tr class="t-row">
<th>序号</th>
<th>设备名称</th>
<th>运行频率</th>
<th>设备状态</th>
</tr>
</thead>
<transition-group name="fan-list" tag="tbody" mode="out-in">
<tr
class="t-row"
v-for="row in tableData1"
:key="row && 'length' in row ? row[0] : Math.random()"
>
<td v-for="(d, idx) in row" :key="idx">
<template v-if="idx === 2">
<FrequentComp :value="d" />
</template>
<template v-else-if="idx === 3">
<StatusComp :value="d" />
</template>
<template v-else>
{{ d }}
</template>
</td>
</tr>
</transition-group>
<!-- </tbody> -->
</table>
</div>
</div>
</div>
</template>
<script>
import FrequentComp from "./components/TableFrequence.vue";
import StatusComp from "./components/TableStatus.vue";
import { mapState } from "vuex";
export default {
name: "YxDarkTables",
components: { FrequentComp, StatusComp },
data() {
return {
tableHead: ["序号", "设备名称", "运行频率", "设备状态"],
tableCache: [
[16, "风机16", "未运行", "正常" /**or 0,1*/],
[17, "风机17", "未运行", "正常" /**or 0,1*/],
[17, "风机18", "73Hz", "正常" /**or 0,1*/],
],
tableData1: [
[1, "风机1", "2332Hz", "正常" /**or 0,1*/],
[2, "风机2", "未运行", "故障" /**or 0,1*/],
[3, "风机3", "333Hz", "正常" /**or 0,1*/],
[4, "风机4", "100Hz", "正常" /**or 0,1*/],
[5, "风机5", "未运行", "正常" /**or 0,1*/],
[6, "风机6", "未运行", "故障" /**or 0,1*/],
[7, "风机7", "3000Hz", "正常" /**or 0,1*/],
[8, "风机8", "未运行", "正常" /**or 0,1*/],
[9, "风机9", "未运行", "正常" /**or 0,1*/],
[10, "风机10", "86423Hz", "正常" /**or 0,1*/],
[11, "风机11", "未运行", "正常" /**or 0,1*/],
[12, "风机12", "未运行", "正常" /**or 0,1*/],
[13, "风机13", "73Hz", "正常" /**or 0,1*/],
[14, "风机14", "未运行", "正常" /**or 0,1*/],
[15, "风机15", "未运行", "正常" /**or 0,1*/],
],
};
},
computed: {
...mapState(["fan"]),
},
watch: {
// fan: {
// handler: function (data) {
// if (!data) return;
// let idx = 0;
// this.tableData1 = data.slice(0, 10).map((item, index) => {
// idx += 1;
// return [idx, ...item];
// });
// this.tableCache = data
// .slice(10)
// .map((item, index) => [index + 1 + idx, ...item]);
// },
// deep: true,
// immediate: true,
// },
},
mounted() {
setInterval(() => {
const inData = this.tableCache.shift();
const outData = this.tableData1.shift();
setTimeout(() => {
if (inData) this.tableData1.splice(this.tableData1.length, 0, inData);
}, 200);
if (outData) this.tableCache.push(outData);
}, 3000);
},
};
</script>
<style scoped lang="scss">
.yx-dark-tables {
height: 100%;
// background: #fff3;
}
::-webkit-scrollbar {
width: 6px;
background: #eee1;
}
::-webkit-scrollbar-thumb {
width: 6px;
border-radius: 8px;
background: #eee3;
}
.fan-list-enter-active,
.fan-list-leave-active {
transition: all 0.5s;
}
// .fan-list-leave-move {
// transition: all 1s;
// }
.fan-list-enter,
.fan-list-leave-to {
opacity: 0;
transform: scaleY(0);
}
.flex-1 {
flex: 1;
}
.vertical-line {
margin: 0 6px;
width: 6px;
background: radial-gradient(
ellipse at center,
#6fe2ff,
#52cbef80,
transparent,
transparent
);
}
.table-wrapper {
// padding-right: 6px;
// height: 480px;
height: 100%;
// overflow-y: auto;
overflow: hidden;
}
table {
width: 100%;
border-spacing: 2px;
}
// tr, td, th {
// max-height: 13.88px !important;
// }
.t-row {
height: 28px;
}
.tables > table {
overflow-y: auto;
}
.align-start {
align-self: flex-start;
}
thead > tr th:first-child {
text-align: center;
}
thead > tr th {
font-size: 20px;
line-height: 1.5;
padding: 6px 16px;
font-weight: 400;
background: #044a8446;
text-align: left;
}
tbody > tr:nth-child(odd) {
background: #0b549960;
}
tbody > tr td {
font-size: 20px;
line-height: 1.25;
padding: 4px 16px;
font-weight: 400;
background: inherit;
}
tbody > tr td:first-child {
text-align: center;
}
</style>

View File

@ -0,0 +1,130 @@
<template>
<header class="header">
<div>
<span class="header--logo">
<!-- <img src="../../assets/logo.png" alt="logo"> -->
</span>
<h1>宜兴三期生产线大数据指挥中心</h1>
</div>
<span class="header--wing absolute company"></span>
<span class="header--wing absolute datetime">
{{ moment(today).format("YYYY.M.D dddd HH:mm:ss") }}
</span>
</header>
</template>
<script>
import moment from "moment";
export default {
name: "Header",
data() {
return {
today: new Date(),
time: "00:00:00",
moment,
};
},
computed: {
date() {
return this.today.toLocaleDateString().replaceAll("/", ".");
},
week() {
return [
"星期日",
"星期一",
"星期二",
"星期三",
"星期四",
"星期五",
"星期六",
][this.today.getDay()];
},
},
mounted() {
moment.locale("zh-cn");
// this.time = this.getTime().join(":");
setInterval(() => {
this.today = new Date();
// this.time = this.getTime().join(":");
}, 1000);
},
methods: {
getTime() {
const now = new Date();
return [
now.getHours() < 10 ? "0" + now.getHours() : now.getHours() + "",
now.getMinutes() < 10 ? "0" + now.getMinutes() : now.getMinutes() + "",
now.getSeconds() < 10 ? "0" + now.getSeconds() : now.getSeconds() + "",
];
},
},
};
</script>
<style scoped lang="scss">
@import "../../../assets/styles/functions";
@import "../../../assets/styles/variables";
header {
position: absolute;
width: 100%;
top: 0;
left: 0;
z-index: 10000;
background: url(../../../assets/header.png) no-repeat;
background-position: center;
background-size: contain;
// background-size: 100%;
height: 146px;
display: grid;
place-content: center;
> div {
display: flex;
align-items: center;
margin-bottom: 0;
.header--logo {
margin-top: 12px;
width: 64px;
height: 94px;
background: url(../../../assets/logo.png) center/contain no-repeat;
}
h1 {
margin-left: 36px;
font-size: 72px;
user-select: none;
letter-spacing: 14px;
font-weight: 400;
color: $main-color;
font-family: "微软雅黑", sans-serif;
}
}
}
.header--wing {
left: 0;
bottom: -20px;
height: 72px;
}
.company {
margin-left: 1458px;
width: 768px;
height: 67px;
background: url("../../../assets/company.png") center/cover no-repeat;
}
.datetime {
color: $main-color;
font-size: 48px;
text-align: center;
// display: inline-block;
left: unset;
right: 1573px;
width: 646px;
height: 67px;
background: url("../../../assets/date.png") center/cover no-repeat;
}
</style>

View File

@ -0,0 +1,952 @@
{
"baseInfo": {
"fireChangeTime": "20分钟",
"waterInTemp": "75.0",
"lastFireChangeTime": "10分15秒",
"kilnPressure": "94.0",
"fireDirection": "南火",
"waterOutTemp": "26.0"
},
"fan": [
[
"8#压延冷却风机",
"4373Hz",
"正常"
],
[
"7#压延冷却风机",
"4772Hz",
"正常"
],
[
"6#压延冷却风机",
"1704Hz",
"正常"
],
[
"5#压延冷却风机",
"3109Hz",
"正常"
],
[
"4#压延冷却风机",
"2595Hz",
"正常"
],
[
"3#压延冷却风机",
"8903Hz",
"正常"
],
[
"2#压延冷却风机",
"3741Hz",
"正常"
],
[
"1#压延冷却风机",
"9035Hz",
"正常"
],
[
"4#熔化部风机",
"5223Hz",
"正常"
],
[
"3#熔化部风机",
"9722Hz",
"正常"
],
[
"2#熔化部风机",
"9617Hz",
"正常"
],
[
"1#熔化部风机",
"7135Hz",
"正常"
],
[
"4#澄清部风机",
"1699Hz",
"正常"
],
[
"3#澄清部风机",
"2511Hz",
"正常"
],
[
"2#澄清部风机",
"9780Hz",
"正常"
],
[
"1#澄清部风机",
"3809Hz",
"正常"
],
[
"2#助燃风机",
"435Hz",
"正常"
],
[
"1#助燃风机",
"6270Hz",
"正常"
],
[
"2#L吊墙风机",
"8181Hz",
"正常"
],
[
"1#L吊墙风机",
"5587Hz",
"正常"
],
[
"2#钢碹碴池壁风机",
"6652Hz",
"正常"
],
[
"1#钢碹碴池壁风机",
"2000Hz",
"正常"
],
[
"2#池壁拐角风机",
"1972Hz",
"正常"
],
[
"1#池壁拐角风机",
"7730Hz",
"正常"
]
],
"gas": {
"kilnGasT1": {
"FE111R": [
53.02,
69.84,
99.33,
17.21,
1.17,
27.84,
95.44,
30.72,
32.24,
64.16,
59.65,
14.59,
78.58,
99.15,
58.91,
34.13,
99.62,
2.23,
28.31,
91.17,
97.15,
60.62,
94.12,
23.24
],
"FE113R": [
22.04,
40.78,
75.62,
61.01,
72.7,
48.46,
32.44,
42.51,
59.61,
22.86,
32.95,
21.32,
23.59,
84.16,
55.14,
55.71,
10.81,
56.53,
75.51,
2.85,
27.77,
52.42,
43.34,
22.04
],
"FE112R": [
77.02,
13.83,
1.71,
53.99,
4.03,
1,
22.17,
61.73,
11.25,
31.69,
90.31,
69.26,
68.72,
80.79,
3.08,
39.17,
12.6,
35.31,
97.2,
38.77,
27.5,
11.78,
72.32,
23.13
],
"FE115R": [
28.31,
10.16,
13.22,
41.44,
97.19,
60.08,
34.13,
16.75,
92.7,
79.48,
3.08,
14.71,
4.4,
0.88,
77.6,
57,
31,
86.14,
44.31,
45.7,
6.85,
65.62,
77.97,
49.2
],
"FE114R": [
17.72,
32.45,
1.42,
24.51,
68.57,
61.48,
2.08,
3.1,
38.27,
20.07,
25.71,
85.58,
48.31,
78.14,
22.43,
87.47,
83.78,
17.66,
72.36,
19,
20.69,
33.92,
25.66,
91.28
],
"FE117R": [
47.8,
62.27,
90.23,
28.31,
73.09,
34.04,
9.03,
44.69,
32.62,
25.78,
27.79,
25.42,
28.96,
56.52,
75.43,
50.56,
90.22,
11.85,
4.56,
39.9,
9.83,
65.98,
91.22,
92.43
],
"FE116R": [
64.79,
46.14,
58.67,
54.46,
15.67,
72.02,
15.06,
5.88,
38.19,
66.98,
89.24,
33.13,
87.57,
43.95,
55.06,
93.26,
96.91,
56.5,
20.75,
83.76,
60.88,
62.04,
22.34,
82.43
],
"FE118R": [
94.32,
86.26,
5.13,
47.33,
40.01,
34.97,
18.69,
81.81,
87.37,
96.47,
16.04,
23.33,
0.66,
16.86,
13.19,
67.32,
37.63,
13.74,
22.85,
78.89,
9.52,
75.46,
0.2,
1.51
]
},
"kilnGasT2": {
"FE124R": [
53.02,
69.84,
99.33,
17.21,
1.17,
27.84,
95.44,
30.72,
32.24,
64.16,
59.65,
14.59,
78.58,
99.15,
58.91,
34.13,
99.62,
2.23,
28.31,
91.17,
97.15,
60.62,
94.12,
23.24
],
"FE123aR": [
17.72,
32.45,
1.42,
24.51,
68.57,
61.48,
2.08,
3.1,
38.27,
20.07,
25.71,
85.58,
48.31,
78.14,
22.43,
87.47,
83.78,
17.66,
72.36,
19,
20.69,
33.92,
25.66,
91.28
],
"FE123R": [
77.02,
13.83,
1.71,
53.99,
4.03,
1,
22.17,
61.73,
11.25,
31.69,
90.31,
69.26,
68.72,
80.79,
3.08,
39.17,
12.6,
35.31,
97.2,
38.77,
27.5,
11.78,
72.32,
23.13
],
"FE124aR": [
22.04,
40.78,
75.62,
61.01,
72.7,
48.46,
32.44,
42.51,
59.61,
22.86,
32.95,
21.32,
23.59,
84.16,
55.14,
55.71,
10.81,
56.53,
75.51,
2.85,
27.77,
52.42,
43.34,
22.04
],
"FE126R": [
64.79,
46.14,
58.67,
54.46,
15.67,
72.02,
15.06,
5.88,
38.19,
66.98,
89.24,
33.13,
87.57,
43.95,
55.06,
93.26,
96.91,
56.5,
20.75,
83.76,
60.88,
62.04,
22.34,
82.43
],
"FE125aR": [
47.8,
62.27,
90.23,
28.31,
73.09,
34.04,
9.03,
44.69,
32.62,
25.78,
27.79,
25.42,
28.96,
56.52,
75.43,
50.56,
90.22,
11.85,
4.56,
39.9,
9.83,
65.98,
91.22,
92.43
],
"FE125R": [
28.31,
10.16,
13.22,
41.44,
97.19,
60.08,
34.13,
16.75,
92.7,
79.48,
3.08,
14.71,
4.4,
0.88,
77.6,
57,
31,
86.14,
44.31,
45.7,
6.85,
65.62,
77.97,
49.2
],
"FE126aR": [
94.32,
86.26,
5.13,
47.33,
40.01,
34.97,
18.69,
81.81,
87.37,
96.47,
16.04,
23.33,
0.66,
16.86,
13.19,
67.32,
37.63,
13.74,
22.85,
78.89,
9.52,
75.46,
0.2,
1.51
]
}
},
"kilnBottom": {
"kilnTempBottomT1": {
"TE316": [
44,
49,
20,
29,
96,
76,
20,
82,
28,
86,
69,
18,
23,
58,
83,
84,
94,
99,
36,
51,
32
],
"TE315": [
84,
61,
87,
82,
33,
9,
20,
23,
81,
0,
16,
81,
9,
78,
30,
16,
49,
16,
95,
53,
19
],
"TE314": [
45,
93,
11,
47,
27,
69,
91,
17,
0,
67,
60,
15,
84,
36,
89,
30,
36,
90,
38,
94,
87
],
"TE313": [
60,
9,
59,
15,
43,
41,
83,
93,
99,
91,
29,
47,
2,
40,
65,
39,
12,
20,
57,
64,
95
],
"TE312": [
22,
46,
93,
69,
44,
3,
62,
49,
4,
18,
87,
76,
36,
16,
50,
36,
54,
90,
1,
66,
68
]
},
"kilnTempBottomT2": {
"TE319": [
48,
56,
40,
44,
31,
82,
35,
36,
0,
84,
49,
38,
28,
34,
98,
60,
4,
69,
15,
86,
19
],
"TE318": [
7,
30,
57,
78,
47,
99,
1,
98,
47,
86,
55,
10,
98,
27,
97,
85,
54,
41,
27,
85,
44
],
"TE317": [
72,
13,
7,
69,
77,
36,
6,
34,
97,
48,
75,
29,
75,
4,
70,
80,
31,
10,
39,
86,
52
],
"TE321": [
6,
60,
32,
19,
79,
99,
98,
81,
82,
68,
3,
94,
7,
29,
48,
52,
36,
59,
28,
77,
17
],
"TE320": [
23,
47,
4,
15,
7,
74,
75,
60,
78,
89,
15,
95,
74,
85,
20,
48,
79,
51,
63,
82,
68
]
}
},
"kilnTop": {
"kilnTempTopT2": {
"TE215": [
81,
12,
86,
55,
50,
59,
20,
67,
66,
29,
17,
74,
11,
12,
63,
23,
34,
86,
9,
38,
99,
3,
33,
77
],
"TE214": [
51,
12,
49,
60,
3,
67,
95,
62,
22,
89,
69,
14,
41,
79,
77,
27,
26,
34,
69,
44,
89,
86,
92,
1
],
"TE213": [
76,
14,
35,
1,
36,
67,
40,
5,
53,
98,
46,
29,
71,
12,
43,
42,
53,
56,
9,
17,
34,
42,
82,
73
]
},
"kilnTempTopT1": {
"TE209": [
51,
12,
49,
60,
3,
67,
95,
62,
22,
89,
69,
14,
41,
79,
77,
27,
26,
34,
69,
44,
89,
86,
92,
1
],
"TE208": [
76,
14,
35,
1,
36,
67,
40,
5,
53,
98,
46,
29,
71,
12,
43,
42,
53,
56,
9,
17,
34,
42,
82,
73
],
"TE210": [
81,
12,
86,
55,
50,
59,
20,
67,
66,
29,
17,
74,
11,
12,
63,
23,
34,
86,
9,
38,
99,
3,
33,
77
]
}
}
}

View File

@ -0,0 +1,67 @@
import { WebSocket, WebSocketServer } from "ws";
import demoData from "./demo.json";
const wss = new WebSocketServer({ port: 9800 });
const frequency = 3; // seconds
wss.on("connection", function (ws, req) {
// console.log("ws", ws);
console.log(
"Client in: ",
req.socket.remoteAddress,
"current users:",
wss.clients.size
);
// ws.on("error", console.error);
// ws.emit("message", "connected");
ws.on("open", function () {
console.log("connected");
ws.send("connected");
});
ws.on("message", function (msg) {
console.log("message from client", msg);
ws.send("echo " + msg.toString());
});
ws.on("error", console.error);
const timer = setInterval(() => {
sendMsg(ws, "base-info");
sendMsg(ws, "fan");
sendMsg(ws, "gas");
sendMsg(ws, "kiln-top");
sendMsg(ws, "kiln-bottom");
}, frequency * 1000);
ws.on("close", function () {
console.log("停止监听");
clearInterval(timer);
});
});
type MsgType = "base-info" | "fan" | "gas" | "kiln-top" | "kiln-bottom";
function sendMsg(ws: WebSocket, type: MsgType) {
let data: any;
switch (type) {
case "base-info":
data = demoData.baseInfo;
break;
case "fan":
data = demoData.fan;
break;
case "gas":
data = demoData.gas;
break;
case "kiln-top":
data = demoData.kilnTop;
break;
case "kiln-bottom":
data = demoData.kilnBottom;
break;
default:
data = "You are connected!";
break;
}
// console.log("sendMsg: ", ws);
// ws.emit("message", JSON.stringify(data));
ws.send(JSON.stringify(data));
}

View File

@ -0,0 +1,109 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
/* Projects */
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
"resolveJsonModule": true, /* Enable importing .json files. */
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}

View File

@ -0,0 +1,101 @@
<!--
filename: widgetContainer.vue
author: liubin
date: 2023-09-08 13:31:18
description:
-->
<template>
<div class="yx-dark-widget-container">
<div class="icon" :class="iconClass"></div>
<div class="content">
<div class="title">{{ title }}</div>
<div class="value">{{ value }}</div>
</div>
</div>
</template>
<script>
export default {
name: "YxDarkWidgetContainer",
components: {},
props: ["title", "value", "icon"],
data() {
return {};
},
computed: {
iconClass() {
switch (this.icon) {
case "1":
return "icon-1";
case "2":
return "icon-2";
case "3":
return "icon-3";
case "4":
return "icon-4";
}
},
},
methods: {},
};
</script>
<style scoped lang="scss">
.yx-dark-widget-container {
width: 200px;
height: 98px;
border-radius: 4px;
box-shadow: inset 0 0 17px 0 #fff8;
// background: url(../../../assets/) 100% / contain no-repeat;
display: flex;
padding: 4px;
align-items: flex-start;
}
.icon {
width: 58px;
height: 58px;
background: #cfcfff;
// background: url(../../../assets/) 100% / contain no-repeat;
}
.content {
// padding-left: 12px;
display: flex;
flex-direction: column;
// justify-content: center;
align-items: flex-start;
height: 100%;
}
.title {
padding-top: 14px;
font-size: 14px;
line-height: 1;
color: #fffa;
}
.value {
padding-top: 10px;
font-size: 32px;
line-height: 34px;
color: #fff;
}
.icon-1 {
background: url(../../../../assets/icon-1.png) 100% / contain no-repeat;
}
.icon-2 {
background: url(../../../../assets/icon-2.png) 100% / contain no-repeat;
}
.icon-3 {
background: url(../../../../assets/icon-3.png) 100% / contain no-repeat;
}
.icon-4 {
background: url(../../../../assets/icon-4.png) 100% / contain no-repeat;
}
</style>

View File

@ -0,0 +1,41 @@
<!--
filename: index.vue
author: liubin
date: 2023-09-08 13:30:13
description: 放在这中间的小组件
-->
<template>
<div class="base-info">
<BaseInfoContainer icon="1" title="车间温度" value="27℃" />
<BaseInfoContainer icon="2" title="当前火向" value="东火" />
<BaseInfoContainer icon="3" title="换火时间" value="12:23:33" />
<BaseInfoContainer icon="4" title="剩余时间" value="6h" />
</div>
</template>
<script>
import BaseInfoContainer from "@/components/yx-dark/widget/baseInfo/baseInfoContainer.vue";
export default {
name: "BaseInfo",
components: { BaseInfoContainer },
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.base-info {
display: flex;
gap: 16px;
// position: absolute;
// top: 80px;
// left: 50%;
// transform: translateX(-50%);
}
</style>

View File

@ -0,0 +1,65 @@
<!--
filename: index.vue
author: liubin
date: 2023-09-08 16:13:14
description:
-->
<template>
<div class="yx-dark-press-info">
<template v-for="ch in pressInfo">
<YxDarkPressContainer
v-if="!isDot(ch)"
:key="ch"
:value="ch"
:class="{ digit: isDigit(ch) }"
/>
<span class="dot" v-else>.</span>
</template>
</div>
</template>
<script>
import YxDarkPressContainer from "./pressContainer.vue";
export default {
name: "YxDarkPressInfo",
components: { YxDarkPressContainer },
props: {},
data() {
return {
press: 12.2,
};
},
computed: {
pressInfo() {
return ["压", "力", ...(this.press + ""), "Pa"];
},
},
methods: {
isDigit(ch) {
return ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"].includes(ch);
},
isDot(ch) {
return ch === ".";
},
},
};
</script>
<style scoped lang="scss">
.yx-dark-press-info {
display: flex;
gap: 8px;
}
.dot {
font-size: 72px;
line-height: 90px;
font-family: "zcoolqingkehuangyouti-Regular", sans-serif;
}
.digit {
font-size: 80px;
line-height: 80px;
}
</style>

View File

@ -0,0 +1,38 @@
<!--
filename: pressContainer.vue
author: liubin
date: 2023-09-08 16:10:43
description:
-->
<template>
<div class="yx-dark-press-container">
{{ value }}
</div>
</template>
<script>
export default {
name: "YxDarkPressContainer",
components: {},
props: ["value"],
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.yx-dark-press-container {
width: 60px;
height: 80px;
text-align: center;
padding-left: 6px;
font-size: 48px;
line-height: 90px;
font-family: "zcoolqingkehuangyouti-Regular", sans-serif;
background: url(../../../../assets/digit-bg.png) 100% / contain no-repeat;
}
</style>

View File

@ -0,0 +1,65 @@
<!--
filename: index.vue
author: liubin
date: 2023-09-08 16:13:14
description:
-->
<template>
<div class="yx-dark-runtime-info">
<template v-for="ch in pressInfo">
<YxDarkRuntimeContainer
v-if="!isDot(ch)"
:key="ch"
:value="ch"
:class="{ digit: isDigit(ch) }"
/>
<span class="dot" v-else>.</span>
</template>
</div>
</template>
<script>
import YxDarkRuntimeContainer from "./runtimeContainer.vue";
export default {
name: "YxDarkRuntimeInfo",
components: { YxDarkRuntimeContainer },
props: {},
data() {
return {
days: 122,
};
},
computed: {
pressInfo() {
return ["运", "行", ...(this.days + ""), "天"];
},
},
methods: {
isDigit(ch) {
return ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"].includes(ch);
},
isDot(ch) {
return ch === ".";
},
},
};
</script>
<style scoped lang="scss">
.yx-dark-runtime-info {
display: flex;
gap: 8px;
}
.dot {
font-size: 72px;
line-height: 90px;
font-family: "zcoolqingkehuangyouti-Regular", sans-serif;
}
.digit {
font-size: 80px;
line-height: 80px;
}
</style>

View File

@ -0,0 +1,38 @@
<!--
filename: pressContainer.vue
author: liubin
date: 2023-09-08 16:10:43
description:
-->
<template>
<div class="yx-dark-runtime-container">
{{ value }}
</div>
</template>
<script>
export default {
name: "YxDarkRuntimeContainer",
components: {},
props: ["value"],
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.yx-dark-runtime-container {
width: 60px;
height: 80px;
text-align: center;
padding-left: 6px;
font-size: 48px;
line-height: 90px;
font-family: "zcoolqingkehuangyouti-Regular", sans-serif;
background: url(../../../../assets/digit-bg.png) 100% / contain no-repeat;
}
</style>

View File

@ -0,0 +1,73 @@
<!--
filename: WaterTemp.vue
author: liubin
date: 2023-09-08 10:00:10
description: 进出口水温
-->
<template>
<div class="water-temp">
<div class="in">
<span class="value"> {{ inValue }}<small></small> </span>
<span class="title">进口实时水温</span>
</div>
<div class="out">
<span class="value"> {{ outValue }}<small></small> </span>
<span class="title">出口实时水温</span>
</div>
</div>
</template>
<script>
export default {
name: "WaterTemp",
components: {},
props: {},
data() {
return {
inValue: 22.3,
outValue: 23.4,
};
},
computed: {},
methods: {},
};
</script>
<style lang="scss" scoped>
.water-temp {
margin-left: 12px;
margin-top: 24px;
width: 500px;
// height: 120px;
// background: #cccc;
display: flex;
justify-content: space-between;
}
.in,
.out {
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.title {
font-size: 24px;
line-height: 32px;
color: #eff0f5;
margin-top: 8px;
letter-spacing: .5px;
}
.value {
font-size: 54px;
line-height: 48px;
color: #eff0f5;
letter-spacing: 1px;
}
.value > small {
font-size: 32px;
}
</style>

View File

@ -39,7 +39,8 @@ function handleClose(data) {
export default class WsClient { export default class WsClient {
static wsServer = 'ws://172.16.1.112:8081/dz-screen/websocket/1' // static wsServer = 'ws://172.16.1.112:8081/dz-screen/websocket/1'
static wsServer = 'ws://127.0.0.1:9800'
// static wsServer = 'ws://m306416y13.yicp.fun:48978/dz-screen/websocket/1' // static wsServer = 'ws://m306416y13.yicp.fun:48978/dz-screen/websocket/1'
static tableMap = { static tableMap = {
// 窑顶温度 // 窑顶温度

View File

@ -1,39 +1,151 @@
<template> <template>
<div class="home-view"> <!-- transform: 'scale(0.18182, 0.25)', -->
<!-- :style="{
transform: 'scale(0.72727, 1)',
transformOrigin: 'top left',
}" -->
<div class="home-view" :style="styles">
<!-- <div class="bg-layer"></div> -->
<LeftSide />
<section class="center">
<BigHeader /> <BigHeader />
<Main /> <MainPanel style="height: 1px; flex: 1" />
<!-- <Main /> -->
</section>
<RightSide />
</div> </div>
</template> </template>
<script> <script>
import BigHeader from '../components/layout/Header.vue' import BigHeader from "../components/yx-dark/layout/Header.vue";
import Main from '../components/layout/Main.vue' import Main from "../components/layout/Main.vue";
import LeftSide from "./LeftSide.vue";
import RightSide from "./RightSide.vue";
import MainPanel from "./MainPanel.vue";
import WsClient from "../utils/wsClass";
export default { export default {
name: "HomeView", name: "HomeView",
components: { BigHeader, Main }, components: { BigHeader, Main, LeftSide, RightSide, MainPanel },
props: {}, props: {},
data() { data() {
return {}; return {
value: 20,
};
},
computed: {
styles() {
let v = (this.value / 100).toFixed(2);
return {
// transform: `scale(${(v * 24) / 33}, ${v})`,
transform: `scale(${v}, ${v})`,
transformOrigin: "top left",
};
},
},
created() {
// const wsc = new WsClient(this);
// wsc.registerListeners();
},
mounted() {
const slider = document.createElement("div");
slider.id = "slider";
slider.classList.add("slider");
const ranger = document.createElement("input");
ranger.type = "range";
ranger.value = this.value;
ranger.addEventListener("input", this.handleSlide);
slider.appendChild(ranger);
document.body.appendChild(slider);
// this.$watch('value', val => {
// ranger.value = val
// })
document.addEventListener("keydown", (e) => {
if (e.shiftKey && e.key === "L") {
document.getElementById("slider").classList.toggle("show");
}
});
document.getElementById("slider").addEventListener("mouseleave", () => {
setTimeout(() => {
document.getElementById("slider").classList.remove("show");
}, 200);
});
},
methods: {
handleSlide(e) {
this.value = e.target.value;
window.scroll(0, 0);
},
}, },
created() {},
mounted() {},
methods: {},
}; };
</script> </script>
<style scoped lang="scss"> <style lang="scss">
@import '../assets/styles/functions'; @import "../assets/styles/functions";
* {
user-select: none;
}
.home-view { .home-view {
// width: 100vw; height: 1080px;
// height: 100vh; width: 8640px;
height: adjust($actual_height);
width: adjust($actual_width);
overflow: hidden; overflow: hidden;
// background: #C9CCE5;
background: url(../assets/bg.png) center/cover no-repeat; background: url(../assets/bg.png) center/cover no-repeat;
color: white; color: white;
display: flex; display: flex;
position: relative;
}
.bg-layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #c9cce577;
// background: url(../assets/bg.png) center/cover no-repeat;
}
.center {
position: relative;
width: 6592px;
// flex: 1;
display: flex;
flex-direction: column; flex-direction: column;
} }
.slider {
height: 5vh;
width: 20vw;
border-radius: 88px;
box-shadow: 0 0 68px 8px rgba($color: #000000, $alpha: 0.3);
padding: 32px;
display: grid;
place-items: center;
background: #fff;
position: fixed;
// bottom: 64px;
top: 0;
opacity: 0;
left: 50%;
transform: translateX(-50%);
transition: opacity 0.3s ease-out, bottom 0.3s ease-out;
input {
width: 100%;
transform: translateY(-7px);
color: #0b58ff;
background: #fcc;
}
}
.slider.show {
opacity: 1;
bottom: 64px;
}
</style> </style>

26
src/views/LeftSide.vue Normal file
View File

@ -0,0 +1,26 @@
<template>
<div class="left-side"></div>
</template>
<script>
export default {
name: "LeftSide",
props: {},
data() {
return {};
},
created() {},
mounted() {},
methods: {},
};
</script>
<style scoped lang="scss">
// import
.left-side {
background: #000;
height: 1080px;
width: 1024px;
}
</style>

53
src/views/MainArea.vue Normal file
View File

@ -0,0 +1,53 @@
<!--
filename: MainArea.vue
author: liubin
date: 2023-09-08 13:23:03
description:
-->
<template>
<div class="main-area">
<PressInfo />
<BaseInfo />
<RuntimeInfo />
</div>
</template>
<script>
import BaseInfo from "@/components/yx-dark/widget/baseInfo/index.vue";
import PressInfo from "@/components/yx-dark/widget/pressInfo/index.vue";
import RuntimeInfo from "@/components/yx-dark/widget/runtimeInfo/index.vue";
export default {
name: "MainArea",
components: { BaseInfo, PressInfo, RuntimeInfo },
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.main-area {
position: relative;
display: flex;
justify-content: center;
gap: 240px;
padding-top: 96px;
overflow: visible;
}
.main-area::after {
content: '';
display: inline-block;
background: url("../assets/main-area-bg.png") 100% / 100% no-repeat;
position: absolute;
top: 128px;
left: -560px;
width: 130%;
height: 100%;
}
</style>

181
src/views/MainPanel.vue Normal file
View File

@ -0,0 +1,181 @@
<!--
filename: MainPanel.vue
author: liubin
date: 2023-09-08 10:00:10
description:
-->
<template>
<div class="main-panel">
<RectContainer class="leftTop">
<WaterTemp />
</RectContainer>
<RectContainer class="leftMiddle" title="窑炉进口水温历史" icon="icon-left-middle">
<GradientChart />
</RectContainer>
<!-- <RectContainer class="leftBottom">
<ChartContainer />
</RectContainer> -->
<RectContainer class="bottom-1 bg-bottom" title="油流量" icon="icon-left-bottom">
<ChartContainer />
</RectContainer>
<RectContainer class="bottom-2 bg-bottom" title="天然气流量" icon="icon-gas">
<ChartContainer />
</RectContainer>
<RectContainer class="bottom-3 bg-bottom" title="窑顶温度" icon="icon-kiln-top">
<ChartContainer />
</RectContainer>
<RectContainer class="bottom-4 bg-bottom" title="窑底温度" icon="icon-kiln-bottom">
<ChartContainer />
</RectContainer>
<RectContainer class="bottom-5 bg-bottom" title="锡槽温度" icon="icon-right-bottom">
<ChartContainer />
</RectContainer>
<!-- <RectContainer class="bottom-6">
<TablesContainer />
</RectContainer>
<RectContainer class="bottom-7">
<ChartContainer />
</RectContainer>
<RectContainer class="bottom-8">
<ChartContainer />
</RectContainer> -->
<RectContainer class="rightTop" title="风机运行情况" icon="icon-right-top">
<TablesContainer />
</RectContainer>
<!-- <RectContainer class="rightMiddle">
<TablesContainer />
</RectContainer>
<RectContainer class="rightBottom">
<ChartContainer />
</RectContainer> -->
<MainArea style="grid-area: main" />
</div>
</template>
<script>
import RectContainer from "@/components/yx-dark/containers/rect.vue";
import MainArea from "./MainArea.vue";
import ChartContainer from "@/components/yx-dark/containers/chart.vue";
import TablesContainer from "@/components/yx-dark/containers/table.vue";
import GradientChart from "@/components/yx-dark/chart/gradientChart.vue";
import WaterTemp from "@/components/yx-dark/widget/waterTemp/index.vue";
export default {
name: "MainPanel",
components: {
RectContainer,
MainArea,
ChartContainer,
TablesContainer,
WaterTemp,
GradientChart,
},
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.main-panel {
// background: #cccc;
padding: 0 0 14px;
position: relative;
// top: -28px; //
display: grid;
gap: 32px;
place-content: end center;
// grid-auto-columns: 624px;
// grid-auto-rows: 304px;
// grid-template-areas:
// "leftTop main main main main main main main main rightTop "
// "leftMiddle main main main main main main main main rightMiddle "
// "leftBottom BottomOne BottomTwo BottomThree BottomFour BottomFive BottomSix BottomSeven BottomEight rightBottom ";
grid-auto-columns: 1282px;
grid-template-rows: 215px 409px 314px;
grid-template-areas:
"leftTop main main main rightTop "
"leftMiddle main main main rightTop "
"BottomOne BottomTwo BottomThree BottomFour BottomFive ";
}
.main-area {
grid-area: main;
}
.leftTop {
grid-area: leftTop;
// justify-self: end;
width: 729px;
background: url(../assets/left-top-bg.png) 100% / contain no-repeat;
}
.leftMiddle {
grid-area: leftMiddle;
width: 729px;
background: url(../assets/left-middle-bg.png) 100% / contain no-repeat;
}
.bg-bottom {
background: url(../assets/bottom-bg.png) 100% / contain no-repeat;
}
.leftBottom {
grid-area: leftBottom;
justify-self: end;
}
.rightTop {
grid-area: rightTop;
justify-self: end;
width: 623px;
background: url(../assets/right-top-bg.png) 100% / contain no-repeat;
}
.rightMiddle {
grid-area: rightMiddle;
}
.rightBottom {
grid-area: rightBottom;
}
.bottom-1 {
grid-area: BottomOne;
}
.bottom-2 {
grid-area: BottomTwo;
}
.bottom-3 {
grid-area: BottomThree;
}
.bottom-4 {
grid-area: BottomFour;
}
.bottom-5 {
grid-area: BottomFive;
}
.bottom-6 {
grid-area: BottomSix;
}
.bottom-7 {
grid-area: BottomSeven;
}
.bottom-8 {
grid-area: BottomEight;
}
</style>

26
src/views/RightSide.vue Normal file
View File

@ -0,0 +1,26 @@
<template>
<div class="right-side"></div>
</template>
<script>
export default {
name: "RightSide",
props: {},
data() {
return {};
},
created() {},
mounted() {},
methods: {},
};
</script>
<style scoped lang="scss">
// import
.right-side {
background: #000;
height: 1080px;
width: 1024px;
}
</style>

View File

@ -1198,10 +1198,10 @@
"resolved" "https://registry.npmmirror.com/@types/minimist/-/minimist-1.2.2.tgz" "resolved" "https://registry.npmmirror.com/@types/minimist/-/minimist-1.2.2.tgz"
"version" "1.2.2" "version" "1.2.2"
"@types/node@*": "@types/node@*", "@types/node@^20.6.0":
"integrity" "sha512-O+z53uwx64xY7D6roOi4+jApDGFg0qn6WHcxe5QeqjMaTezBO/mxdfFXIVAVVyNWKx84OmPB3L8kbVYOTeN34A==" "integrity" "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg=="
"resolved" "https://registry.npmmirror.com/@types/node/-/node-20.1.0.tgz" "resolved" "https://registry.npmjs.org/@types/node/-/node-20.6.0.tgz"
"version" "20.1.0" "version" "20.6.0"
"@types/normalize-package-data@^2.4.0": "@types/normalize-package-data@^2.4.0":
"integrity" "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==" "integrity" "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw=="
@ -1258,10 +1258,10 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/ws@^8.5.1": "@types/ws@^8.5.1", "@types/ws@^8.5.5":
"integrity" "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==" "integrity" "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg=="
"resolved" "https://registry.npmmirror.com/@types/ws/-/ws-8.5.4.tgz" "resolved" "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz"
"version" "8.5.4" "version" "8.5.5"
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
@ -5573,13 +5573,13 @@
"ws@^7.3.1": "ws@^7.3.1":
"integrity" "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==" "integrity" "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q=="
"resolved" "https://registry.npmmirror.com/ws/-/ws-7.5.9.tgz" "resolved" "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz"
"version" "7.5.9" "version" "7.5.9"
"ws@^8.13.0": "ws@^8.13.0", "ws@^8.14.1":
"integrity" "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==" "integrity" "sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A=="
"resolved" "https://registry.npmmirror.com/ws/-/ws-8.13.0.tgz" "resolved" "https://registry.npmjs.org/ws/-/ws-8.14.1.tgz"
"version" "8.13.0" "version" "8.14.1"
"y18n@^5.0.5": "y18n@^5.0.5":
"integrity" "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" "integrity" "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="