Compare commits
84 Commits
d78e93b494
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d77506ed31 | ||
|
|
f03cf59e73 | ||
|
|
c2e901e4bc | ||
|
|
8cf50b9cb9 | ||
| 04e98ab1db | |||
| 347e51e9a4 | |||
|
|
fe7b34615a | ||
| 1b0746cc2d | |||
|
|
c992fa0200 | ||
| b97532e4e1 | |||
|
|
82573307e9 | ||
| 20f5cec3e9 | |||
|
|
67d59c5693 | ||
| 43f7ccac4c | |||
|
|
55947ceb16 | ||
|
|
fccd2ab9cc | ||
| e44b2b5f5b | |||
|
|
43a6f59afe | ||
| aeb43c8d41 | |||
| 5652cff730 | |||
|
|
f66b3a8a7a | ||
|
|
476b936660 | ||
|
|
59c652c3cf | ||
|
|
bb7f77e3ac | ||
| e306b0f837 | |||
|
|
85cc0c4c43 | ||
|
|
cfcdf4eb0a | ||
|
|
bb44001961 | ||
|
|
f9fc8e8c66 | ||
|
|
d56efd1c2f | ||
|
|
6d57597aa1 | ||
|
|
149e801d6d | ||
|
|
c6f5bc7d80 | ||
|
|
822732742d | ||
|
|
9c3b9218d2 | ||
|
|
52a9111a19 | ||
|
|
8ff6fd02df | ||
|
|
1b33520b61 | ||
|
|
335f61c0a1 | ||
|
|
fb4c1500e7 | ||
|
|
8d30507f1b | ||
| ae7adebae0 | |||
| ae3c430d38 | |||
|
|
23bf4790df | ||
|
|
544e42ac83 | ||
| d4001ed86e | |||
|
|
ca35a1768d | ||
| 9cdd255947 | |||
|
|
1c4ce804ff | ||
|
|
da305dbba9 | ||
|
|
62d3566f29 | ||
|
|
7eab7ddebb | ||
|
|
e0da16c903 | ||
|
|
53ead47882 | ||
|
|
31f427789f | ||
|
|
2a6cb3fe87 | ||
|
|
22f4b99ab1 | ||
|
|
2276c1f9dd | ||
|
|
85e82a1913 | ||
|
|
23cb871c93 | ||
|
|
7c84ba4595 | ||
|
|
c314f4b78e | ||
|
|
086be4da66 | ||
|
|
259752291c | ||
|
|
b6b17d1ef0 | ||
|
|
9b3779555c | ||
|
|
e25dfe8f02 | ||
|
|
98dd4428af | ||
|
|
8402afcdfc | ||
|
|
90c29c141c | ||
|
|
0d96fec181 | ||
|
|
7bf5a24cda | ||
|
|
bc96f76d7f | ||
|
|
112730b52a | ||
|
|
733ee07fa7 | ||
|
|
32ae14602e | ||
|
|
e7a0d10423 | ||
|
|
ef3c7a422a | ||
|
|
e425de93c7 | ||
|
|
14991c7ede | ||
|
|
71e9204fd4 | ||
|
|
c39a00cac1 | ||
|
|
3d765b4026 | ||
|
|
ac8eb57317 |
@@ -1,4 +1,4 @@
|
|||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
@@ -6,8 +6,12 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Vite + Vue</title>
|
<title>Vite + Vue</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body style="position: relative">
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
<!-- <div
|
||||||
|
id="glass-layer"
|
||||||
|
style="position: absolute; top: 0; left: 0; height: 100%"
|
||||||
|
></div> -->
|
||||||
<script type="module" src="/src/main.js"></script>
|
<script type="module" src="/src/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
14
package-lock.json
generated
@@ -11,6 +11,7 @@
|
|||||||
"echarts": "^5.4.3",
|
"echarts": "^5.4.3",
|
||||||
"element-plus": "^2.4.4",
|
"element-plus": "^2.4.4",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
|
"screenfull": "^6.0.2",
|
||||||
"vue": "^3.3.11",
|
"vue": "^3.3.11",
|
||||||
"vue3-marquee": "^4.1.0"
|
"vue3-marquee": "^4.1.0"
|
||||||
},
|
},
|
||||||
@@ -1123,6 +1124,14 @@
|
|||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/screenfull": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/screenfull/-/screenfull-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-AQdy8s4WhNvUZ6P8F6PB21tSPIYKniic+Ogx0AacBMjKP1GUHN2E9URxQHtCusiwxudnCKkdy4GrHXPPJSkCCw==",
|
||||||
|
"engines": {
|
||||||
|
"node": "^14.13.1 || >=16.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/source-map-js": {
|
"node_modules/source-map-js": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||||
@@ -1888,6 +1897,11 @@
|
|||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"screenfull": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/screenfull/-/screenfull-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-AQdy8s4WhNvUZ6P8F6PB21tSPIYKniic+Ogx0AacBMjKP1GUHN2E9URxQHtCusiwxudnCKkdy4GrHXPPJSkCCw=="
|
||||||
|
},
|
||||||
"source-map-js": {
|
"source-map-js": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"echarts": "^5.4.3",
|
"echarts": "^5.4.3",
|
||||||
"element-plus": "^2.4.4",
|
"element-plus": "^2.4.4",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
|
"screenfull": "^6.0.2",
|
||||||
"vue": "^3.3.11",
|
"vue": "^3.3.11",
|
||||||
"vue3-marquee": "^4.1.0"
|
"vue3-marquee": "^4.1.0"
|
||||||
},
|
},
|
||||||
|
|||||||
276
src/AlertListScreen.vue
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
<!-- 报警列表页面 -->
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from "vue";
|
||||||
|
import { useWsStore } from "./store";
|
||||||
|
import { useSettings } from "./store/settings";
|
||||||
|
import Container from "./components/Base/Container.vue";
|
||||||
|
import DatetimeTool from "./components/HeadTime.vue";
|
||||||
|
import AppHeader from "./components/Base/Header.vue";
|
||||||
|
import Tools from "./components/Tools.vue";
|
||||||
|
import FullEqList from "./FullEqList.vue";
|
||||||
|
import { useGlass } from "./utils/glass";
|
||||||
|
|
||||||
|
const store = useWsStore();
|
||||||
|
const GlassContainer = useGlass(store);
|
||||||
|
const settingStore = useSettings();
|
||||||
|
const props = defineProps({
|
||||||
|
line: {
|
||||||
|
type: Number,
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const mainContainer = ref(null);
|
||||||
|
const alarmList = ref(
|
||||||
|
(store.mainDataAlarm.alarmArrList || []).map((item, index) => ({
|
||||||
|
id: item.id,
|
||||||
|
eqName: item.equipmentName,
|
||||||
|
eqIndex: index + 1,
|
||||||
|
alarmGrade: item.alarmLevel,
|
||||||
|
alarmDetail: item.alarmDetails,
|
||||||
|
position: `${item.productLine} - ${item.segment}`,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
alarmList.value = (state.mainDataAlarm.alarmArrList || []).map(
|
||||||
|
(item, index) => ({
|
||||||
|
id: item.id,
|
||||||
|
eqName: item.equipmentName,
|
||||||
|
eqIndex: index + 1,
|
||||||
|
alarmGrade: item.alarmLevel,
|
||||||
|
alarmDetail: item.alarmDetails,
|
||||||
|
position: `${item.productLine} - ${item.segment}`,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 检查状态
|
||||||
|
onMounted(() => {
|
||||||
|
const settings = settingStore.settings;
|
||||||
|
// 设置分辨率
|
||||||
|
handleResolutionChange(settings.resolution.width, settings.resolution.height);
|
||||||
|
});
|
||||||
|
function changeScale(elm, width, height) {
|
||||||
|
const xScale = width / 1920;
|
||||||
|
const yScale = height / 1080;
|
||||||
|
const style = {
|
||||||
|
transform: `scale(${xScale}, ${yScale})`,
|
||||||
|
transformOrigin: "top left",
|
||||||
|
};
|
||||||
|
elm.style.transform = style.transform;
|
||||||
|
elm.style.transformOrigin = style.transformOrigin;
|
||||||
|
}
|
||||||
|
function handleResolutionChange(width, height) {
|
||||||
|
mainContainer.value &&
|
||||||
|
changeScale(mainContainer.value, width, height) &&
|
||||||
|
changeScale(document.getElementById("glass-layer"), width, height);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div id="main-container" ref="mainContainer" class="main-container">
|
||||||
|
<div id="main-container__fulleq">
|
||||||
|
<FullEqList v-if="0" />
|
||||||
|
</div>
|
||||||
|
<DatetimeTool />
|
||||||
|
<Tools @change-resolution="handleResolutionChange" />
|
||||||
|
<AppHeader />
|
||||||
|
|
||||||
|
<GlassContainer />
|
||||||
|
<!-- <div
|
||||||
|
id="glass-layer"
|
||||||
|
style="position: absolute; top: 0; left: 0; height: 100%"
|
||||||
|
></div>-->
|
||||||
|
|
||||||
|
<div class="alert-list-page">
|
||||||
|
<Container class="alert-list" title="报警列表" icon="cube">
|
||||||
|
<div class="alert-list__table" style="">
|
||||||
|
<el-table
|
||||||
|
class="dark-table"
|
||||||
|
:data="alarmList"
|
||||||
|
row-class-name="dark-row"
|
||||||
|
header-row-class-name="dark-header"
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
prop="eqName"
|
||||||
|
label="设备名"
|
||||||
|
width="90"
|
||||||
|
></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="eqIndex"
|
||||||
|
label="序号"
|
||||||
|
width="60"
|
||||||
|
></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="alarmGrade"
|
||||||
|
label="等级"
|
||||||
|
width="60"
|
||||||
|
></el-table-column>
|
||||||
|
<el-table-column prop="alarmDetail" label="报警细节">
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<el-tooltip
|
||||||
|
class="box-item"
|
||||||
|
effect="dark"
|
||||||
|
:content="row.alarmDetail || '---'"
|
||||||
|
placement="top-start"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style="
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
word-break: break-all;
|
||||||
|
"
|
||||||
|
>{{ row.alarmDetail || "---" }}</span
|
||||||
|
>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="position"
|
||||||
|
width="128"
|
||||||
|
label="定位"
|
||||||
|
></el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<!-- <button @click="handleIgnore" class="alert-btn">忽略</button> -->
|
||||||
|
</Container>
|
||||||
|
|
||||||
|
<ul class="main-screen-navigator alert-screen-navigator">
|
||||||
|
<li><a href="/main-screen">主屏页面</a></li>
|
||||||
|
<li class="active">报警列表</li>
|
||||||
|
<li><a href="/1-1">分屏页面</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.dark-table {
|
||||||
|
height: 100%;
|
||||||
|
background: transparent;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-row {
|
||||||
|
color: #fff;
|
||||||
|
background: #006acd32 !important;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-row:nth-child(odd) {
|
||||||
|
background: #020d2d32 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-row > td.el-table__cell {
|
||||||
|
border: none;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-row > td.el-table__cell:not(:last-child) {
|
||||||
|
border-right: 1px solid #0003;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-row:hover > td.el-table__cell {
|
||||||
|
background-color: #fff1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-header {
|
||||||
|
background-color: transparent !important;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-header > th.el-table__cell.is-leaf {
|
||||||
|
border-bottom: none;
|
||||||
|
background-color: #006acd32 !important;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-header > th.el-table__cell {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-header > th.el-table__cell:not(:last-child) {
|
||||||
|
border-right: 1px solid #0003;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.main-container {
|
||||||
|
width: 1920px;
|
||||||
|
height: 1080px;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: url(./assets/bg.png) 100% / cover no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-container__fulleq {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: url(./assets/full-lines.png) 100% / cover no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pages-wrapper {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-list-page {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-list {
|
||||||
|
height: calc(100% - 56px);
|
||||||
|
width: 640px;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top: 15px;
|
||||||
|
right: 32px;
|
||||||
|
z-index: 300;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
:fullscreen .alert-list {
|
||||||
|
width: 35%;
|
||||||
|
top: 32px;
|
||||||
|
height: calc(100% - 64px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-list__table {
|
||||||
|
height: calc(100% - 72px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-list__table >>> .el-table__inner-wrapper::before {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
appearance: none;
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 72px;
|
||||||
|
background: #0f04;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 32px;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
transition: all 0.2s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-btn:hover {
|
||||||
|
background: #0f08;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
53
src/App.vue
@@ -1,48 +1,55 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted } from "vue";
|
||||||
import MainPage from "./MainPage.vue";
|
import MainPage from "./MainPage.vue";
|
||||||
import Slider from "./components/Slider.vue";
|
import MainScreen from "./MainScreen.vue";
|
||||||
|
import AlertListScreen from "./AlertListScreen.vue";
|
||||||
|
// import Slider from "./components/Slider.vue";
|
||||||
import useWebsocket from "./utils/useWebsocket";
|
import useWebsocket from "./utils/useWebsocket";
|
||||||
import { useWsStore } from "./store";
|
import { useWsStore } from "./store";
|
||||||
|
|
||||||
const store = useWsStore();
|
const store = useWsStore();
|
||||||
|
|
||||||
|
const excludePaths = ["/alert-list", "/main-screen"];
|
||||||
// use websocket
|
// use websocket
|
||||||
let urlPath = document.location.pathname;
|
let urlPath = ref(document.location.pathname);
|
||||||
if (urlPath === "/") {
|
if (urlPath.value === "/") {
|
||||||
urlPath = "/1-1";
|
urlPath.value = "/1-1";
|
||||||
}
|
}
|
||||||
useWebsocket(store, urlPath);
|
useWebsocket(store, urlPath.value, excludePaths);
|
||||||
|
|
||||||
// size setting
|
// size setting
|
||||||
const size = ref(80);
|
// const size = ref(80);
|
||||||
onMounted(() => {
|
// onMounted(() => {
|
||||||
setSize(size.value);
|
// setSize(size.value);
|
||||||
});
|
// });
|
||||||
|
|
||||||
// style update
|
// style update
|
||||||
const styles = ref({});
|
// const styles = ref({});
|
||||||
function setSize(value) {
|
// function setSize(value) {
|
||||||
const v = (value / 100).toFixed(2);
|
// const v = (value / 100).toFixed(2);
|
||||||
console.log("size change", value);
|
// styles.value = {
|
||||||
styles.value = {
|
// transform: `scale(${v})`,
|
||||||
transform: `scale(${v})`,
|
// // transform: `scale(${v * 24 / 33}, ${v})`,
|
||||||
// transform: `scale(${v * 24 / 33}, ${v})`,
|
// transformOrigin: "top left",
|
||||||
transformOrigin: "top left",
|
// };
|
||||||
};
|
// }
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="app-container">
|
<div id="app-container">
|
||||||
<MainPage :style="styles" />
|
<!-- <Slider :size="size" @size-change="setSize" /> -->
|
||||||
<Slider :size="size" @size-change="setSize" />
|
<MainPage v-if="!excludePaths.includes(urlPath)" :path="urlPath" />
|
||||||
|
<MainScreen v-if="urlPath == '/main-screen'" />
|
||||||
|
<AlertListScreen v-if="urlPath == '/alert-list'" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#app-container {
|
#app-container {
|
||||||
width: 100vw;
|
/* width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh; */
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
height: 100%;
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
119
src/FullEqList.vue
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
<!--
|
||||||
|
filename: FullEqList.vue
|
||||||
|
author: liubin
|
||||||
|
date: 2024-03-05 14:13:06
|
||||||
|
description:
|
||||||
|
-->
|
||||||
|
<script setup>
|
||||||
|
import "./full-eq-list.css";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="absolute v-1 tag-container">
|
||||||
|
<span class="name-tag">M7上片</span>
|
||||||
|
<span class="name-tag">M6上片</span>
|
||||||
|
<span class="name-tag">M5上片</span>
|
||||||
|
<span class="name-tag">M4上片</span>
|
||||||
|
<span class="name-tag">M3上片</span>
|
||||||
|
<span class="name-tag">M2上片</span>
|
||||||
|
<span class="name-tag">M1上片</span>
|
||||||
|
</div>
|
||||||
|
<div class="absolute v-2 tag-container">
|
||||||
|
<span class="name-tag">M7磨边机</span>
|
||||||
|
<span class="name-tag">M6磨边机</span>
|
||||||
|
<span class="name-tag">M5磨边机</span>
|
||||||
|
<span class="name-tag">M4磨边机</span>
|
||||||
|
<span class="name-tag">M3磨边机</span>
|
||||||
|
<span class="name-tag">M2磨边机</span>
|
||||||
|
<span class="name-tag">M1磨边机</span>
|
||||||
|
</div>
|
||||||
|
<div class="absolute v-3 tag-container">
|
||||||
|
<span class="name-tag">M7清洗机</span>
|
||||||
|
<span class="name-tag">M6清洗机</span>
|
||||||
|
<span class="name-tag">M5清洗机</span>
|
||||||
|
<span class="name-tag">M4清洗机</span>
|
||||||
|
<span class="name-tag">M3清洗机</span>
|
||||||
|
<span class="name-tag">M2清洗机</span>
|
||||||
|
<span class="name-tag">M1清洗机</span>
|
||||||
|
</div>
|
||||||
|
<div class="absolute z-1 v-4 tag-container">
|
||||||
|
<span class="name-tag">Z7钻孔机</span>
|
||||||
|
<span class="name-tag">Z6钻孔机</span>
|
||||||
|
<span class="name-tag">Z5钻孔机</span>
|
||||||
|
<span class="name-tag">Z4钻孔机</span>
|
||||||
|
<span class="name-tag">Z3钻孔机</span>
|
||||||
|
<span class="name-tag">Z2钻孔机</span>
|
||||||
|
<span class="name-tag">Z1钻孔机</span>
|
||||||
|
</div>
|
||||||
|
<div class="absolute z-1 v-5 tag-container">
|
||||||
|
<span class="name-tag">S7清洗机</span>
|
||||||
|
<span class="name-tag">S6清洗机</span>
|
||||||
|
<span class="name-tag">S5清洗机</span>
|
||||||
|
<span class="name-tag">S4清洗机</span>
|
||||||
|
<span class="name-tag">S3清洗机</span>
|
||||||
|
<span class="name-tag">S2清洗机</span>
|
||||||
|
<span class="name-tag">S1清洗机</span>
|
||||||
|
</div>
|
||||||
|
<div class="absolute z-1 v-6 tag-container">
|
||||||
|
<span class="name-tag">S7前储片台</span>
|
||||||
|
<span class="name-tag">S6前储片台</span>
|
||||||
|
<span class="name-tag">S5前储片台</span>
|
||||||
|
<span class="name-tag">S4前储片台</span>
|
||||||
|
<span class="name-tag">S3前储片台</span>
|
||||||
|
<span class="name-tag">S2前储片台</span>
|
||||||
|
<span class="name-tag">S1前储片台</span>
|
||||||
|
</div>
|
||||||
|
<div class="absolute z-2 v-7 tag-container">
|
||||||
|
<span class="name-tag">S7丝印机</span>
|
||||||
|
<span class="name-tag">S6丝印机</span>
|
||||||
|
<span class="name-tag">S5丝印机</span>
|
||||||
|
<span class="name-tag">S4丝印机</span>
|
||||||
|
<span class="name-tag">S3丝印机</span>
|
||||||
|
<span class="name-tag">S2丝印机</span>
|
||||||
|
<span class="name-tag">S1丝印机</span>
|
||||||
|
</div>
|
||||||
|
<div class="absolute z-2 v-8 tag-container">
|
||||||
|
<span class="name-tag">S7固化炉</span>
|
||||||
|
<span class="name-tag">S6固化炉</span>
|
||||||
|
<span class="name-tag">S5固化炉</span>
|
||||||
|
<span class="name-tag">S4固化炉</span>
|
||||||
|
<span class="name-tag">S3固化炉</span>
|
||||||
|
<span class="name-tag">S2固化炉</span>
|
||||||
|
<span class="name-tag">S1固化炉</span>
|
||||||
|
</div>
|
||||||
|
<div class="absolute z-1 v-10 tag-container">
|
||||||
|
<span class="name-tag">D2镀膜机</span>
|
||||||
|
<span class="name-tag">D1镀膜机</span>
|
||||||
|
</div>
|
||||||
|
<div class="absolute z-1 v-9 tag-container">
|
||||||
|
<span class="name-tag">S7后储片台</span>
|
||||||
|
<span class="name-tag">S6后储片台</span>
|
||||||
|
<span class="name-tag">S5后储片台</span>
|
||||||
|
<span class="name-tag">S4后储片台</span>
|
||||||
|
<span class="name-tag">S3后储片台</span>
|
||||||
|
<span class="name-tag">S2后储片台</span>
|
||||||
|
<span class="name-tag">S1后储片台</span>
|
||||||
|
</div>
|
||||||
|
<div class="absolute z-3 tag-container">
|
||||||
|
<span class="name-tag">B3前储片台</span>
|
||||||
|
<span class="name-tag">B2前储片台</span>
|
||||||
|
<span class="name-tag">B1前储片台</span>
|
||||||
|
</div>
|
||||||
|
<div class="absolute z-3 b-1 tag-container">
|
||||||
|
<span class="name-tag">B3清洗机</span>
|
||||||
|
<span class="name-tag">B2清洗机</span>
|
||||||
|
<span class="name-tag">B1清洗机</span>
|
||||||
|
</div>
|
||||||
|
<div class="absolute z-3 b-2 tag-container">
|
||||||
|
<span class="name-tag">B3下片</span>
|
||||||
|
<span class="name-tag">B2下片</span>
|
||||||
|
<span class="name-tag">B1下片</span>
|
||||||
|
</div>
|
||||||
|
<div class="absolute z-3 b-3 tag-container">
|
||||||
|
<span class="name-tag">B3后储片台</span>
|
||||||
|
<span class="name-tag">B2后储片台</span>
|
||||||
|
<span class="name-tag">B1后储片台</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
141
src/MainPage.vue
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
import { ref, onMounted } from "vue";
|
||||||
import Tools from "./components/Tools.vue";
|
import Tools from "./components/Tools.vue";
|
||||||
import NavMenu from "./components/NavMenu.vue";
|
import NavMenu from "./components/NavMenu.vue";
|
||||||
import AnnoucementPage from "./pages/AnnouncementPage.vue";
|
import AnnoucementPage from "./pages/AnnouncementPage.vue";
|
||||||
@@ -8,19 +8,126 @@ import AppHeader from "./components/Base/Header.vue";
|
|||||||
import AlertListPage from "./pages/AlertListPage.vue";
|
import AlertListPage from "./pages/AlertListPage.vue";
|
||||||
import DataPage from "./pages/DataPage.vue";
|
import DataPage from "./pages/DataPage.vue";
|
||||||
import DatetimeTool from "./components/HeadTime.vue";
|
import DatetimeTool from "./components/HeadTime.vue";
|
||||||
import TriplePage from "./pages/3D.vue";
|
import ThreeDimension from "./pages/ThreeDimension.vue";
|
||||||
|
import { useSettings } from "./store/settings";
|
||||||
|
|
||||||
|
const props = defineProps(["path"]);
|
||||||
|
|
||||||
|
const pages = ["3d", "data", "realtime", "alert", "announcement"];
|
||||||
const currentPage = ref("3d");
|
const currentPage = ref("3d");
|
||||||
const handlePageChange = (page) => {
|
const handlePageChange = (page) => {
|
||||||
currentPage.value = page;
|
currentPage.value = page;
|
||||||
console.log(currentPage.value);
|
|
||||||
};
|
};
|
||||||
|
const mainContainer = ref(null);
|
||||||
|
|
||||||
|
const store = useSettings();
|
||||||
|
const timer = ref(null);
|
||||||
|
|
||||||
|
function startCarousel(pages, duration) {
|
||||||
|
if (timer.value) clearInterval(timer.value);
|
||||||
|
timer.value = setInterval(() => {
|
||||||
|
handlePageChange(
|
||||||
|
pages[(pages.indexOf(currentPage.value) + 1) % pages.length]
|
||||||
|
);
|
||||||
|
}, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
const pages = state.settings.carouselPages;
|
||||||
|
// 如果更新了时间
|
||||||
|
if (
|
||||||
|
mutation.events.key == "carouselTime" &&
|
||||||
|
state.settings.carouselTime > 0 &&
|
||||||
|
state.settings.carousel
|
||||||
|
) {
|
||||||
|
startCarousel(pages, state.settings.carouselTime * 1000);
|
||||||
|
} else if (mutation.events.key == "carousel") {
|
||||||
|
// 如果更新了状态
|
||||||
|
if (state.settings.carousel) {
|
||||||
|
startCarousel(pages, state.settings.carouselTime * 1000);
|
||||||
|
} else {
|
||||||
|
clearInterval(timer.value);
|
||||||
|
timer.value = null;
|
||||||
|
}
|
||||||
|
} else if (mutation.events.key == "carouselPages") {
|
||||||
|
if (state.settings.carousel) {
|
||||||
|
startCarousel(pages, state.settings.carouselTime * 1000);
|
||||||
|
} else {
|
||||||
|
clearInterval(timer.value);
|
||||||
|
timer.value = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 检查状态
|
||||||
|
onMounted(() => {
|
||||||
|
const settings = store.settings;
|
||||||
|
const pages = settings.carouselPages;
|
||||||
|
if (settings.carousel) {
|
||||||
|
// 开始轮播
|
||||||
|
if (timer.value) clearInterval(timer.value);
|
||||||
|
timer.value = setInterval(() => {
|
||||||
|
handlePageChange(
|
||||||
|
pages[(pages.indexOf(currentPage.value) + 1) % pages.length]
|
||||||
|
);
|
||||||
|
}, settings.carouselTime * 1000);
|
||||||
|
}
|
||||||
|
// 设置分辨率
|
||||||
|
handleResolutionChange(settings.resolution.width, settings.resolution.height);
|
||||||
|
});
|
||||||
|
|
||||||
|
const pathMap = {
|
||||||
|
// 钢三线
|
||||||
|
"/3-1": 1,
|
||||||
|
"/3-2": 2,
|
||||||
|
"/3-3": 11, // 3,
|
||||||
|
"/3-4": 12,
|
||||||
|
// 钢二线
|
||||||
|
"/2-1": 5,
|
||||||
|
"/2-2": 6,
|
||||||
|
"/2-3": 7,
|
||||||
|
"/2-4": 4,
|
||||||
|
// 钢一线
|
||||||
|
"/1-1": 9,
|
||||||
|
"/1-2": 10,
|
||||||
|
"/1-3": 3,
|
||||||
|
"/1-4": 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleResolutionChange(width, height) {
|
||||||
|
console.log("document.documentElement", document.documentElement);
|
||||||
|
if (mainContainer.value) {
|
||||||
|
// mainContainer.value.style.width = `${width}px`;
|
||||||
|
// mainContainer.value.style.height = `${height}px`;
|
||||||
|
// changeScale(mainContainer.value, width, height)
|
||||||
|
changeScale(mainContainer.value, width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeScale(elm, width, height) {
|
||||||
|
const xScale = width / 1920;
|
||||||
|
const yScale = height / 1080;
|
||||||
|
const style = {
|
||||||
|
transform: `scale(${xScale}, ${yScale})`,
|
||||||
|
transformOrigin: "top left",
|
||||||
|
};
|
||||||
|
elm.style.transform = style.transform;
|
||||||
|
elm.style.transformOrigin = style.transformOrigin;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetScale(elm) {
|
||||||
|
elm.style.transform = "initial";
|
||||||
|
elm.style.transformOrigin = "initial";
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="main-container">
|
<div id="main-container" ref="mainContainer" class="main-container">
|
||||||
<DatetimeTool v-if="currentPage !== 'announcement'" />
|
<DatetimeTool v-if="currentPage !== 'announcement'" />
|
||||||
<Tools v-if="currentPage !== 'announcement'" />
|
<Tools
|
||||||
|
v-if="currentPage !== 'announcement'"
|
||||||
|
@change-resolution="handleResolutionChange"
|
||||||
|
/>
|
||||||
<AppHeader v-if="currentPage !== 'announcement'" />
|
<AppHeader v-if="currentPage !== 'announcement'" />
|
||||||
<AnnoucementPage
|
<AnnoucementPage
|
||||||
v-if="currentPage === 'announcement'"
|
v-if="currentPage === 'announcement'"
|
||||||
@@ -28,11 +135,21 @@ const handlePageChange = (page) => {
|
|||||||
@home="() => handlePageChange('3d')"
|
@home="() => handlePageChange('3d')"
|
||||||
/>
|
/>
|
||||||
<div v-else class="pages-wrapper">
|
<div v-else class="pages-wrapper">
|
||||||
<NavMenu @change="handlePageChange" />
|
<NavMenu @change="handlePageChange" :value="currentPage" />
|
||||||
<TriplePage v-if="currentPage === '3d'" line="8" />
|
<!-- <TriplePage v-if="currentPage === '3d'" :line="pathMap[path] ?? '1'" /> -->
|
||||||
<DataPage v-if="currentPage === 'data'" />
|
<ThreeDimension
|
||||||
<AlertListPage v-if="currentPage === 'alert'" />
|
v-if="currentPage === '3d'"
|
||||||
<RealtimePage v-if="currentPage === 'realtime'" />
|
:line="pathMap[path] ?? '1'"
|
||||||
|
/>
|
||||||
|
<DataPage v-if="currentPage === 'data'" :line="pathMap[path] ?? '1'" />
|
||||||
|
<AlertListPage
|
||||||
|
v-if="currentPage === 'alert'"
|
||||||
|
:line="pathMap[path] ?? '1'"
|
||||||
|
/>
|
||||||
|
<RealtimePage
|
||||||
|
v-if="currentPage === 'realtime'"
|
||||||
|
:line="pathMap[path] ?? '1'"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -45,10 +162,6 @@ const handlePageChange = (page) => {
|
|||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
/**
|
|
||||||
background: url('https://img1.baidu.com/it/u=2052683582,2603151390&fm=253&fmt=auto&app=120&f=JPEG?w=1422&h=800')
|
|
||||||
100% / 100% no-repeat;
|
|
||||||
*/
|
|
||||||
background: url(./assets/bg.png) 100% / cover no-repeat;
|
background: url(./assets/bg.png) 100% / cover no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
294
src/MainScreen.vue
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
<!-- 报警列表页面 -->
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from "vue";
|
||||||
|
import { useWsStore } from "./store";
|
||||||
|
import { useSettings } from "./store/settings";
|
||||||
|
import DatetimeTool from "./components/HeadTime.vue";
|
||||||
|
import AppHeader from "./components/Base/Header.vue";
|
||||||
|
import Tools from "./components/Tools.vue";
|
||||||
|
import TodayYield from "./components/mainscreen/TodayYield.vue";
|
||||||
|
import SumYield from "./components/mainscreen/SumYield.vue";
|
||||||
|
import TodayRate from "./components/mainscreen/TodayRate.vue";
|
||||||
|
import SumRate from "./components/mainscreen/SumRate.vue";
|
||||||
|
import FullEqList from "./FullEqList.vue";
|
||||||
|
import { useGlass } from "./utils/glass";
|
||||||
|
|
||||||
|
const mainContainer = ref(null);
|
||||||
|
const props = defineProps({
|
||||||
|
line: {
|
||||||
|
type: Number,
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const store = useWsStore();
|
||||||
|
const GlassContainer = useGlass(store);
|
||||||
|
const settingStore = useSettings();
|
||||||
|
|
||||||
|
// 检查状态
|
||||||
|
onMounted(() => {
|
||||||
|
const settings = settingStore.settings;
|
||||||
|
// 设置分辨率
|
||||||
|
handleResolutionChange(settings.resolution.width, settings.resolution.height);
|
||||||
|
});
|
||||||
|
function changeScale(elm, width, height) {
|
||||||
|
const xScale = width / 1920;
|
||||||
|
const yScale = height / 1080;
|
||||||
|
const style = {
|
||||||
|
transform: `scale(${xScale}, ${yScale})`,
|
||||||
|
transformOrigin: "top left",
|
||||||
|
};
|
||||||
|
elm.style.transform = style.transform;
|
||||||
|
elm.style.transformOrigin = style.transformOrigin;
|
||||||
|
}
|
||||||
|
function handleResolutionChange(width, height) {
|
||||||
|
mainContainer.value && changeScale(mainContainer.value, width, height);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div id="main-container" ref="mainContainer" class="main-container">
|
||||||
|
<div id="main-container__fulleq">
|
||||||
|
<FullEqList v-if="0" />
|
||||||
|
</div>
|
||||||
|
<DatetimeTool />
|
||||||
|
<Tools @change-resolution="handleResolutionChange" />
|
||||||
|
<AppHeader />
|
||||||
|
|
||||||
|
<GlassContainer />
|
||||||
|
|
||||||
|
<div class="main-screen">
|
||||||
|
<!-- <div
|
||||||
|
style="
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: -279px;
|
||||||
|
width: calc(100% + 279px);
|
||||||
|
height: 100%;
|
||||||
|
background: #ccc3;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<ThreeD :line="line ?? '1'" />
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<TodayYield class=" " />
|
||||||
|
<SumYield class=" " />
|
||||||
|
<TodayRate class=" " />
|
||||||
|
<SumRate class=" " />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="main-screen-navigator alert-screen-navigator">
|
||||||
|
<li class="active">主屏页面</li>
|
||||||
|
<li><a href="/alert-list">报警列表</a></li>
|
||||||
|
<li><a href="/1-1">分屏页面</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
ul,
|
||||||
|
li {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
.alert-screen-navigator a,
|
||||||
|
.main-screen-navigator a {
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-screen-navigator,
|
||||||
|
.main-screen-navigator {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1000;
|
||||||
|
bottom: 32px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 460px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
background: rgba(46, 175, 214, 0.1);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 16px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
user-select: none;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-screen-navigator > li,
|
||||||
|
.main-screen-navigator > li {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease-out;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 12px 24px;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-screen-navigator > li:hover,
|
||||||
|
.main-screen-navigator > li:hover {
|
||||||
|
background: rgba(5, 106, 246, 0.168);
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-screen-navigator > li.active,
|
||||||
|
.main-screen-navigator > li.active {
|
||||||
|
background: rgba(5, 106, 246, 0.668);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-table {
|
||||||
|
height: 100%;
|
||||||
|
background: transparent;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-row {
|
||||||
|
color: #fff;
|
||||||
|
background: #006acd32 !important;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-row:nth-child(odd) {
|
||||||
|
background: #020d2d32 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-row > td.el-table__cell {
|
||||||
|
border: none;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-row > td.el-table__cell:not(:last-child) {
|
||||||
|
border-right: 1px solid #0003;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-row:hover > td.el-table__cell {
|
||||||
|
background-color: #fff1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-header {
|
||||||
|
background-color: transparent !important;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-header > th.el-table__cell.is-leaf {
|
||||||
|
border-bottom: none;
|
||||||
|
background-color: #006acd32 !important;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-header > th.el-table__cell {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-header > th.el-table__cell:not(:last-child) {
|
||||||
|
border-right: 1px solid #0003;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.ccontainer {
|
||||||
|
width: 420px;
|
||||||
|
height: 420px;
|
||||||
|
background: #ccc3;
|
||||||
|
/* position: absolute; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-top {
|
||||||
|
top: 32px;
|
||||||
|
left: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-bottom {
|
||||||
|
bottom: 32px;
|
||||||
|
left: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-top {
|
||||||
|
top: 32px;
|
||||||
|
right: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-bottom {
|
||||||
|
bottom: 32px;
|
||||||
|
right: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-container {
|
||||||
|
width: 1920px;
|
||||||
|
height: 1080px;
|
||||||
|
background: #000;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: url(./assets/bg.png) 100% / cover no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pages-wrapper {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-screen {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: repeat(2, 400px);
|
||||||
|
grid-template-columns: repeat(2, 400px);
|
||||||
|
justify-content: center;
|
||||||
|
/* align-content: center; */
|
||||||
|
/* place-content: center; */
|
||||||
|
gap: 15% 55%;
|
||||||
|
z-index: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-list {
|
||||||
|
height: calc(100% - 56px);
|
||||||
|
width: 520px;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top: 15px;
|
||||||
|
right: 32px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
:fullscreen .alert-list {
|
||||||
|
width: 35%;
|
||||||
|
top: 32px;
|
||||||
|
height: calc(100% - 64px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-list__table {
|
||||||
|
height: calc(100% - 72px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-list__table >>> .el-table__inner-wrapper::before {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
appearance: none;
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 72px;
|
||||||
|
background: #0f04;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 32px;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
transition: all 0.2s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-btn:hover {
|
||||||
|
background: #0f08;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
BIN
src/assets/dialog-bg.png
Normal file
|
After Width: | Height: | Size: 218 KiB |
BIN
src/assets/dialog-button.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
src/assets/full-lines.png
Normal file
|
After Width: | Height: | Size: 978 KiB |
BIN
src/assets/glass.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
src/assets/line.png
Normal file
|
After Width: | Height: | Size: 429 KiB |
BIN
src/assets/logo.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 12 KiB |
@@ -40,7 +40,7 @@ defineProps({
|
|||||||
result="shadowBlurOuter1"
|
result="shadowBlurOuter1"
|
||||||
></feGaussianBlur>
|
></feGaussianBlur>
|
||||||
<feColorMatrix
|
<feColorMatrix
|
||||||
values="0 0 0 0 0.000727194297 0 0 0 0 0.0682545659 0 0 0 0 0.141870471 0 0 0 1 0"
|
values="0 0 0 0 0.0123 0 0 0 0 0.0123 0 0 0 0 0.0123 0 0 0 1 0"
|
||||||
type="matrix"
|
type="matrix"
|
||||||
in="shadowBlurOuter1"
|
in="shadowBlurOuter1"
|
||||||
result="shadowMatrixOuter1"
|
result="shadowMatrixOuter1"
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ defineProps({
|
|||||||
<path
|
<path
|
||||||
d="M40.6,25.8120454 C40.6,28.1705437 40.1561224,30.3912077 39.2683673,32.4740374 C38.3806122,34.5568671 37.1637755,36.4023154 35.6178571,38.0103825 C34.0719388,39.6184495 32.2505102,40.935533 30.1535714,41.9616329 C28.0566327,42.9877328 25.7989796,43.6079872 23.3806122,43.8223962 C23.227551,43.853026 23.0897959,43.8759984 22.9673469,43.8913133 C22.844898,43.9066283 22.7071429,43.9142857 22.5540816,43.9142857 L14.6102041,43.9142857 C14.0897959,43.9142857 13.5770408,43.8223962 13.0719388,43.6386171 C12.5668367,43.454838 12.1153061,43.2021417 11.7173469,42.8805283 C11.3193878,42.5589149 10.9903061,42.1836993 10.730102,41.7548814 C10.469898,41.3260635 10.3397959,40.8819307 10.3397959,40.422483 C10.3397959,39.9630353 10.4622449,39.5189025 10.7071429,39.0900846 C10.9520408,38.6612667 11.2734694,38.2937086 11.6714286,37.9874101 C12.0693878,37.6811116 12.5132653,37.4360728 13.0030612,37.2522937 C13.4928571,37.0685146 13.9979592,36.9766251 14.5183673,36.9766251 L21.6357143,37.0225699 C23.2581633,37.0225699 24.7887755,36.7239288 26.227551,36.1266468 C27.6663265,35.5293648 28.9214286,34.7253312 29.9928571,33.7145462 C31.0642857,32.7037613 31.9061224,31.5168546 32.5183673,30.1538264 C33.1306122,28.7907981 33.4367347,27.3282229 33.4367347,25.7661006 C33.4367347,24.2958679 33.1612245,22.9175247 32.6102041,21.6310711 C32.0591837,20.3446175 31.3015306,19.1959982 30.3372449,18.1852132 C29.3729592,17.1744282 28.2479592,16.3550797 26.9622449,15.7271679 C25.6765306,15.099256 24.2836735,14.7087254 22.7836735,14.5555762 C22.722449,14.5555762 22.6841837,14.5632336 22.6688776,14.5785485 C22.6535714,14.5938635 22.6153061,14.6015209 22.5540816,14.6015209 L15.2530612,14.6015209 L15.2530612,18.2311579 C15.2530612,18.7518654 15.0464286,19.1347385 14.6331633,19.3797773 C14.219898,19.624816 13.5540816,19.4716668 12.6357143,18.9203295 C12.3908163,18.7671803 12.0005102,18.4991691 11.4647959,18.116296 C10.9290816,17.7334229 10.3015306,17.2816327 9.58214286,16.7609252 C8.8627551,16.2402178 8.10510204,15.6888805 7.30918367,15.1069134 L5.01326531,13.3610121 C4.55408163,12.9934539 4.15612245,12.664183 3.81938776,12.3731995 C3.48265306,12.0822159 3.31428571,11.7223152 3.31428571,11.2934973 C3.31428571,10.9259391 3.50561224,10.543066 3.88826531,10.144878 C4.27091837,9.74668998 4.70714286,9.34850195 5.19693878,8.95031393 C5.74795918,8.4908662 6.40612245,7.95484386 7.17142857,7.34224689 C7.93673469,6.72964993 8.69438776,6.13236789 9.44438776,5.55040077 C10.1943878,4.96843365 10.8678571,4.44006877 11.4647959,3.96530612 C12.0617347,3.49054347 12.4826531,3.16127261 12.727551,2.97749352 C13.4622449,2.4567861 14.0591837,2.34958163 14.5183673,2.65588011 C14.977551,2.96217859 15.222449,3.42162632 15.2530612,4.03422328 L15.2530612,7.70980507 L22.5540816,7.70980507 C22.7071429,7.70980507 22.8678571,7.72512 23.0362245,7.75574984 C23.2045918,7.78637969 23.3653061,7.81700954 23.5183673,7.84763939 C25.9061224,8.09267818 28.1408163,8.72059006 30.222449,9.73137506 C32.3040816,10.74216 34.1178571,12.0515861 35.6637755,13.6596531 C37.2096939,15.2677201 38.4188776,17.1131685 39.2913265,19.1959982 C40.1637755,21.2788279 40.6,23.4841769 40.6,25.8120454 L40.6,25.8120454 Z"
|
d="M40.6,25.8120454 C40.6,28.1705437 40.1561224,30.3912077 39.2683673,32.4740374 C38.3806122,34.5568671 37.1637755,36.4023154 35.6178571,38.0103825 C34.0719388,39.6184495 32.2505102,40.935533 30.1535714,41.9616329 C28.0566327,42.9877328 25.7989796,43.6079872 23.3806122,43.8223962 C23.227551,43.853026 23.0897959,43.8759984 22.9673469,43.8913133 C22.844898,43.9066283 22.7071429,43.9142857 22.5540816,43.9142857 L14.6102041,43.9142857 C14.0897959,43.9142857 13.5770408,43.8223962 13.0719388,43.6386171 C12.5668367,43.454838 12.1153061,43.2021417 11.7173469,42.8805283 C11.3193878,42.5589149 10.9903061,42.1836993 10.730102,41.7548814 C10.469898,41.3260635 10.3397959,40.8819307 10.3397959,40.422483 C10.3397959,39.9630353 10.4622449,39.5189025 10.7071429,39.0900846 C10.9520408,38.6612667 11.2734694,38.2937086 11.6714286,37.9874101 C12.0693878,37.6811116 12.5132653,37.4360728 13.0030612,37.2522937 C13.4928571,37.0685146 13.9979592,36.9766251 14.5183673,36.9766251 L21.6357143,37.0225699 C23.2581633,37.0225699 24.7887755,36.7239288 26.227551,36.1266468 C27.6663265,35.5293648 28.9214286,34.7253312 29.9928571,33.7145462 C31.0642857,32.7037613 31.9061224,31.5168546 32.5183673,30.1538264 C33.1306122,28.7907981 33.4367347,27.3282229 33.4367347,25.7661006 C33.4367347,24.2958679 33.1612245,22.9175247 32.6102041,21.6310711 C32.0591837,20.3446175 31.3015306,19.1959982 30.3372449,18.1852132 C29.3729592,17.1744282 28.2479592,16.3550797 26.9622449,15.7271679 C25.6765306,15.099256 24.2836735,14.7087254 22.7836735,14.5555762 C22.722449,14.5555762 22.6841837,14.5632336 22.6688776,14.5785485 C22.6535714,14.5938635 22.6153061,14.6015209 22.5540816,14.6015209 L15.2530612,14.6015209 L15.2530612,18.2311579 C15.2530612,18.7518654 15.0464286,19.1347385 14.6331633,19.3797773 C14.219898,19.624816 13.5540816,19.4716668 12.6357143,18.9203295 C12.3908163,18.7671803 12.0005102,18.4991691 11.4647959,18.116296 C10.9290816,17.7334229 10.3015306,17.2816327 9.58214286,16.7609252 C8.8627551,16.2402178 8.10510204,15.6888805 7.30918367,15.1069134 L5.01326531,13.3610121 C4.55408163,12.9934539 4.15612245,12.664183 3.81938776,12.3731995 C3.48265306,12.0822159 3.31428571,11.7223152 3.31428571,11.2934973 C3.31428571,10.9259391 3.50561224,10.543066 3.88826531,10.144878 C4.27091837,9.74668998 4.70714286,9.34850195 5.19693878,8.95031393 C5.74795918,8.4908662 6.40612245,7.95484386 7.17142857,7.34224689 C7.93673469,6.72964993 8.69438776,6.13236789 9.44438776,5.55040077 C10.1943878,4.96843365 10.8678571,4.44006877 11.4647959,3.96530612 C12.0617347,3.49054347 12.4826531,3.16127261 12.727551,2.97749352 C13.4622449,2.4567861 14.0591837,2.34958163 14.5183673,2.65588011 C14.977551,2.96217859 15.222449,3.42162632 15.2530612,4.03422328 L15.2530612,7.70980507 L22.5540816,7.70980507 C22.7071429,7.70980507 22.8678571,7.72512 23.0362245,7.75574984 C23.2045918,7.78637969 23.3653061,7.81700954 23.5183673,7.84763939 C25.9061224,8.09267818 28.1408163,8.72059006 30.222449,9.73137506 C32.3040816,10.74216 34.1178571,12.0515861 35.6637755,13.6596531 C37.2096939,15.2677201 38.4188776,17.1131685 39.2913265,19.1959982 C40.1637755,21.2788279 40.6,23.4841769 40.6,25.8120454 L40.6,25.8120454 Z"
|
||||||
id="back-btn"
|
id="back-btn"
|
||||||
fill="#50A1EC"
|
:fill="color ?? '#50A1EC'"
|
||||||
></path>
|
></path>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
|
|||||||
24
src/assets/svg/IconStatus.vue
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<!-- Icon: alert Icon -->
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<title>状态icon</title>
|
||||||
|
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="郴州旗滨光伏光电玻璃" transform="translate(-641.167539, -519.090909)" :fill="color ?? '#24FF5E'" fill-rule="nonzero">
|
||||||
|
<g id="状态icon" transform="translate(641.167539, 519.090909)">
|
||||||
|
<path
|
||||||
|
d="M21.6498582,4.55479956 C21.6463914,4.55050501 21.642058,4.54535155 21.6368579,4.54191591 C18.7967223,1.61303292 15.0188308,0 11,0 C6.98116924,0 3.20327766,1.61303292 0.362275449,4.54191591 C0.128269776,4.7824107 0,5.10278412 0,5.44377138 C0,5.78389972 0.127403089,6.10341423 0.361408761,6.34390902 C0.595414434,6.58440381 0.905688623,6.71753486 1.23676332,6.71753486 C1.56697132,6.71753486 1.87724551,6.58440381 2.11125118,6.34390902 C4.48510873,3.89687452 7.64158525,2.54924478 11,2.54924478 C14.3584147,2.54924478 17.515758,3.89773343 19.8887488,6.34476793 C20.1236212,6.58526272 20.4338954,6.71839377 20.7641034,6.71839377 C21.0943114,6.71839377 21.4054523,6.58526272 21.6377246,6.34476793 C21.8725969,6.10427314 22,5.78304081 22,5.44291247 C21.9991333,5.10879649 21.8760637,4.79443544 21.6498582,4.55479956 Z M10.9998918,22 C14.348751,22 17.0635378,19.3620338 17.0635378,16.1079376 C17.0635378,12.8538414 14.348751,10.2158752 10.9998918,10.2158752 C7.65103259,10.2158752 4.9362458,12.8538414 4.9362458,16.1079376 C4.9362458,19.3620338 7.65103259,22 10.9998918,22 Z M11,5.19640531 C8.47793886,5.19640531 6.10668137,6.16869139 4.32390482,7.9363281 C4.06909864,8.18884763 3.92869524,8.52382252 3.92869524,8.88027016 C3.92869524,9.23757671 4.06909864,9.5734105 4.32390482,9.82507112 C4.57784431,10.0767317 4.91585251,10.2158752 5.27552789,10.2158752 C5.63520328,10.2158752 5.97407816,10.0767317 6.22801765,9.82507112 C7.50291522,8.56161456 9.19815632,7.86589749 11,7.86589749 C12.8027104,7.86589749 14.4979515,8.56161456 15.7719824,9.82507112 C16.0267885,10.0767317 16.3647967,10.2158752 16.7253388,10.2158752 C17.0858809,10.2158752 17.4247558,10.0767317 17.6778286,9.82421221 C18.2030413,9.30285386 18.2013079,8.45682754 17.6778286,7.9363281 C15.8933186,6.1695503 13.5220611,5.19640531 11,5.19640531 Z"
|
||||||
|
id="形状"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg></template>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg width="26px" height="26px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<svg width="28px" height="28px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<title>任务</title>
|
<title>任务</title>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient x1="91.384997%" y1="100%" x2="25.4330364%" y2="7.84095011e-14%" id="linearGradient-1">
|
<linearGradient x1="91.384997%" y1="100%" x2="25.4330364%" y2="7.84095011e-14%" id="linearGradient-1">
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg width="26px" height="26px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<svg width="28px" height="28px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<title>更多 2</title>
|
<title>更多 2</title>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient x1="100%" y1="100%" x2="20.318998%" y2="7.84095011e-14%" id="linearGradient-1">
|
<linearGradient x1="100%" y1="100%" x2="20.318998%" y2="7.84095011e-14%" id="linearGradient-1">
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg width="26px" height="26px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<svg width="28px" height="28px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<title>多种 2</title>
|
<title>多种 2</title>
|
||||||
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
<g id="环动科技热处理车间立库看板" transform="translate(-39.000000, -620.000000)" fill="#FFFFFF" fill-rule="nonzero">
|
<g id="环动科技热处理车间立库看板" transform="translate(-39.000000, -620.000000)" fill="#FFFFFF" fill-rule="nonzero">
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg width="26px" height="26px" viewBox="0 0 24.4721163 23.7661066" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<svg width="28px" height="28px" viewBox="0 0 24.4721163 23.7661066" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<title>多种</title>
|
<title>多种</title>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient x1="100%" y1="89.6187762%" x2="20.318998%" y2="10.3812238%" id="linearGradient-1">
|
<linearGradient x1="100%" y1="89.6187762%" x2="20.318998%" y2="10.3812238%" id="linearGradient-1">
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
11
src/assets/svg/status_icon.svg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<title>状态icon</title>
|
||||||
|
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="郴州旗滨光伏光电玻璃" transform="translate(-641.167539, -519.090909)" fill="#FF3737" fill-rule="nonzero">
|
||||||
|
<g id="状态icon" transform="translate(641.167539, 519.090909)">
|
||||||
|
<path d="M21.6498582,4.55479956 C21.6463914,4.55050501 21.642058,4.54535155 21.6368579,4.54191591 C18.7967223,1.61303292 15.0188308,0 11,0 C6.98116924,0 3.20327766,1.61303292 0.362275449,4.54191591 C0.128269776,4.7824107 0,5.10278412 0,5.44377138 C0,5.78389972 0.127403089,6.10341423 0.361408761,6.34390902 C0.595414434,6.58440381 0.905688623,6.71753486 1.23676332,6.71753486 C1.56697132,6.71753486 1.87724551,6.58440381 2.11125118,6.34390902 C4.48510873,3.89687452 7.64158525,2.54924478 11,2.54924478 C14.3584147,2.54924478 17.515758,3.89773343 19.8887488,6.34476793 C20.1236212,6.58526272 20.4338954,6.71839377 20.7641034,6.71839377 C21.0943114,6.71839377 21.4054523,6.58526272 21.6377246,6.34476793 C21.8725969,6.10427314 22,5.78304081 22,5.44291247 C21.9991333,5.10879649 21.8760637,4.79443544 21.6498582,4.55479956 Z M10.9998918,22 C14.348751,22 17.0635378,19.3620338 17.0635378,16.1079376 C17.0635378,12.8538414 14.348751,10.2158752 10.9998918,10.2158752 C7.65103259,10.2158752 4.9362458,12.8538414 4.9362458,16.1079376 C4.9362458,19.3620338 7.65103259,22 10.9998918,22 Z M11,5.19640531 C8.47793886,5.19640531 6.10668137,6.16869139 4.32390482,7.9363281 C4.06909864,8.18884763 3.92869524,8.52382252 3.92869524,8.88027016 C3.92869524,9.23757671 4.06909864,9.5734105 4.32390482,9.82507112 C4.57784431,10.0767317 4.91585251,10.2158752 5.27552789,10.2158752 C5.63520328,10.2158752 5.97407816,10.0767317 6.22801765,9.82507112 C7.50291522,8.56161456 9.19815632,7.86589749 11,7.86589749 C12.8027104,7.86589749 14.4979515,8.56161456 15.7719824,9.82507112 C16.0267885,10.0767317 16.3647967,10.2158752 16.7253388,10.2158752 C17.0858809,10.2158752 17.4247558,10.0767317 17.6778286,9.82421221 C18.2030413,9.30285386 18.2013079,8.45682754 17.6778286,7.9363281 C15.8933186,6.1695503 13.5220611,5.19640531 11,5.19640531 Z" id="形状"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -51,7 +51,7 @@ const props = defineProps({
|
|||||||
<div class="cube" :class="[`cube-${cubeCorner}`]"></div>
|
<div class="cube" :class="[`cube-${cubeCorner}`]"></div>
|
||||||
<div class="container-header">
|
<div class="container-header">
|
||||||
<Icon :name="icon" />
|
<Icon :name="icon" />
|
||||||
<span>{{ title }}</span>
|
<span class="container-header__title">{{ title }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="container-body">
|
<div class="container-body">
|
||||||
<slot />
|
<slot />
|
||||||
@@ -105,6 +105,10 @@ const props = defineProps({
|
|||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container-header__title {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
.container-body {
|
.container-body {
|
||||||
background: #ffffff11;
|
background: #ffffff11;
|
||||||
backdrop-filter: blur(2px);
|
backdrop-filter: blur(2px);
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<div>
|
<div>
|
||||||
<Icon htmlRole="logo" icon="logo" />
|
<div class="icon"></div>
|
||||||
<h1 class="header__title">郴州旗滨光伏光电玻璃有限公司</h1>
|
<h1 class="header__title">郴州旗滨光伏光电玻璃有限公司</h1>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
@@ -18,18 +17,29 @@ import { ref, computed } from 'vue';
|
|||||||
background: url(../../assets/header-bg@2x.png) 100% / 100% no-repeat;
|
background: url(../../assets/header-bg@2x.png) 100% / 100% no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
header .icon {
|
||||||
|
background: url(../../assets/logo.png) 100% / contain no-repeat;
|
||||||
|
width: 52px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
.header > div {
|
.header > div {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
/** width: 520px; **/
|
/** width: 520px; **/
|
||||||
width: 480px;
|
width: 520px;
|
||||||
top: 20px;
|
top: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header__title {
|
.header__title {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
font-size: 30px;
|
||||||
letter-spacing: 2px;
|
letter-spacing: 2px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|||||||
@@ -41,9 +41,8 @@ const icon = computed(() => {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.icon {
|
.icon {
|
||||||
height: 16px;
|
height: 24px;
|
||||||
width: 16px;
|
width: 24px;
|
||||||
background: #fff3;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
159
src/components/Chart/RateChart.vue
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
<script setup>
|
||||||
|
import { computed, nextTick, onMounted, ref, watch } from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
import getOptions from "./rateOption";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
isOnlyChild: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
rawData: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
targetProduction: 0,
|
||||||
|
nowProduction: 0,
|
||||||
|
targetYield: 0,
|
||||||
|
nowYield: 0,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
displayPlaceholder: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.isOnlyChild,
|
||||||
|
(newVal) => {
|
||||||
|
reInitChart();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const rate = computed(() => {
|
||||||
|
if (!props.rawData?.nowYield || props.rawData.nowYield == 0) return [0, 0];
|
||||||
|
// const _rate = ((props.rawData.nowYield / props.rawData.targetYield) * 100)
|
||||||
|
// .toFixed(2)
|
||||||
|
// .toString();
|
||||||
|
// return [parseInt(_rate), _rate.split(".")[1]];
|
||||||
|
return [
|
||||||
|
parseInt(props.rawData.nowYield),
|
||||||
|
((props.rawData.nowYield + "").split(".")[1] ?? "").padStart(2, "0"),
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
const chart = ref(null);
|
||||||
|
const rateChartRef = ref(null);
|
||||||
|
|
||||||
|
function reInitChart() {
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
const _chart = echarts.init(rateChartRef.value);
|
||||||
|
_chart.setOption(getOptions(props.rawData));
|
||||||
|
chart.value = _chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
reInitChart();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="chart rate-chart">
|
||||||
|
<div ref="rateChartRef" class="chart-container"></div>
|
||||||
|
|
||||||
|
<div :class="['fake-chart-title', isOnlyChild ? 'is-only-child' : '']">
|
||||||
|
<span class="integer-part">{{ rate[0] }}.</span>
|
||||||
|
<span class="decimal-part">{{ rate[1] }}%</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-intro">
|
||||||
|
<div class="text-intro__item">
|
||||||
|
<span class="legend-box green"></span>
|
||||||
|
<span>当前成品率: {{ props.rawData?.nowYield ?? 0 }}%</span>
|
||||||
|
</div>
|
||||||
|
<div class="text-intro__item">
|
||||||
|
<span class="legend-box blue"></span>
|
||||||
|
<span>目标成品率: {{ props.rawData?.targetYield ?? 0 }}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.rate-chart {
|
||||||
|
height: 240px;
|
||||||
|
flex-grow: 1;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-placeholder,
|
||||||
|
.chart-container {
|
||||||
|
margin: auto;
|
||||||
|
width: 320px;
|
||||||
|
height: 100%;
|
||||||
|
background: "#0f01";
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fake-chart-title {
|
||||||
|
user-select: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 30%;
|
||||||
|
left: 36%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fake-chart-title.is-only-child {
|
||||||
|
left: 36%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fake-chart-title > .integer-part {
|
||||||
|
font-size: 48px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fake-chart-title > .decimal-part {
|
||||||
|
font-size: 32px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-intro {
|
||||||
|
position: absolute;
|
||||||
|
height: auto;
|
||||||
|
width: 240px;
|
||||||
|
bottom: 18px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 12px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
align-items: center;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-intro__item {
|
||||||
|
font-size: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-box {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.green {
|
||||||
|
background: #4cf0e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blue {
|
||||||
|
background: #1065ff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
110
src/components/Chart/YieldChart.vue
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
<script setup>
|
||||||
|
import { nextTick, onMounted, ref, watch } from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
import getOptions from "./yieldOption";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
rawData: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
targetProduction: 0,
|
||||||
|
nowProduction: 0,
|
||||||
|
targetYield: 0,
|
||||||
|
nowYield: 0,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
displayPlaceholder: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const chart = ref(null);
|
||||||
|
const yieldChartRef = ref(null);
|
||||||
|
|
||||||
|
function reInitChart() {
|
||||||
|
// if (props.displayPlaceholder) return;
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
const _chart = echarts.init(yieldChartRef.value);
|
||||||
|
_chart.setOption(
|
||||||
|
getOptions(
|
||||||
|
props.rawData ?? {
|
||||||
|
nowProduction: 0,
|
||||||
|
targetProduction: 0,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
chart.value = _chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
reInitChart();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="chart yield-chart">
|
||||||
|
<!-- <div v-if="displayPlaceholder" class="chart-placeholder"></div>
|
||||||
|
<div v-else ref="yieldChartRef" class="chart-container"></div> -->
|
||||||
|
<div ref="yieldChartRef" class="chart-container"></div>
|
||||||
|
<div class="text-intro">
|
||||||
|
<div class="text-intro__item">
|
||||||
|
<span class="legend-box green"></span>
|
||||||
|
<span>当前产量: {{ rawData?.nowProduction ?? 0 }}片</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="!displayPlaceholder" class="text-intro__item">
|
||||||
|
<span>目标产量: {{ rawData?.targetProduction ?? 0 }}片</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.yield-chart {
|
||||||
|
height: 240px;
|
||||||
|
flex-grow: 1;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-placeholder,
|
||||||
|
.chart-container {
|
||||||
|
margin: auto;
|
||||||
|
width: 320px;
|
||||||
|
height: 100%;
|
||||||
|
background: "#0f01";
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-intro {
|
||||||
|
position: absolute;
|
||||||
|
height: auto;
|
||||||
|
width: 220px;
|
||||||
|
bottom: 18px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 12px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
align-items: center;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-intro__item {
|
||||||
|
font-size: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-box {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #4cf0e8;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
149
src/components/Chart/rateOption.js
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
const radius = ["58%", "72%"];
|
||||||
|
const radius2 = ["45%", "58%"];
|
||||||
|
const grid = {
|
||||||
|
top: 0,
|
||||||
|
left: 24,
|
||||||
|
right: 24,
|
||||||
|
bottom: 32,
|
||||||
|
};
|
||||||
|
const title = {
|
||||||
|
// 由外部负责展示,此处占位
|
||||||
|
text: " ",
|
||||||
|
left: "50%",
|
||||||
|
top: "30%",
|
||||||
|
textAlign: "center",
|
||||||
|
textStyle: {
|
||||||
|
fontWeight: 400,
|
||||||
|
fontSize: 48,
|
||||||
|
color: "#fffd",
|
||||||
|
},
|
||||||
|
subtext: "当前成品率\u2002",
|
||||||
|
subtextStyle: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 100,
|
||||||
|
color: "#fffd",
|
||||||
|
align: "right",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const tooltip = {
|
||||||
|
// trigger: "item",
|
||||||
|
show: false,
|
||||||
|
};
|
||||||
|
const legend = {
|
||||||
|
top: "5%",
|
||||||
|
left: "center",
|
||||||
|
};
|
||||||
|
const bgSerie = {
|
||||||
|
type: "pie",
|
||||||
|
radius: radius,
|
||||||
|
center: ["50%", "40%"],
|
||||||
|
emptyCircleStyle: {
|
||||||
|
color: "#042c5f33",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const dataSerie = {
|
||||||
|
type: "pie",
|
||||||
|
radius: radius,
|
||||||
|
center: ["50%", "40%"],
|
||||||
|
avoidLabelOvervlap: false,
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
// position: "center",
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
value: 90,
|
||||||
|
name: "当前成品率",
|
||||||
|
selected: false,
|
||||||
|
itemStyle: {
|
||||||
|
borderJoin: "round",
|
||||||
|
borderCap: "round",
|
||||||
|
borderWidth: 12,
|
||||||
|
borderRadius: "50%",
|
||||||
|
color: {
|
||||||
|
type: "linear",
|
||||||
|
x: 1,
|
||||||
|
y: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 1,
|
||||||
|
colorStops: [
|
||||||
|
{ offset: 0, color: "#4CF0E811" },
|
||||||
|
{ offset: 1, color: "#4CF0E8" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 20,
|
||||||
|
name: "-",
|
||||||
|
itemStyle: { color: "transparent" },
|
||||||
|
label: { show: false },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const targetSerie = {
|
||||||
|
type: "pie",
|
||||||
|
radius: radius2,
|
||||||
|
center: ["50%", "40%"],
|
||||||
|
avoidLabelOvervlap: false,
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
value: 90,
|
||||||
|
name: "目标成品率",
|
||||||
|
selected: false,
|
||||||
|
itemStyle: {
|
||||||
|
borderJoin: "round",
|
||||||
|
borderCap: "round",
|
||||||
|
borderWidth: 12,
|
||||||
|
borderRadius: "50%",
|
||||||
|
color: {
|
||||||
|
type: "linear",
|
||||||
|
x: 1,
|
||||||
|
y: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 1,
|
||||||
|
colorStops: [
|
||||||
|
{ offset: 0, color: "#1065ff66" },
|
||||||
|
{ offset: 1, color: "#1065ff" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 20,
|
||||||
|
name: "-",
|
||||||
|
itemStyle: { color: "transparent" },
|
||||||
|
label: { show: false },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default (data) => {
|
||||||
|
title.subtext = "当前成品率\u2002";
|
||||||
|
dataSerie.data[0].value = data?.nowYield ?? 0;
|
||||||
|
dataSerie.data[1].value = 100 - (data?.nowYield ?? 0);
|
||||||
|
targetSerie.data[0].value = data?.targetYield ?? 0;
|
||||||
|
targetSerie.data[1].value = 100 - (data?.targetYield ?? 0);
|
||||||
|
return {
|
||||||
|
tooltip,
|
||||||
|
title,
|
||||||
|
grid,
|
||||||
|
series: [
|
||||||
|
// background
|
||||||
|
bgSerie,
|
||||||
|
// actual data
|
||||||
|
dataSerie,
|
||||||
|
// target data
|
||||||
|
targetSerie,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
};
|
||||||
157
src/components/Chart/yieldOption.js
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
const radius = ["58%", "72%"];
|
||||||
|
const radius2 = ["45%", "58%"];
|
||||||
|
const grid = {
|
||||||
|
top: 0,
|
||||||
|
left: 24,
|
||||||
|
right: 24,
|
||||||
|
bottom: 32,
|
||||||
|
};
|
||||||
|
const title = {
|
||||||
|
text: "75%",
|
||||||
|
left: "50%",
|
||||||
|
top: "30%",
|
||||||
|
textAlign: "center",
|
||||||
|
textStyle: {
|
||||||
|
fontWeight: 400,
|
||||||
|
fontSize: 48,
|
||||||
|
color: "#fffd",
|
||||||
|
},
|
||||||
|
subtext: "当前产量\u2002",
|
||||||
|
subtextStyle: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 100,
|
||||||
|
color: "#fffd",
|
||||||
|
align: "right",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const tooltip = {
|
||||||
|
// trigger: "item",
|
||||||
|
show: false,
|
||||||
|
};
|
||||||
|
const legend = {
|
||||||
|
top: "5%",
|
||||||
|
left: "center",
|
||||||
|
};
|
||||||
|
const bgSerie = {
|
||||||
|
type: "pie",
|
||||||
|
radius: radius,
|
||||||
|
center: ["50%", "40%"],
|
||||||
|
emptyCircleStyle: {
|
||||||
|
color: "#042c5f33",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const dataSerie = {
|
||||||
|
type: "pie",
|
||||||
|
radius: radius,
|
||||||
|
center: ["50%", "40%"],
|
||||||
|
avoidLabelOvervlap: false,
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
// position: "center",
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
value: 90,
|
||||||
|
name: "当前产量",
|
||||||
|
selected: false,
|
||||||
|
itemStyle: {
|
||||||
|
borderJoin: "round",
|
||||||
|
borderCap: "round",
|
||||||
|
borderWidth: 12,
|
||||||
|
borderRadius: "50%",
|
||||||
|
color: {
|
||||||
|
type: "linear",
|
||||||
|
x: 1,
|
||||||
|
y: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 1,
|
||||||
|
colorStops: [
|
||||||
|
{ offset: 0, color: "#4CF0E811" },
|
||||||
|
{ offset: 1, color: "#4CF0E8" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 20,
|
||||||
|
name: "-",
|
||||||
|
itemStyle: { color: "transparent" },
|
||||||
|
label: { show: false },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const targetSerie = {
|
||||||
|
type: "pie",
|
||||||
|
radius: radius2,
|
||||||
|
center: ["50%", "40%"],
|
||||||
|
avoidLabelOvervlap: false,
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
value: 90,
|
||||||
|
name: "目标成产量",
|
||||||
|
selected: false,
|
||||||
|
itemStyle: {
|
||||||
|
borderJoin: "round",
|
||||||
|
borderCap: "round",
|
||||||
|
borderWidth: 12,
|
||||||
|
borderRadius: "50%",
|
||||||
|
color: {
|
||||||
|
type: "linear",
|
||||||
|
x: 1,
|
||||||
|
y: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 1,
|
||||||
|
colorStops: [
|
||||||
|
{ offset: 0, color: "#1065ff66" },
|
||||||
|
{ offset: 1, color: "#1065ff" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 20,
|
||||||
|
name: "-",
|
||||||
|
itemStyle: { color: "transparent" },
|
||||||
|
label: { show: false },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default (data) => {
|
||||||
|
// title.text =
|
||||||
|
// (100 * (+data.nowProduction / +data.targetProduction)).toFixed(0) + "%";
|
||||||
|
// 外圈
|
||||||
|
title.text = data.nowProduction || 0;
|
||||||
|
dataSerie.data[0].value = data.nowProduction;
|
||||||
|
dataSerie.data[1].value = !data.targetProduction
|
||||||
|
? data.nowProduction == 0
|
||||||
|
? 1
|
||||||
|
: 0
|
||||||
|
: data.targetProduction - data.nowProduction;
|
||||||
|
|
||||||
|
// 内圈
|
||||||
|
targetSerie.data[0].value = data?.targetProduction ?? 0;
|
||||||
|
targetSerie.data[1].value = data?.targetProduction ? 0 : 1;
|
||||||
|
|
||||||
|
return {
|
||||||
|
tooltip,
|
||||||
|
title,
|
||||||
|
grid,
|
||||||
|
series: [
|
||||||
|
// background
|
||||||
|
bgSerie,
|
||||||
|
dataSerie,
|
||||||
|
targetSerie,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -24,7 +24,7 @@ onMounted(() => {
|
|||||||
top: 50px;
|
top: 50px;
|
||||||
right: 420px;
|
right: 420px;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
color: #69B4FF;
|
color: #69b4ff;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch, onMounted } from "vue";
|
import { ref, watch, onMounted, nextTick } from "vue";
|
||||||
import * as echarts from "echarts";
|
import * as echarts from "echarts";
|
||||||
import Container from "./Base/Container.vue";
|
import Container from "./Base/Container.vue";
|
||||||
import { useWsStore } from "../store";
|
import { useWsStore } from "../store";
|
||||||
@@ -9,57 +9,80 @@ const store = useWsStore();
|
|||||||
const chartChart = ref(null);
|
const chartChart = ref(null);
|
||||||
const chart = ref(null);
|
const chart = ref(null);
|
||||||
// 小时数据
|
// 小时数据
|
||||||
const hourData = ref(null);
|
const hourData = ref([
|
||||||
|
// { lineName: "001", hour: "00:00", num: 10 },
|
||||||
|
// { lineName: "002", hour: "00:20", num: 20 },
|
||||||
|
// { lineName: "003", hour: "00:30", num: 30 },
|
||||||
|
// { lineName: "004", hour: "00:40", num: 14 },
|
||||||
|
// { lineName: "005", hour: "00:50", num: 50 },
|
||||||
|
]);
|
||||||
store.$subscribe((mutation, state) => {
|
store.$subscribe((mutation, state) => {
|
||||||
console.log("lineHourList ===> ", state.data2.lineHourList);
|
if (
|
||||||
|
state.data2.lineHourList == undefined ||
|
||||||
|
state.data2.lineHourList?.length == 0
|
||||||
|
) {
|
||||||
|
hourData.value.splice(0);
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
hourData.value = (state.data2?.lineHourList ?? []).map((item, index) => ({
|
hourData.value = (state.data2?.lineHourList ?? []).map((item, index) => ({
|
||||||
id: `${item.lineName}_${index}`,
|
id: `${item.lineName}_${index}`,
|
||||||
hour: item.hour || `${index}`.padStart(2, "0"),
|
hour: item.hour || "__",
|
||||||
data: item.num || Math.random() * 100,
|
data: item.num || 0,
|
||||||
}));
|
}));
|
||||||
chartSetup(
|
setupChart();
|
||||||
chart.value,
|
|
||||||
hourData.value.map((item) => item.hour),
|
|
||||||
hourData.value.map((item) => item.data)
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// watch(hourData, (newVal) => {
|
function setupChart() {
|
||||||
// console.log("hourData", newVal);
|
if (chart.value) chart.value.dispose();
|
||||||
// if (newVal) {
|
nextTick(() => {
|
||||||
// chartSetup(
|
chart.value = echarts.init(chartChart.value);
|
||||||
// chart.value,
|
chartSetup(
|
||||||
// newVal.map((item) => item.hour),
|
chart.value,
|
||||||
// newVal.map((item) => item.data)
|
hourData.value.map((item) => item.hour),
|
||||||
// );
|
hourData.value.map((item) => item.data)
|
||||||
// }
|
);
|
||||||
// });
|
});
|
||||||
|
|
||||||
|
// chart.value.setOption({
|
||||||
|
// xAxis: {
|
||||||
|
// type: "category",
|
||||||
|
// data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
||||||
|
// },
|
||||||
|
// yAxis: {
|
||||||
|
// type: "value",
|
||||||
|
// },
|
||||||
|
// series: [
|
||||||
|
// {
|
||||||
|
// data: [150, 230, 224, 218, 135, 147, 260],
|
||||||
|
// type: "line",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
chartChart.value.classList.add("h-full");
|
chartChart.value.classList.add("h-full");
|
||||||
chart.value = echarts.init(chartChart.value);
|
// setupChart();
|
||||||
chart.value.setOption({})
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Container class="chart" title="小时数据" icon="cube">
|
<Container class="chart" title="小时数据" icon="cube">
|
||||||
<div
|
<div
|
||||||
v-show="hourData && hourData.length > 0"
|
|
||||||
ref="chartChart"
|
ref="chartChart"
|
||||||
class="chart-chart"
|
class="chart-chart"
|
||||||
|
style="{opacity: (hourData && hourData.length > 0) ? 1 : 0}"
|
||||||
></div>
|
></div>
|
||||||
<p v-show="!hourData || hourData.length === 0" class="empty-data-hint">暂无数据</p>
|
<p v-show="!hourData || hourData.length === 0" class="empty-data-hint">
|
||||||
|
暂无数据
|
||||||
|
</p>
|
||||||
</Container>
|
</Container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.chart {
|
.chart {
|
||||||
height: 300px;
|
height: 450px;
|
||||||
}
|
|
||||||
|
|
||||||
.chart-inner {
|
|
||||||
background: #0f0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.chart-chart {
|
.chart-chart {
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
export const options = {
|
export const options = {
|
||||||
|
color: ["#FFD160", "#99D66C", "#5B9BFF", "#2760FF", "#8167F6", "#FF00B2"],
|
||||||
grid: {
|
grid: {
|
||||||
top: "5%",
|
top: 10,
|
||||||
bottom: "5%",
|
bottom: 0,
|
||||||
left: "3%",
|
left: 12,
|
||||||
right: "3%",
|
right: 10,
|
||||||
containLabel: true,
|
containLabel: true,
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: "category",
|
type: "category",
|
||||||
data: ["00", "11", "22", "33", "44", "55", "66"],
|
data: [],
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
|
color: '#fff8'
|
||||||
},
|
},
|
||||||
axisLine: {
|
axisLine: {
|
||||||
show: true,
|
show: true,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: "#dff1fe",
|
color: "#e6e6e633",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -24,19 +26,42 @@ export const options = {
|
|||||||
axisLine: {
|
axisLine: {
|
||||||
show: true,
|
show: true,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: "#dff1fe",
|
color: "#e6e6e633",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#e6e6e633'
|
||||||
|
}
|
||||||
|
},
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
|
color: '#fff8'
|
||||||
},
|
},
|
||||||
minInterval: 1,
|
// minInterval: 1,
|
||||||
|
// max: 100,
|
||||||
|
// min: 1,
|
||||||
|
max: function(value) {
|
||||||
|
return value.max + Math.floor(value.max / 5)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
data: Array.from({ length: 7 }, () => Math.random() * 100),
|
data: [],
|
||||||
|
// data: Array.from({ length: 7 }, () => Math.random() * 100),
|
||||||
type: "bar",
|
type: "bar",
|
||||||
|
// barWidth: 20,
|
||||||
showBackground: true,
|
showBackground: true,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
distance: 20,
|
||||||
|
rotate: 90,
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 16,
|
||||||
|
verticalAlign: "middle",
|
||||||
|
position: 'top',
|
||||||
|
formatter: "{c}"
|
||||||
|
},
|
||||||
backgroundStyle: {
|
backgroundStyle: {
|
||||||
color: "rgba(180, 180, 180, 0.2)",
|
color: "rgba(180, 180, 180, 0.2)",
|
||||||
},
|
},
|
||||||
|
|||||||
163
src/components/LatestWeekYield.vue
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, watch, onMounted, nextTick } from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
import Container from "./Base/Container.vue";
|
||||||
|
import { useWsStore } from "../store";
|
||||||
|
import chartSetup, { loadData } from "./LatestWeekYieldOptions";
|
||||||
|
|
||||||
|
const store = useWsStore();
|
||||||
|
const chartContainer = ref(null);
|
||||||
|
const chartInstance = ref(null);
|
||||||
|
const show = ref(false);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
chartContainer.value.classList.add("h-full");
|
||||||
|
const d = loadData(store.data2.lineSevenDayLogList);
|
||||||
|
// const d = loadData([
|
||||||
|
// {
|
||||||
|
// data: [
|
||||||
|
// { day: "10-10", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-11", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-12", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-13", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-14", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-15", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-16", num: Math.floor(Math.random() * 500) },
|
||||||
|
// ],
|
||||||
|
// name: "钢一线",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// data: [
|
||||||
|
// { day: "10-10", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-11", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-12", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-13", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-14", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-15", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-16", num: Math.floor(Math.random() * 500) },
|
||||||
|
// ],
|
||||||
|
// name: "钢二线",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// data: [
|
||||||
|
// { day: "10-10", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-11", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-12", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-13", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-14", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-15", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-16", num: Math.floor(Math.random() * 500) },
|
||||||
|
// ],
|
||||||
|
// name: "钢三线",
|
||||||
|
// },
|
||||||
|
// ]);
|
||||||
|
if (!d) {
|
||||||
|
show.value = false;
|
||||||
|
if (chartInstance.value) {
|
||||||
|
chartInstance.value.dispose();
|
||||||
|
chartInstance.value = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!chartInstance.value)
|
||||||
|
chartInstance.value = echarts.init(chartContainer.value);
|
||||||
|
chartSetup(chartInstance.value, d);
|
||||||
|
show.value = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 订阅
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
const d = loadData(state.data2.lineSevenDayLogList);
|
||||||
|
// const d = loadData([
|
||||||
|
// {
|
||||||
|
// data: [
|
||||||
|
// { day: "10-10", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-11", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-12", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-13", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-14", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-15", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-16", num: Math.floor(Math.random() * 500) },
|
||||||
|
// ],
|
||||||
|
// name: "钢一线",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// data: [
|
||||||
|
// { day: "10-10", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-11", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-12", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-13", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-14", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-15", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-16", num: Math.floor(Math.random() * 500) },
|
||||||
|
// ],
|
||||||
|
// name: "钢二线",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// data: [
|
||||||
|
// { day: "10-10", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-11", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-12", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-13", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-14", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-15", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-16", num: Math.floor(Math.random() * 500) },
|
||||||
|
// ],
|
||||||
|
// name: "钢三线",
|
||||||
|
// },
|
||||||
|
// ]);
|
||||||
|
if (!d) {
|
||||||
|
show.value = false;
|
||||||
|
if (chartInstance.value) {
|
||||||
|
chartInstance.value.dispose();
|
||||||
|
chartInstance.value = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!chartInstance.value)
|
||||||
|
chartInstance.value = echarts.init(chartContainer.value);
|
||||||
|
chartSetup(chartInstance.value, d);
|
||||||
|
show.value = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Container class="chart" title="近7日产量" icon="cube">
|
||||||
|
<div
|
||||||
|
ref="chartContainer"
|
||||||
|
class="chart-chart"
|
||||||
|
:style="{ opacity: show ? 1 : 0 }"
|
||||||
|
></div>
|
||||||
|
<p v-show="!show" class="empty-data-hint">暂无数据</p>
|
||||||
|
</Container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chart {
|
||||||
|
height: 450px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-chart {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.empty-data-hint {
|
||||||
|
color: #c5c5c5;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 1.25;
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
margin: auto;
|
||||||
|
display: inline-block;
|
||||||
|
width: 200px;
|
||||||
|
height: 32px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
137
src/components/LatestWeekYieldOptions.js
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
export const options = {
|
||||||
|
color: ['#00D3E7', '#2B9BFF', '#0D4DFF'],
|
||||||
|
legend: {
|
||||||
|
textStyle: {
|
||||||
|
color: "#fff8",
|
||||||
|
},
|
||||||
|
right: 0,
|
||||||
|
itemWidth: 12,
|
||||||
|
itemHeight: 12
|
||||||
|
},
|
||||||
|
tooltip: {},
|
||||||
|
dataset: {
|
||||||
|
source: [],
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: 56,
|
||||||
|
bottom: 12,
|
||||||
|
left: 10,
|
||||||
|
right: 20,
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: "category",
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 12,
|
||||||
|
color: "#fff8",
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
alignWithLabel: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
name: "片",
|
||||||
|
nameTextStyle: {
|
||||||
|
color: "#fff8",
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 12,
|
||||||
|
color: "#fff8",
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: "#fff8",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
minInterval: 1,
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: "bar",
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
distance: 20,
|
||||||
|
rotate: 90,
|
||||||
|
color: "#fff",
|
||||||
|
verticalAlign: "middle",
|
||||||
|
position: 'top',
|
||||||
|
formatter: (params) => {
|
||||||
|
return params.data[1];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "bar",
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
distance: 20,
|
||||||
|
rotate: 90,
|
||||||
|
color: "#fff",
|
||||||
|
verticalAlign: "middle",
|
||||||
|
position: 'top',
|
||||||
|
formatter: (params) => {
|
||||||
|
return params.data[2];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "bar",
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
distance: 20,
|
||||||
|
rotate: 90,
|
||||||
|
color: "#fff",
|
||||||
|
verticalAlign: "middle",
|
||||||
|
position: 'top',
|
||||||
|
formatter: (params) => {
|
||||||
|
return params.data[3];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function setup(
|
||||||
|
echartInstance,
|
||||||
|
list = [
|
||||||
|
["1-12", 1, 2, 3],
|
||||||
|
["1-13", 4, 5, 6],
|
||||||
|
["1-14", 14, 15, 16],
|
||||||
|
["1-15", 9],
|
||||||
|
["1-16", 4, 5, 6],
|
||||||
|
["1-17", 1, 1, 1],
|
||||||
|
]
|
||||||
|
) {
|
||||||
|
const new_options = { ...options };
|
||||||
|
new_options.dataset.source = [["date", "钢1线", "钢2线", "钢3线"], ...list];
|
||||||
|
echartInstance.setOption(new_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createDatasetFrom(lines, datelist) {
|
||||||
|
const dataset = [];
|
||||||
|
datelist.forEach((date) => {
|
||||||
|
const row = [date];
|
||||||
|
lines.forEach((line) => {
|
||||||
|
const item = line.data.find((item) => item.day === date);
|
||||||
|
row.push(item ? item.num : 0);
|
||||||
|
});
|
||||||
|
dataset.push(row);
|
||||||
|
});
|
||||||
|
console.log(dataset);
|
||||||
|
return dataset;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function findDatelist(lines) {
|
||||||
|
const dateList = [];
|
||||||
|
lines.forEach((line) => {
|
||||||
|
dateList.push(...line.data.map((item) => item.day));
|
||||||
|
});
|
||||||
|
return Array.from(new Set(dateList)).sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadData(list) {
|
||||||
|
if (!list || list.length != 3 || list[0].data.length <= 0) return null;
|
||||||
|
const datelist = findDatelist(list);
|
||||||
|
return createDatasetFrom(list, datelist);
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import IconAlert from "../assets/menu_icon/IconAlert.vue";
|
|||||||
import IconChart from "../assets/menu_icon/IconChart.vue";
|
import IconChart from "../assets/menu_icon/IconChart.vue";
|
||||||
import IconRealtime from "../assets/menu_icon/IconRealtime.vue";
|
import IconRealtime from "../assets/menu_icon/IconRealtime.vue";
|
||||||
import IconAnnounce from "../assets/menu_icon/IconAnnouncement.vue";
|
import IconAnnounce from "../assets/menu_icon/IconAnnouncement.vue";
|
||||||
|
const props = defineProps(['value'])
|
||||||
const emit = defineEmits(["change"]);
|
const emit = defineEmits(["change"]);
|
||||||
const handleClick = (page) => {
|
const handleClick = (page) => {
|
||||||
emit("change", page);
|
emit("change", page);
|
||||||
@@ -17,27 +17,32 @@ const handleClick = (page) => {
|
|||||||
<ul class="flex-list">
|
<ul class="flex-list">
|
||||||
<li>
|
<li>
|
||||||
<button type="button" @click="(e) => handleClick('3d')">
|
<button type="button" @click="(e) => handleClick('3d')">
|
||||||
<span style="">三维界面</span><Icon3D class="nav-icon" />
|
<span :style="{ color: value == '3d' ? '#b1daff' : '#339dff' }">三维界面</span>
|
||||||
|
<Icon3D class="nav-icon" :color="value == '3d' ? '#b1daff' : '#339dff'" />
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button type="button" @click="(e) => handleClick('data')">
|
<button type="button" @click="(e) => handleClick('data')">
|
||||||
<span style="">数据界面</span><IconChart class="nav-icon" />
|
<span :style="{ color: value == 'data' ? '#b1daff' : '#339dff' }">数据界面</span>
|
||||||
|
<IconChart class="nav-icon" :color="value == 'data' ? '#b1daff' : '#339dff'" />
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button type="button" @click="(e) => handleClick('realtime')">
|
<button type="button" @click="(e) => handleClick('realtime')">
|
||||||
<span style="">实时数据</span><IconRealtime class="nav-icon" />
|
<span :style="{ color: value == 'realtime' ? '#b1daff' : '#339dff' }">实时数据</span>
|
||||||
|
<IconRealtime class="nav-icon" :color="value == 'realtime' ? '#b1daff' : '#339dff'" />
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button type="button" @click="(e) => handleClick('alert')">
|
<button type="button" @click="(e) => handleClick('alert')">
|
||||||
<span style="">报警列表</span><IconAlert class="nav-icon" />
|
<span :style="{ color: value == 'alert' ? '#b1daff' : '#339dff' }">报警列表</span>
|
||||||
|
<IconAlert class="nav-icon" :color="value == 'alert' ? '#b1daff' : '#339dff'" />
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button type="button" @click="(e) => handleClick('announcement')">
|
<button type="button" @click="(e) => handleClick('announcement')">
|
||||||
<span style="">公告页面</span><IconAnnounce class="nav-icon" />
|
<span style="">公告页面</span>
|
||||||
|
<IconAnnounce class="nav-icon" />
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -54,8 +59,13 @@ const handleClick = (page) => {
|
|||||||
position: relative;
|
position: relative;
|
||||||
top: 72px;
|
top: 72px;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* :fullscreen .nav-menu {
|
||||||
|
top: 25%;
|
||||||
|
} */
|
||||||
|
|
||||||
.flex-list {
|
.flex-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -84,7 +94,7 @@ li {
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-menu button > span {
|
.nav-menu button>span {
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
letter-spacing: 3px;
|
letter-spacing: 3px;
|
||||||
line-height: 45px;
|
line-height: 45px;
|
||||||
@@ -92,18 +102,19 @@ li {
|
|||||||
text-shadow: 0 5px 1px #001124;
|
text-shadow: 0 5px 1px #001124;
|
||||||
/* text-shadow: 0 5px 1px #004969; */
|
/* text-shadow: 0 5px 1px #004969; */
|
||||||
}
|
}
|
||||||
.nav-menu button:hover > span {
|
|
||||||
color: #b1daff;
|
.nav-menu button:hover>span {
|
||||||
|
color: #b1daff !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.nav-menu button:hover > .nav-icon #icon3d-g,
|
.nav-menu button:hover>.nav-icon #icon3d-g,
|
||||||
.nav-menu button:hover > .nav-icon #alert-rect,
|
.nav-menu button:hover>.nav-icon #alert-rect,
|
||||||
.nav-menu button:hover > .nav-icon #alert-dot,
|
.nav-menu button:hover>.nav-icon #alert-dot,
|
||||||
.nav-menu button:hover > .nav-icon #realtime-main,
|
.nav-menu button:hover>.nav-icon #realtime-main,
|
||||||
.nav-menu button:hover > .nav-icon #announce-main,
|
.nav-menu button:hover>.nav-icon #announce-main,
|
||||||
.nav-menu button:hover > .nav-icon #chart-main {
|
.nav-menu button:hover>.nav-icon #chart-main {
|
||||||
fill: #b1daff !important;
|
fill: #b1daff !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const options = {
|
|||||||
axisLabel: { show: false },
|
axisLabel: { show: false },
|
||||||
axisTick: { show: false },
|
axisTick: { show: false },
|
||||||
splitLine: { show: false },
|
splitLine: { show: false },
|
||||||
data: ["废片", "阶段成品"],
|
data: ["阶段成品", "废片"],
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
color: "#fff",
|
color: "#fff",
|
||||||
|
|||||||
@@ -3,8 +3,26 @@
|
|||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useWsStore } from "../store";
|
import { useWsStore } from "../store";
|
||||||
|
|
||||||
const listData = ref([]);
|
|
||||||
const store = useWsStore();
|
const store = useWsStore();
|
||||||
|
const listData = ref((store.data2.lineDetailData || Array(3).fill({})).map(
|
||||||
|
(item, index) => ({
|
||||||
|
productLine: item.productLine || "---",
|
||||||
|
mbt: item.edgingInput || "---",
|
||||||
|
mbb: item.edgingOutput || "---",
|
||||||
|
dkt: item.drillingInput || "---",
|
||||||
|
dkb: item.drillingOutput || "---",
|
||||||
|
dmt: item.coatingInput || "---",
|
||||||
|
dmb: item.coatingOutput || "---",
|
||||||
|
syt: item.silkInput || "---",
|
||||||
|
syb: item.silkOutput || "---",
|
||||||
|
ght: item.solidificationInput || "---",
|
||||||
|
ghb: item.solidificationOutput || "---",
|
||||||
|
gh1: item.temperingInput || "---",
|
||||||
|
gh2: item.temperingOutput || "---",
|
||||||
|
bzt: item.finalInput || "---",
|
||||||
|
bzb: item.finalOutput || "---",
|
||||||
|
})
|
||||||
|
));
|
||||||
store.$subscribe((mutation, state) => {
|
store.$subscribe((mutation, state) => {
|
||||||
listData.value = (state.data2.lineDetailData || Array(3).fill({})).map(
|
listData.value = (state.data2.lineDetailData || Array(3).fill({})).map(
|
||||||
(item, index) => ({
|
(item, index) => ({
|
||||||
@@ -30,13 +48,8 @@ store.$subscribe((mutation, state) => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="realtime-table">
|
<div class="realtime-table">
|
||||||
<el-table
|
<el-table class="dark-table" :data="listData" :show-overflow-tooltip="true" row-class-name="dark-row"
|
||||||
class="dark-table"
|
header-row-class-name="dark-header">
|
||||||
:data="listData"
|
|
||||||
:show-overflow-tooltip="true"
|
|
||||||
row-class-name="dark-row"
|
|
||||||
header-row-class-name="dark-header"
|
|
||||||
>
|
|
||||||
<el-table-column prop="productLine" label="产线"></el-table-column>
|
<el-table-column prop="productLine" label="产线"></el-table-column>
|
||||||
<el-table-column prop="mbt" label="磨边上"></el-table-column>
|
<el-table-column prop="mbt" label="磨边上"></el-table-column>
|
||||||
<el-table-column prop="mbb" label="磨边下"></el-table-column>
|
<el-table-column prop="mbb" label="磨边下"></el-table-column>
|
||||||
@@ -58,7 +71,7 @@ store.$subscribe((mutation, state) => {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.realtime-table {
|
.realtime-table {
|
||||||
background: #00f3;
|
/* background: #00f3; */
|
||||||
height: 160px;
|
height: 160px;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
align-self: self-start;
|
align-self: self-start;
|
||||||
@@ -68,7 +81,7 @@ store.$subscribe((mutation, state) => {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-table >>> .el-table__inner-wrapper::before {
|
.dark-table>>>.el-table__inner-wrapper::before {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
363
src/components/SettingDialog.vue
Normal file
@@ -0,0 +1,363 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { useSettings } from "../store/settings";
|
||||||
|
const emit = defineEmits(["close", "change-resolution"]);
|
||||||
|
|
||||||
|
const store = useSettings();
|
||||||
|
const settings = ref(store.settings);
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
settings.value.fullscreen = state.settings.fullscreen;
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleCancel() {
|
||||||
|
emit("close");
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleConfirm() {
|
||||||
|
if (settings.value.resolution.width < 480)
|
||||||
|
store.settings.resolution.width = 480;
|
||||||
|
if (settings.value.resolution.width > 7680)
|
||||||
|
store.settings.resolution.width = 7680;
|
||||||
|
if (settings.value.resolution.height < 270)
|
||||||
|
store.settings.resolution.height = 270;
|
||||||
|
if (settings.value.resolution.height > 4320)
|
||||||
|
store.settings.resolution.height = 4320;
|
||||||
|
|
||||||
|
emit(
|
||||||
|
"change-resolution",
|
||||||
|
store.settings.resolution.width,
|
||||||
|
store.settings.resolution.height
|
||||||
|
);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="setting-dialog">
|
||||||
|
<h1>设置</h1>
|
||||||
|
<div class="main-content">
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="carousel">轮播时间</label>
|
||||||
|
<input id="carousel" type="number" v-model="settings.carouselTime" />
|
||||||
|
<span>秒</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="form-item"
|
||||||
|
style="display: flex; flex-direction: column; gap: 12px"
|
||||||
|
>
|
||||||
|
<label for="carouselPages">轮播项目</label>
|
||||||
|
<div class="carousel-page__list">
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="cp-3d"
|
||||||
|
name="carouselPages"
|
||||||
|
:class="[
|
||||||
|
settings.carouselPages.includes('3d') ? 'checked' : '',
|
||||||
|
'carousel-page',
|
||||||
|
]"
|
||||||
|
@change="
|
||||||
|
() => {
|
||||||
|
store.updateSettings({ type: 'carousel-page', value: '3d' });
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<label for="cp-3d">三维界面</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="cp-data"
|
||||||
|
name="carouselPages"
|
||||||
|
:class="[
|
||||||
|
settings.carouselPages.includes('data') ? 'checked' : '',
|
||||||
|
'carousel-page',
|
||||||
|
]"
|
||||||
|
@change="
|
||||||
|
() => {
|
||||||
|
store.updateSettings({
|
||||||
|
type: 'carousel-page',
|
||||||
|
value: 'data',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<label for="cp-data">数据界面</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="cp-realtime"
|
||||||
|
name="carouselPages"
|
||||||
|
:class="[
|
||||||
|
settings.carouselPages.includes('realtime') ? 'checked' : '',
|
||||||
|
'carousel-page',
|
||||||
|
]"
|
||||||
|
@change="
|
||||||
|
() => {
|
||||||
|
store.updateSettings({
|
||||||
|
type: 'carousel-page',
|
||||||
|
value: 'realtime',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<label for="cp-realtime">实时数据</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="cp-alert"
|
||||||
|
name="carouselPages"
|
||||||
|
:class="[
|
||||||
|
settings.carouselPages.includes('alert') ? 'checked' : '',
|
||||||
|
'carousel-page',
|
||||||
|
]"
|
||||||
|
@change="
|
||||||
|
() => {
|
||||||
|
store.updateSettings({
|
||||||
|
type: 'carousel-page',
|
||||||
|
value: 'alert',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<label for="cp-alert">报警列表</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="cp-announcement"
|
||||||
|
name="carouselPages"
|
||||||
|
:class="[
|
||||||
|
settings.carouselPages.includes('announcement')
|
||||||
|
? 'checked'
|
||||||
|
: '',
|
||||||
|
'carousel-page',
|
||||||
|
]"
|
||||||
|
@change="
|
||||||
|
() => {
|
||||||
|
store.updateSettings({
|
||||||
|
type: 'carousel-page',
|
||||||
|
value: 'announcement',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<label for="cp-announcement">公告页面</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="resolution1">分辨率</label>
|
||||||
|
<input
|
||||||
|
id="resolution1"
|
||||||
|
type="number"
|
||||||
|
min="480"
|
||||||
|
max="7680"
|
||||||
|
v-model="settings.resolution.width"
|
||||||
|
/>
|
||||||
|
<span>X</span>
|
||||||
|
<input
|
||||||
|
id="resolution2"
|
||||||
|
type="number"
|
||||||
|
min="270"
|
||||||
|
max="4320"
|
||||||
|
v-model="settings.resolution.height"
|
||||||
|
/>
|
||||||
|
<span>px</span>
|
||||||
|
</div>
|
||||||
|
<div class="form-item selector">
|
||||||
|
<!-- <div class="opt opt1">
|
||||||
|
<input type="checkbox" id="fullscreen" name="fullscreen" :class="[settings.fullscreen ? 'checked' : '']"
|
||||||
|
v-model="settings.fullscreen" />
|
||||||
|
<label for="fullscreen">全屏显示</label>
|
||||||
|
</div> -->
|
||||||
|
<div class="opt opt2">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="status"
|
||||||
|
name="status"
|
||||||
|
:class="[settings.eqStatus ? 'checked' : '', 'carousel-page']"
|
||||||
|
v-model="settings.eqStatus"
|
||||||
|
/>
|
||||||
|
<label for="status">设备状态</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
<button @click="handleCancel" class="btn btn-cancel">取消</button>
|
||||||
|
<button @click="handleConfirm" class="btn btn-confirm">确认</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
* {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-dialog {
|
||||||
|
position: absolute;
|
||||||
|
margin: auto;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 577px;
|
||||||
|
height: 422px;
|
||||||
|
background: url(../assets/dialog-bg.png) 100% / contain no-repeat;
|
||||||
|
z-index: 1001;
|
||||||
|
transition: all 0.3s ease-out;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 24px 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
flex: 1;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
margin: 20px 0;
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 24px;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
padding: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item.selector {
|
||||||
|
gap: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opt {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opt2 {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item input {
|
||||||
|
flex: 1;
|
||||||
|
border: none;
|
||||||
|
appearance: none;
|
||||||
|
outline: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px 12px;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input#resolution1,
|
||||||
|
input#resolution2 {
|
||||||
|
width: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
appearance: initial;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
background: #fff;
|
||||||
|
flex: unset;
|
||||||
|
padding: unset;
|
||||||
|
font-size: unset;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"].checked {
|
||||||
|
background: #0049ff;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"].checked::after {
|
||||||
|
content: "\2713";
|
||||||
|
color: #fff;
|
||||||
|
font-size: 22px;
|
||||||
|
line-height: 24px;
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-page__list {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-page__list > div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"].carousel-page {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
input[type="checkbox"].carousel-page.checked::after {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
flex: 1;
|
||||||
|
padding: 12px;
|
||||||
|
font-size: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
letter-spacing: 8px;
|
||||||
|
background: url(../assets/dialog-button.png) 0 0 / 100% 100% no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
appearance: none;
|
||||||
|
outline: none;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
/* position: fixed;
|
||||||
|
height: 1080px;
|
||||||
|
width: 1920px; */
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
background: #0003;
|
||||||
|
backdrop-filter: blur(3px);
|
||||||
|
z-index: 999;
|
||||||
|
transition: all 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-dialog > h1 {
|
||||||
|
text-align: center;
|
||||||
|
letter-spacing: 24px;
|
||||||
|
font-weight: 400;
|
||||||
|
text-shadow: 0 5px 1px #001124;
|
||||||
|
user-select: none;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,47 +1,75 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted, nextTick } from "vue";
|
||||||
import * as echarts from "echarts";
|
import * as echarts from "echarts";
|
||||||
import Container from "./Base/Container.vue";
|
import Container from "./Base/Container.vue";
|
||||||
import { useWsStore } from "../store";
|
import { useWsStore } from "../store";
|
||||||
import chartSetup from "./HourChartOptions";
|
import setupFn from "./TeamChartDayOptions";
|
||||||
|
|
||||||
const store = useWsStore();
|
const store = useWsStore();
|
||||||
const chartChart = ref(null);
|
const chartChart = ref(null);
|
||||||
const chart = ref(null);
|
const chart = ref(null);
|
||||||
|
const showChartDom = ref(false);
|
||||||
|
|
||||||
// 小时数据
|
/** 无状态,处理数据 */
|
||||||
const hourData = ref(null);
|
function loadData(yieldArray) {
|
||||||
|
const result = [];
|
||||||
|
if (yieldArray == undefined || yieldArray?.length == 0) return null;
|
||||||
|
for (let i = 0; i < yieldArray.length; ++i) {
|
||||||
|
if (yieldArray[i].teamName == "A组") {
|
||||||
|
result[0] = parseInt(yieldArray[i].yield);
|
||||||
|
} else if (yieldArray[i].teamName == "B组") {
|
||||||
|
result[1] = parseInt(yieldArray[i].yield);
|
||||||
|
} else if (yieldArray[i].teamName == "C组") {
|
||||||
|
result[2] = parseInt(yieldArray[i].yield);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupChart(chart, dom, data) {
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
nextTick(() => {
|
||||||
|
chart.value = echarts.init(dom);
|
||||||
|
setupFn(chart.value, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 有状态,处理数据 */
|
||||||
|
function __apply(yieldArray) {
|
||||||
|
const d = loadData(yieldArray);
|
||||||
|
// const d = loadData([
|
||||||
|
// { teamName: "A组", yield: 11 },
|
||||||
|
// { teamName: "B组", yield: 23 },
|
||||||
|
// { teamName: "C组", yield: 14 },
|
||||||
|
// ]);
|
||||||
|
if (!d) {
|
||||||
|
showChartDom.value = false;
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showChartDom.value = true;
|
||||||
|
setupChart(chart, chartChart.value, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订阅
|
||||||
store.$subscribe((mutation, state) => {
|
store.$subscribe((mutation, state) => {
|
||||||
console.log("lineHourList ===> ", state.data2.lineHourList);
|
__apply(state.data2.classTodayProductYield);
|
||||||
hourData.value = (state.data2?.lineHourList ?? []).map((item, index) => ({
|
|
||||||
id: `${item.lineName}_${index}`,
|
|
||||||
hour: item.hour || `${index}`.padStart(2, "0"),
|
|
||||||
data: item.num || Math.random() * 100,
|
|
||||||
}));
|
|
||||||
chartSetup(
|
|
||||||
chart.value,
|
|
||||||
hourData.value.map((item) => item.hour),
|
|
||||||
hourData.value.map((item) => item.data)
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
chartChart.value.classList.add("h-full");
|
chartChart.value.classList.add("h-full");
|
||||||
chart.value = echarts.init(chartChart.value);
|
// __apply();
|
||||||
chart.value.setOption({});
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Container class="chart" title="本日班组情况" icon="cube">
|
<Container class="chart" title="本日班组情况" icon="cube">
|
||||||
<div
|
<div
|
||||||
v-show="hourData && hourData.length > 0"
|
|
||||||
ref="chartChart"
|
ref="chartChart"
|
||||||
class="chart-chart"
|
class="chart-chart"
|
||||||
|
:style="{ opacity: showChartDom ? 1 : 0 }"
|
||||||
></div>
|
></div>
|
||||||
<p v-show="!hourData || hourData.length === 0" class="empty-data-hint">
|
<p v-show="!chart" class="empty-data-hint">暂无数据</p>
|
||||||
暂无数据
|
|
||||||
</p>
|
|
||||||
</Container>
|
</Container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -50,10 +78,6 @@ onMounted(() => {
|
|||||||
height: 300px;
|
height: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chart-inner {
|
|
||||||
background: #0f0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-chart {
|
.chart-chart {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,52 +1,55 @@
|
|||||||
export const options = {
|
export const options = {
|
||||||
|
color: ['#a4c9d1', '#72340b', '#ffd601' ],
|
||||||
grid: {
|
grid: {
|
||||||
top: "10%",
|
top: 8,
|
||||||
bottom: "5%",
|
bottom: 20,
|
||||||
left: "3%",
|
left: 42,
|
||||||
right: "5%",
|
right: 28,
|
||||||
containLabel: true,
|
},
|
||||||
|
legend: {
|
||||||
|
show: false,
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
max: 100,
|
max: 100,
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: "#fff2",
|
||||||
|
},
|
||||||
|
},
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
fontSize: 22,
|
fontSize: 16,
|
||||||
|
color: "#e5e5e5a3",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
type: "category",
|
type: "category",
|
||||||
data: ["A组", "B组", "C组"],
|
data: ["A组", "B组", "C组"],
|
||||||
inverse: true,
|
inverse: true,
|
||||||
animationDuration: 300,
|
|
||||||
animationDurationUpdate: 300,
|
|
||||||
max: 2, // only the largest 3 bars will be displayed
|
max: 2, // only the largest 3 bars will be displayed
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
fontSize: 22,
|
fontSize: 16,
|
||||||
|
color: "#e5e5e5a3",
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: "#e5e5e5",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
realtimeSort: true,
|
|
||||||
name: "X",
|
|
||||||
type: "bar",
|
type: "bar",
|
||||||
data: [10, 20, 30],
|
data: [34, 2, 23],
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
position: "right",
|
position: "right",
|
||||||
valueAnimation: true,
|
|
||||||
formatter: "{c}%",
|
formatter: "{c}%",
|
||||||
color: "rgba(255, 255, 255, 1)",
|
color: "#fff",
|
||||||
fontWeight: "bold",
|
fontSize: 16,
|
||||||
fontSize: 22,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
legend: {
|
|
||||||
show: false,
|
|
||||||
},
|
|
||||||
animationDuration: 0,
|
|
||||||
animationDurationUpdate: 3000,
|
|
||||||
animationEasing: "linear",
|
|
||||||
animationEasingUpdate: "linear",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function setup(echartInstance, dataArr) {
|
export default function setup(echartInstance, dataArr) {
|
||||||
|
|||||||
@@ -1,47 +1,87 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted, nextTick } from "vue";
|
||||||
import * as echarts from "echarts";
|
import * as echarts from "echarts";
|
||||||
import Container from "./Base/Container.vue";
|
import Container from "./Base/Container.vue";
|
||||||
import { useWsStore } from "../store";
|
import { useWsStore } from "../store";
|
||||||
import chartSetup from "./HourChartOptions";
|
import setupFn from "./TeamChartMonthOptions";
|
||||||
|
|
||||||
|
const show = ref(false);
|
||||||
|
const chartContainer = ref(null);
|
||||||
|
const chartInstance = ref(null);
|
||||||
const store = useWsStore();
|
const store = useWsStore();
|
||||||
const chartChart = ref(null);
|
|
||||||
const chart = ref(null);
|
|
||||||
|
|
||||||
// 小时数据
|
|
||||||
const hourData = ref(null);
|
|
||||||
store.$subscribe((mutation, state) => {
|
|
||||||
console.log("lineHourList ===> ", state.data2.lineHourList);
|
|
||||||
hourData.value = (state.data2?.lineHourList ?? []).map((item, index) => ({
|
|
||||||
id: `${item.lineName}_${index}`,
|
|
||||||
hour: item.hour || `${index}`.padStart(2, "0"),
|
|
||||||
data: item.num || Math.random() * 100,
|
|
||||||
}));
|
|
||||||
chartSetup(
|
|
||||||
chart.value,
|
|
||||||
hourData.value.map((item) => item.hour),
|
|
||||||
hourData.value.map((item) => item.data)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// 绿色:24FF5E
|
||||||
|
// 黄色:FFB524
|
||||||
|
// 红色:FF3737
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
chartChart.value.classList.add("h-full");
|
chartContainer.value.classList.add("h-full");
|
||||||
chart.value = echarts.init(chartChart.value);
|
const d = loadData(store.data2.monthlyTarget);
|
||||||
chart.value.setOption({});
|
// const d = loadData([
|
||||||
|
// {
|
||||||
|
// targetProduction: 100,
|
||||||
|
// nowProduction: 66,
|
||||||
|
// targetYield: 13,
|
||||||
|
// nowYield: 3,
|
||||||
|
// },
|
||||||
|
// ]);
|
||||||
|
if (!d) {
|
||||||
|
show.value = false;
|
||||||
|
if (chartInstance.value) {
|
||||||
|
chartInstance.value.dispose();
|
||||||
|
chartInstance.value = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!chartInstance.value)
|
||||||
|
chartInstance.value = echarts.init(chartContainer.value);
|
||||||
|
setupFn(chartInstance.value, d);
|
||||||
|
show.value = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 订阅
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
const d = loadData(state.data2.monthlyTarget);
|
||||||
|
if (!d) {
|
||||||
|
show.value = false;
|
||||||
|
if (chartInstance.value) {
|
||||||
|
chartInstance.value.dispose();
|
||||||
|
chartInstance.value = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!chartInstance.value)
|
||||||
|
chartInstance.value = echarts.init(chartContainer.value);
|
||||||
|
setupFn(chartInstance.value, d);
|
||||||
|
show.value = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// utils
|
||||||
|
function loadData(monthlyTarget) {
|
||||||
|
if (
|
||||||
|
monthlyTarget == undefined ||
|
||||||
|
// monthlyTarget?.length == 0 ||
|
||||||
|
!monthlyTarget[0]
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
targetProduction: monthlyTarget[0].targetProduction,
|
||||||
|
nowProduction: monthlyTarget[0].nowProduction,
|
||||||
|
targetYield: monthlyTarget[0].targetYield,
|
||||||
|
nowYield: monthlyTarget[0].nowYield,
|
||||||
|
};
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Container class="chart" title="本月班组情况" icon="cube">
|
<Container class="chart" title="本月班组情况" icon="cube">
|
||||||
<div
|
<div
|
||||||
v-show="hourData && hourData.length > 0"
|
ref="chartContainer"
|
||||||
ref="chartChart"
|
|
||||||
class="chart-chart"
|
class="chart-chart"
|
||||||
|
:style="{ opacity: show ? 1 : 0 }"
|
||||||
></div>
|
></div>
|
||||||
<p v-show="!hourData || hourData.length === 0" class="empty-data-hint">
|
<p v-show="!show" class="empty-data-hint">暂无数据</p>
|
||||||
暂无数据
|
|
||||||
</p>
|
|
||||||
</Container>
|
</Container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -50,10 +90,6 @@ onMounted(() => {
|
|||||||
height: 300px;
|
height: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chart-inner {
|
|
||||||
background: #0f0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-chart {
|
.chart-chart {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +1,50 @@
|
|||||||
export const options = {
|
export const options = {
|
||||||
|
color: ["#99D66C", "#5B9BFF", "#8167F6", "#FF00B2"],
|
||||||
grid: {
|
grid: {
|
||||||
top: "10%",
|
top: 0,
|
||||||
bottom: "10%",
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
},
|
},
|
||||||
title: [
|
title: [
|
||||||
{
|
{
|
||||||
text: "当前产量:" + 100 + " 片",
|
text: "当前产量:" + 118 + " 片",
|
||||||
left: "27%",
|
left: "27%",
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
top: "67%",
|
top: "70%",
|
||||||
textStyle: {
|
textStyle: {
|
||||||
fontSize: 12,
|
fontSize: 16,
|
||||||
|
color: "#fffa",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "目标产量:" + 100 + " 片",
|
text: "目标产量:" + 213 + " 片",
|
||||||
left: "27%",
|
left: "27%",
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
top: "82%",
|
top: "85%",
|
||||||
textStyle: {
|
textStyle: {
|
||||||
fontSize: 12,
|
fontSize: 16,
|
||||||
|
color: "#fffa",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "当前成品率:" + 22 + "%",
|
text: "当前成品率:" + 78 + "%",
|
||||||
left: "73%",
|
left: "72%",
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
top: "67%",
|
top: "70%",
|
||||||
textStyle: {
|
textStyle: {
|
||||||
fontSize: 12,
|
fontSize: 16,
|
||||||
|
color: "#fffa",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "目标成品率:" + 22 + "%",
|
text: "目标成品率:" + 90 + "%",
|
||||||
left: "73%",
|
left: "72%",
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
top: "82%",
|
top: "85%",
|
||||||
textStyle: {
|
textStyle: {
|
||||||
fontSize: 12,
|
fontSize: 16,
|
||||||
|
color: "#fffa",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -71,7 +78,7 @@ export const options = {
|
|||||||
},
|
},
|
||||||
detail: {
|
detail: {
|
||||||
valueAnimation: true,
|
valueAnimation: true,
|
||||||
fontSize: 12,
|
fontSize: 16,
|
||||||
offsetCenter: [0, "0%"],
|
offsetCenter: [0, "0%"],
|
||||||
formatter: "{value}%",
|
formatter: "{value}%",
|
||||||
color: "rgba(255, 255, 255, 1)",
|
color: "rgba(255, 255, 255, 1)",
|
||||||
@@ -79,7 +86,7 @@ export const options = {
|
|||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
// value: (nowProduction / targetProduction * 100).toFixed(1),
|
// value: (nowProduction / targetProduction * 100).toFixed(1),
|
||||||
value: 100,
|
value: 89.78,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -113,16 +120,16 @@ export const options = {
|
|||||||
detail: {
|
detail: {
|
||||||
show: true,
|
show: true,
|
||||||
valueAnimation: true,
|
valueAnimation: true,
|
||||||
fontSize: 12,
|
fontSize: 16,
|
||||||
offsetCenter: [0, "0%"],
|
offsetCenter: [0, "0%"],
|
||||||
formatter: 0 + "%",
|
// formatter: 0 + "%",
|
||||||
// formatter: (nowYield / targetYield * 100).toFixed(1) + '%',
|
// formatter: (nowYield / targetYield * 100).toFixed(1) + '%',
|
||||||
color: "rgba(255, 255, 255, 1)",
|
color: "#fff",
|
||||||
},
|
},
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
// value: targetYield,
|
// value: targetYield,
|
||||||
value: 100,
|
value: 78,
|
||||||
name: "Perfect",
|
name: "Perfect",
|
||||||
title: {
|
title: {
|
||||||
show: false,
|
show: false,
|
||||||
@@ -134,8 +141,7 @@ export const options = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 100,
|
value: 90,
|
||||||
// value: nowYield,
|
|
||||||
name: "Good",
|
name: "Good",
|
||||||
title: {
|
title: {
|
||||||
show: false,
|
show: false,
|
||||||
@@ -144,6 +150,7 @@ export const options = {
|
|||||||
show: false,
|
show: false,
|
||||||
valueAnimation: true,
|
valueAnimation: true,
|
||||||
offsetCenter: ["0%", "10%"],
|
offsetCenter: ["0%", "10%"],
|
||||||
|
formatter: "99.23%",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -162,8 +169,24 @@ export default function setup(echartInstance, data) {
|
|||||||
new_options.title[1].text = "目标产量:" + data.targetProduction + " 片";
|
new_options.title[1].text = "目标产量:" + data.targetProduction + " 片";
|
||||||
new_options.title[2].text = "当前成品率:" + data.nowYield + "%";
|
new_options.title[2].text = "当前成品率:" + data.nowYield + "%";
|
||||||
new_options.title[3].text = "目标成品率:" + data.targetYield + "%";
|
new_options.title[3].text = "目标成品率:" + data.targetYield + "%";
|
||||||
new_options.series[0].data[0].value = (data.nowProduction / data.targetProduction * 100).toFixed(1)
|
new_options.series[0].data[0].value =
|
||||||
new_options.series[1].data[0].value = data.targetYield
|
data.nowProduction != null &&
|
||||||
new_options.series[1].data[1].value = data.nowYield
|
data.targetProduction != null &&
|
||||||
|
data.targetProduction != 0
|
||||||
|
? ((data.nowProduction / data.targetProduction) * 100).toFixed(1)
|
||||||
|
: 0;
|
||||||
|
new_options.series[1].data[0].value = data.targetYield;
|
||||||
|
new_options.series[1].data[1].value = data.nowYield;
|
||||||
|
new_options.series[1].detail.formatter =
|
||||||
|
data.nowYield != null && data.targetYield != null && data.targetYield != 0
|
||||||
|
? ((data.nowYield / data.targetYield) * 100).toFixed(2) + "%"
|
||||||
|
: "0%";
|
||||||
echartInstance.setOption(new_options);
|
echartInstance.setOption(new_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "targetProduction": 99,
|
||||||
|
// "nowProduction": 58,
|
||||||
|
// "targetYield": 12,
|
||||||
|
// "nowYield": 9
|
||||||
|
// }
|
||||||
|
|||||||
@@ -3,14 +3,68 @@ import { ref, watch, onMounted } from "vue";
|
|||||||
import IconBack from "../assets/menu_icon/IconBack.vue";
|
import IconBack from "../assets/menu_icon/IconBack.vue";
|
||||||
import IconExchange from "../assets/menu_icon/IconExchange.vue";
|
import IconExchange from "../assets/menu_icon/IconExchange.vue";
|
||||||
import IconSetting from "../assets/menu_icon/IconSetting.vue";
|
import IconSetting from "../assets/menu_icon/IconSetting.vue";
|
||||||
|
import SettingDialogVue from "./SettingDialog.vue";
|
||||||
|
import { useSettings } from "../store/settings";
|
||||||
|
|
||||||
|
const emit = defineEmits(["change-resolution"]);
|
||||||
|
|
||||||
|
const { settings, updateSettings } = useSettings();
|
||||||
|
// store.$subscribe((_, state) => {
|
||||||
|
// settings.value.carousel = state.settings.carousel;
|
||||||
|
// })
|
||||||
|
const visible = ref(false);
|
||||||
|
|
||||||
|
function toHome() {
|
||||||
|
document.location.reload();
|
||||||
|
}
|
||||||
|
function showDialog() {
|
||||||
|
visible.value = true;
|
||||||
|
}
|
||||||
|
function toggleLunbo() {
|
||||||
|
updateSettings({ type: "carousel", value: null });
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleChangeResolution(w, h) {
|
||||||
|
emit("change-resolution", w, h);
|
||||||
|
visible.value = false;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="tools">
|
<div id="tools-bar" class="tools">
|
||||||
<button><IconBack /></button>
|
<button @click="toHome">
|
||||||
<button><IconSetting /></button>
|
<IconBack />
|
||||||
<button><IconExchange /></button>
|
</button>
|
||||||
|
<button @click="showDialog">
|
||||||
|
<IconSetting />
|
||||||
|
</button>
|
||||||
|
<button style="position: relative" @click="toggleLunbo">
|
||||||
|
<span
|
||||||
|
v-if="settings.carousel"
|
||||||
|
style="
|
||||||
|
color: #fffa;
|
||||||
|
font-family: 'Courier New', Courier, monospace;
|
||||||
|
font-weight: 600;
|
||||||
|
width: 56px;
|
||||||
|
font-size: 22px;
|
||||||
|
user-select: none;
|
||||||
|
position: absolute;
|
||||||
|
line-height: 52px;
|
||||||
|
text-align: center;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ settings.carouselTime }}S</span
|
||||||
|
>
|
||||||
|
<IconExchange :color="settings.carousel ? '#03356a' : '#50A1EC'" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<Teleport to="body">
|
||||||
|
<SettingDialogVue
|
||||||
|
v-if="visible"
|
||||||
|
@close="visible = false"
|
||||||
|
@change-resolution="handleChangeResolution"
|
||||||
|
/>
|
||||||
|
</Teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -20,7 +74,7 @@ import IconSetting from "../assets/menu_icon/IconSetting.vue";
|
|||||||
right: 24px;
|
right: 24px;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0px;
|
gap: 0px;
|
||||||
z-index: 3;
|
z-index: 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
@@ -51,7 +105,6 @@ button svg #switch-btn {
|
|||||||
transition: fill 0.2s ease-out;
|
transition: fill 0.2s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
button:hover svg #back-btn,
|
button:hover svg #back-btn,
|
||||||
button:hover svg #setting-btn,
|
button:hover svg #setting-btn,
|
||||||
button:hover svg #switch-btn {
|
button:hover svg #switch-btn {
|
||||||
|
|||||||
99
src/components/datapage/HourChart.vue
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, watch, onMounted, nextTick } from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
import Container from "../Base/Container.vue";
|
||||||
|
import { useWsStore } from "../../store";
|
||||||
|
import chartSetup from "./HourChartOptions";
|
||||||
|
|
||||||
|
const store = useWsStore();
|
||||||
|
const chartChart = ref(null);
|
||||||
|
const chart = ref(null);
|
||||||
|
// 小时数据
|
||||||
|
const hourData = ref([
|
||||||
|
// { hour: "0:1", data: 10 },
|
||||||
|
// { hour: "0:2", data: 13 },
|
||||||
|
// { hour: "0:3", data: 20 },
|
||||||
|
// { hour: "0:4", data: 12 },
|
||||||
|
// { hour: "0:5", data: 12 },
|
||||||
|
// { hour: "0:6", data: 11 },
|
||||||
|
// { hour: "0:7", data: 10 },
|
||||||
|
// { hour: "0:8", data: 1 },
|
||||||
|
]);
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
if (
|
||||||
|
state.data2.lineHourList == undefined ||
|
||||||
|
state.data2.lineHourList?.length == 0
|
||||||
|
) {
|
||||||
|
hourData.value.splice(0);
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hourData.value = (state.data2?.lineHourList ?? []).map((item, index) => ({
|
||||||
|
id: `${item.lineName}_${index}`,
|
||||||
|
hour: item.hour || `__`,
|
||||||
|
data: item.num || 0,
|
||||||
|
}));
|
||||||
|
setupChart();
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupChart() {
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
nextTick(() => {
|
||||||
|
chart.value = echarts.init(chartChart.value);
|
||||||
|
chartSetup(
|
||||||
|
chart.value,
|
||||||
|
hourData.value.map((item) => item.hour),
|
||||||
|
hourData.value.map((item) => item.data)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
chartChart.value.classList.add("h-full");
|
||||||
|
// setupChart();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Container class="chart" title="小时数据" icon="cube">
|
||||||
|
<div
|
||||||
|
ref="chartChart"
|
||||||
|
class="chart-chart"
|
||||||
|
style="{opacity: (hourData && hourData.length > 0) ? 1 : 0}"
|
||||||
|
></div>
|
||||||
|
<p v-show="!hourData || hourData.length === 0" class="empty-data-hint">
|
||||||
|
暂无数据
|
||||||
|
</p>
|
||||||
|
</Container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chart {
|
||||||
|
/* height: 300px; */
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-chart {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.empty-data-hint {
|
||||||
|
color: #c5c5c5;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 1.25;
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
margin: auto;
|
||||||
|
display: inline-block;
|
||||||
|
width: 200px;
|
||||||
|
height: 32px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
77
src/components/datapage/HourChartOptions.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
export const options = {
|
||||||
|
color: ["#FFD160", "#99D66C", "#5B9BFF", "#2760FF", "#8167F6", "#FF00B2"],
|
||||||
|
grid: {
|
||||||
|
top: 10,
|
||||||
|
bottom: 0,
|
||||||
|
left: 12,
|
||||||
|
right: 10,
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: "category",
|
||||||
|
data: [],
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: "#fff8",
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: "#e6e6e633",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: "value",
|
||||||
|
axisLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: "#e6e6e633",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: "#e6e6e633",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: "#fff8",
|
||||||
|
},
|
||||||
|
minInterval: 1,
|
||||||
|
// max: 100,
|
||||||
|
// min: 1
|
||||||
|
max: function(value) {
|
||||||
|
return value.max + Math.floor(value.max / 4)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
data: [],
|
||||||
|
// data: Array.from({ length: 7 }, () => Math.random() * 100),
|
||||||
|
type: "bar",
|
||||||
|
// barWidth: 20,
|
||||||
|
showBackground: true,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
distance: 20,
|
||||||
|
rotate: 90,
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 16,
|
||||||
|
verticalAlign: "middle",
|
||||||
|
position: 'top',
|
||||||
|
formatter: "{c}"
|
||||||
|
},
|
||||||
|
backgroundStyle: {
|
||||||
|
color: "rgba(180, 180, 180, 0.2)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function setup(echartInstance, timeArr, dataArr) {
|
||||||
|
const new_options = { ...options };
|
||||||
|
new_options.xAxis.data = timeArr;
|
||||||
|
new_options.series[0].data = dataArr;
|
||||||
|
echartInstance.setOption(new_options);
|
||||||
|
}
|
||||||
164
src/components/datapage/LatestWeekYield.vue
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, watch, onMounted, nextTick } from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
import Container from "../Base/Container.vue";
|
||||||
|
import { useWsStore } from "../../store";
|
||||||
|
import chartSetup, { loadData } from "./LatestWeekYieldOptions";
|
||||||
|
|
||||||
|
const store = useWsStore();
|
||||||
|
const chartContainer = ref(null);
|
||||||
|
const chartInstance = ref(null);
|
||||||
|
const show = ref(false);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
chartContainer.value.classList.add("h-full");
|
||||||
|
const d = loadData(store.data2.lineSevenDayLogList);
|
||||||
|
// const d = loadData([
|
||||||
|
// {
|
||||||
|
// data: [
|
||||||
|
// { day: "10-10", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-11", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-12", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-13", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-14", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-15", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-16", num: Math.floor(Math.random() * 500) },
|
||||||
|
// ],
|
||||||
|
// name: "钢一线",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// data: [
|
||||||
|
// { day: "10-10", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-11", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-12", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-13", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-14", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-15", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-16", num: Math.floor(Math.random() * 500) },
|
||||||
|
// ],
|
||||||
|
// name: "钢二线",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// data: [
|
||||||
|
// { day: "10-10", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-11", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-12", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-13", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-14", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-15", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-16", num: Math.floor(Math.random() * 500) },
|
||||||
|
// ],
|
||||||
|
// name: "钢三线",
|
||||||
|
// },
|
||||||
|
// ]);
|
||||||
|
if (!d) {
|
||||||
|
show.value = false;
|
||||||
|
if (chartInstance.value) {
|
||||||
|
chartInstance.value.dispose();
|
||||||
|
chartInstance.value = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!chartInstance.value)
|
||||||
|
chartInstance.value = echarts.init(chartContainer.value);
|
||||||
|
chartSetup(chartInstance.value, d);
|
||||||
|
show.value = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 订阅
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
const d = loadData(state.data2.lineSevenDayLogList);
|
||||||
|
// const d = loadData([
|
||||||
|
// {
|
||||||
|
// data: [
|
||||||
|
// { day: "10-10", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-11", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-12", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-13", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-14", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-15", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-16", num: Math.floor(Math.random() * 500) },
|
||||||
|
// ],
|
||||||
|
// name: "钢一线",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// data: [
|
||||||
|
// { day: "10-10", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-11", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-12", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-13", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-14", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-15", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-16", num: Math.floor(Math.random() * 500) },
|
||||||
|
// ],
|
||||||
|
// name: "钢二线",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// data: [
|
||||||
|
// { day: "10-10", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-11", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-12", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-13", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-14", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-15", num: Math.floor(Math.random() * 500) },
|
||||||
|
// { day: "10-16", num: Math.floor(Math.random() * 500) },
|
||||||
|
// ],
|
||||||
|
// name: "钢三线",
|
||||||
|
// },
|
||||||
|
// ]);
|
||||||
|
if (!d) {
|
||||||
|
show.value = false;
|
||||||
|
if (chartInstance.value) {
|
||||||
|
chartInstance.value.dispose();
|
||||||
|
chartInstance.value = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!chartInstance.value)
|
||||||
|
chartInstance.value = echarts.init(chartContainer.value);
|
||||||
|
chartSetup(chartInstance.value, d);
|
||||||
|
show.value = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Container class="chart" title="近7日产量" icon="cube">
|
||||||
|
<div
|
||||||
|
ref="chartContainer"
|
||||||
|
class="chart-chart"
|
||||||
|
:style="{ opacity: show ? 1 : 0 }"
|
||||||
|
></div>
|
||||||
|
<p v-show="!show" class="empty-data-hint">暂无数据</p>
|
||||||
|
</Container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chart {
|
||||||
|
/* height: 300px; */
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-chart {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.empty-data-hint {
|
||||||
|
color: #c5c5c5;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 1.25;
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
margin: auto;
|
||||||
|
display: inline-block;
|
||||||
|
width: 200px;
|
||||||
|
height: 32px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
134
src/components/datapage/LatestWeekYieldOptions.js
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
export const options = {
|
||||||
|
color: ['#00D3E7', '#2B9BFF', '#0D4DFF'],
|
||||||
|
legend: {
|
||||||
|
textStyle: {
|
||||||
|
color: "#fff8",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tooltip: {},
|
||||||
|
dataset: {
|
||||||
|
source: [],
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: 56,
|
||||||
|
bottom: 12,
|
||||||
|
left: 10,
|
||||||
|
right: 20,
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: "category",
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 12,
|
||||||
|
color: "#fff8",
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
alignWithLabel: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
name: "片",
|
||||||
|
nameTextStyle: {
|
||||||
|
color: "#fff8",
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 12,
|
||||||
|
color: "#fff8",
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: "#fff8",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
minInterval: 1,
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: "bar",
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
distance: 20,
|
||||||
|
rotate: 90,
|
||||||
|
color: "#fff",
|
||||||
|
verticalAlign: "middle",
|
||||||
|
position: 'top',
|
||||||
|
formatter: (params) => {
|
||||||
|
return params.data[1];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "bar",
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
distance: 20,
|
||||||
|
rotate: 90,
|
||||||
|
color: "#fff",
|
||||||
|
verticalAlign: "middle",
|
||||||
|
position: 'top',
|
||||||
|
formatter: (params) => {
|
||||||
|
return params.data[2];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "bar",
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
distance: 20,
|
||||||
|
rotate: 90,
|
||||||
|
color: "#fff",
|
||||||
|
verticalAlign: "middle",
|
||||||
|
position: 'top',
|
||||||
|
formatter: (params) => {
|
||||||
|
return params.data[3];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function setup(
|
||||||
|
echartInstance,
|
||||||
|
list = [
|
||||||
|
["1-12", 1, 2, 3],
|
||||||
|
["1-13", 4, 5, 6],
|
||||||
|
["1-14", 14, 15, 16],
|
||||||
|
["1-15", 9],
|
||||||
|
["1-16", 4, 5, 6],
|
||||||
|
["1-17", 1, 1, 1],
|
||||||
|
]
|
||||||
|
) {
|
||||||
|
const new_options = { ...options };
|
||||||
|
new_options.dataset.source = [["date", "钢1线", "钢2线", "钢3线"], ...list];
|
||||||
|
echartInstance.setOption(new_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createDatasetFrom(lines, datelist) {
|
||||||
|
const dataset = [];
|
||||||
|
datelist.forEach((date) => {
|
||||||
|
const row = [date];
|
||||||
|
lines.forEach((line) => {
|
||||||
|
const item = line.data.find((item) => item.day === date);
|
||||||
|
row.push(item ? item.num : 0);
|
||||||
|
});
|
||||||
|
dataset.push(row);
|
||||||
|
});
|
||||||
|
console.log(dataset);
|
||||||
|
return dataset;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function findDatelist(lines) {
|
||||||
|
const dateList = [];
|
||||||
|
lines.forEach((line) => {
|
||||||
|
dateList.push(...line.data.map((item) => item.day));
|
||||||
|
});
|
||||||
|
return Array.from(new Set(dateList)).sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadData(list) {
|
||||||
|
if (!list || list.length != 3 || list[0].data.length <= 0) return null;
|
||||||
|
const datelist = findDatelist(list);
|
||||||
|
return createDatasetFrom(list, datelist);
|
||||||
|
}
|
||||||
143
src/components/datapage/LineMonth.vue
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, nextTick } from "vue";
|
||||||
|
import Container from "../Base/Container.vue";
|
||||||
|
import { useWsStore } from "../../store";
|
||||||
|
import YieldChart from "../Chart/YieldChart.vue";
|
||||||
|
import RateChart from "../Chart/RateChart.vue";
|
||||||
|
|
||||||
|
const displayProductionChart = ref(false);
|
||||||
|
const displayRateChart = ref(false);
|
||||||
|
const websocketData = ref(null);
|
||||||
|
const refreshToken = ref(1);
|
||||||
|
const store = useWsStore();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// websocketData.value = loadData([
|
||||||
|
// {
|
||||||
|
// targetProduction: 0,
|
||||||
|
// nowProduction: 10,
|
||||||
|
// targetYield: 10.34,
|
||||||
|
// nowYield: 3.11,
|
||||||
|
// },
|
||||||
|
// ]);
|
||||||
|
websocketData.value = loadData(store.data2.monthlyTarget);
|
||||||
|
if (!websocketData.value) {
|
||||||
|
displayProductionChart.value = false;
|
||||||
|
displayRateChart.value = false;
|
||||||
|
} else {
|
||||||
|
/** 阻止 targetProduction == 0 */
|
||||||
|
if (!websocketData.value.targetProduction) {
|
||||||
|
displayProductionChart.value = false;
|
||||||
|
} else {
|
||||||
|
displayProductionChart.value = true;
|
||||||
|
}
|
||||||
|
/** 阻止 targetYield == 0 */
|
||||||
|
if (!websocketData.value.targetYield) {
|
||||||
|
displayRateChart.value = false;
|
||||||
|
} else {
|
||||||
|
displayRateChart.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 订阅
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
// const d = loadData([
|
||||||
|
// {
|
||||||
|
// targetProduction: 100,
|
||||||
|
// nowProduction: 66,
|
||||||
|
// targetYield: 13,
|
||||||
|
// nowYield: 3,
|
||||||
|
// },
|
||||||
|
// ]);
|
||||||
|
websocketData.value = loadData(state.data2.monthlyTarget);
|
||||||
|
if (!websocketData.value) {
|
||||||
|
displayProductionChart.value = false;
|
||||||
|
displayRateChart.value = false;
|
||||||
|
} else {
|
||||||
|
/** 阻止 targetProduction == 0 */
|
||||||
|
if (!websocketData.value.targetProduction) {
|
||||||
|
displayProductionChart.value = false;
|
||||||
|
} else {
|
||||||
|
if (refreshToken.value > 100000) refreshToken.value = 0;
|
||||||
|
refreshToken.value += 1;
|
||||||
|
displayProductionChart.value = true;
|
||||||
|
}
|
||||||
|
/** 阻止 targetYield == 0 */
|
||||||
|
if (!websocketData.value.targetYield) {
|
||||||
|
displayRateChart.value = false;
|
||||||
|
} else {
|
||||||
|
if (refreshToken.value > 100000) refreshToken.value = 0;
|
||||||
|
refreshToken.value += 1;
|
||||||
|
displayRateChart.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// utils
|
||||||
|
function loadData(monthlyTarget) {
|
||||||
|
if (monthlyTarget == undefined || !monthlyTarget[0]) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
targetProduction: monthlyTarget[0].targetProduction,
|
||||||
|
nowProduction: monthlyTarget[0].nowProduction,
|
||||||
|
targetYield: monthlyTarget[0].targetYield,
|
||||||
|
nowYield: monthlyTarget[0].nowYield,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Container class="chart" title="本月生产线情况" icon="cube">
|
||||||
|
<!-- <div
|
||||||
|
ref="chartContainer"
|
||||||
|
class="chart-chart"
|
||||||
|
:style="{ opacity: show ? 1 : 0 }"
|
||||||
|
></div>
|
||||||
|
<p v-show="!show" class="empty-data-hint">暂无数据</p> -->
|
||||||
|
<div class="container-body__h-full">
|
||||||
|
<yield-chart
|
||||||
|
:key="refreshToken + '_yield_chart_linemonth'"
|
||||||
|
:raw-data="websocketData"
|
||||||
|
/>
|
||||||
|
<rate-chart
|
||||||
|
:display-placeholder="!displayRateChart"
|
||||||
|
:key="refreshToken + '_rate_chart_linemonth'"
|
||||||
|
:raw-data="websocketData"
|
||||||
|
:isOnlyChild="!displayProductionChart"
|
||||||
|
/>
|
||||||
|
<!-- <p
|
||||||
|
v-if="!displayProductionChart && !displayRateChart"
|
||||||
|
style="
|
||||||
|
height: 100%;
|
||||||
|
line-height: 350px;
|
||||||
|
user-select: none;
|
||||||
|
flex: 1;
|
||||||
|
color: #fffc;
|
||||||
|
font-size: 24px;
|
||||||
|
text-align: center;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
暂无数据
|
||||||
|
</p> -->
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chart {
|
||||||
|
/* height: 300px; */
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-chart {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-body__h-full {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
177
src/components/datapage/LineMonthOptions.js
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
export const options = {
|
||||||
|
color: ["#99D66C", "#5B9BFF", "#8167F6", "#FF00B2"],
|
||||||
|
grid: {
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0
|
||||||
|
},
|
||||||
|
title: [
|
||||||
|
{
|
||||||
|
text: "当前产量:" + 100 + " 片",
|
||||||
|
left: "27%",
|
||||||
|
textAlign: "center",
|
||||||
|
top: "70%",
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: '#fffd'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "目标产量:" + 100 + " 片",
|
||||||
|
left: "27%",
|
||||||
|
textAlign: "center",
|
||||||
|
top: "85%",
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: '#fffd'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "当前成品率:" + 22 + "%",
|
||||||
|
left: "72%",
|
||||||
|
textAlign: "center",
|
||||||
|
top: "70%",
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: '#fffd'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "目标成品率:" + 22 + "%",
|
||||||
|
left: "72%",
|
||||||
|
textAlign: "center",
|
||||||
|
top: "85%",
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: '#fffd'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: "gauge",
|
||||||
|
startAngle: 90,
|
||||||
|
center: ["27%", "35%"],
|
||||||
|
endAngle: -270,
|
||||||
|
radius: "55%",
|
||||||
|
progress: {
|
||||||
|
show: true,
|
||||||
|
width: 24,
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
width: 24,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pointer: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
valueAnimation: true,
|
||||||
|
fontSize: 16,
|
||||||
|
offsetCenter: [0, "0%"],
|
||||||
|
formatter: "{value}%",
|
||||||
|
color: "rgba(255, 255, 255, 1)",
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
// value: (nowProduction / targetProduction * 100).toFixed(1),
|
||||||
|
value: 100,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "gauge",
|
||||||
|
startAngle: 90,
|
||||||
|
center: ["73%", "35%"],
|
||||||
|
endAngle: -270,
|
||||||
|
radius: "55%",
|
||||||
|
progress: {
|
||||||
|
show: true,
|
||||||
|
width: 24,
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
width: 24,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pointer: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
show: true,
|
||||||
|
valueAnimation: true,
|
||||||
|
fontSize: 16,
|
||||||
|
offsetCenter: [0, "0%"],
|
||||||
|
// formatter: 0 + "%",
|
||||||
|
// formatter: (nowYield / targetYield * 100).toFixed(1) + '%',
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
// value: targetYield,
|
||||||
|
value: 100,
|
||||||
|
name: "Perfect",
|
||||||
|
title: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
show: false,
|
||||||
|
valueAnimation: true,
|
||||||
|
offsetCenter: ["0%", "-20%"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 100,
|
||||||
|
// value: nowYield,
|
||||||
|
name: "Good",
|
||||||
|
title: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
show: false,
|
||||||
|
valueAnimation: true,
|
||||||
|
offsetCenter: ["0%", "10%"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0,
|
||||||
|
detail: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
export default function setup(echartInstance, data) {
|
||||||
|
const new_options = { ...options };
|
||||||
|
new_options.title[0].text = "当前产量:" + data.nowProduction + " 片";
|
||||||
|
new_options.title[1].text = "目标产量:" + data.targetProduction + " 片";
|
||||||
|
new_options.title[2].text = "当前成品率:" + data.nowYield + "%";
|
||||||
|
new_options.title[3].text = "目标成品率:" + data.targetYield + "%";
|
||||||
|
new_options.series[0].data[0].value = (data.nowProduction / data.targetProduction * 100).toFixed(1)
|
||||||
|
new_options.series[1].data[0].value = data.targetYield
|
||||||
|
new_options.series[1].data[1].value = data.nowYield
|
||||||
|
new_options.series[1].detail.formatter = (data.nowYield / data.targetYield * 100).toFixed(2) + '%',
|
||||||
|
echartInstance.setOption(new_options);
|
||||||
|
}
|
||||||
102
src/components/datapage/LineToday copy.vue
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, nextTick } from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
import Container from "../Base/Container.vue";
|
||||||
|
import { useWsStore } from "../../store";
|
||||||
|
import setupFn from "./LineTodayOptions";
|
||||||
|
|
||||||
|
const show = ref(false);
|
||||||
|
const chartContainer = ref(null);
|
||||||
|
const chartInstance = ref(null);
|
||||||
|
const store = useWsStore();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
chartContainer.value.classList.add("h-full");
|
||||||
|
const d = loadData(store.data2.dailyTarget);
|
||||||
|
// const d = loadData([
|
||||||
|
// {
|
||||||
|
// targetProduction: 100,
|
||||||
|
// nowProduction: 66,
|
||||||
|
// targetYield: 13,
|
||||||
|
// nowYield: 3,
|
||||||
|
// },
|
||||||
|
// ]);
|
||||||
|
if (!d) {
|
||||||
|
show.value = false;
|
||||||
|
if (chartInstance.value) {
|
||||||
|
chartInstance.value.dispose();
|
||||||
|
chartInstance.value = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!chartInstance.value)
|
||||||
|
chartInstance.value = echarts.init(chartContainer.value);
|
||||||
|
setupFn(chartInstance.value, d);
|
||||||
|
show.value = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 订阅
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
const d = loadData(state.data2.dailyTarget);
|
||||||
|
// const d = loadData([
|
||||||
|
// {
|
||||||
|
// targetProduction: 100,
|
||||||
|
// nowProduction: 66,
|
||||||
|
// targetYield: 13,
|
||||||
|
// nowYield: 3,
|
||||||
|
// },
|
||||||
|
// ]);
|
||||||
|
if (!d) {
|
||||||
|
show.value = false;
|
||||||
|
if (chartInstance.value) {
|
||||||
|
chartInstance.value.dispose();
|
||||||
|
chartInstance.value = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!chartInstance.value)
|
||||||
|
chartInstance.value = echarts.init(chartContainer.value);
|
||||||
|
setupFn(chartInstance.value, d);
|
||||||
|
show.value = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// utils
|
||||||
|
function loadData(dailyTarget) {
|
||||||
|
if (
|
||||||
|
dailyTarget == undefined ||
|
||||||
|
// dailyTarget?.length == 0 ||
|
||||||
|
!dailyTarget[0]
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
targetProduction: dailyTarget[0].targetProduction,
|
||||||
|
nowProduction: dailyTarget[0].nowProduction,
|
||||||
|
targetYield: dailyTarget[0].targetYield,
|
||||||
|
nowYield: dailyTarget[0].nowYield,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Container class="chart" title="本日生产线情况" icon="cube">
|
||||||
|
<div
|
||||||
|
ref="chartContainer"
|
||||||
|
class="chart-chart"
|
||||||
|
:style="{ opacity: show ? 1 : 0 }"
|
||||||
|
></div>
|
||||||
|
<p v-show="!show" class="empty-data-hint">暂无数据</p>
|
||||||
|
</Container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chart {
|
||||||
|
/* height: 300px; */
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-chart {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
148
src/components/datapage/LineToday.vue
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, nextTick } from "vue";
|
||||||
|
import Container from "../Base/Container.vue";
|
||||||
|
import { useWsStore } from "../../store";
|
||||||
|
import YieldChart from "../Chart/YieldChart.vue";
|
||||||
|
import RateChart from "../Chart/RateChart.vue";
|
||||||
|
|
||||||
|
const displayProductionChart = ref(false);
|
||||||
|
const displayRateChart = ref(false);
|
||||||
|
const websocketData = ref(null);
|
||||||
|
const refreshToken = ref(1);
|
||||||
|
const store = useWsStore();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// websocketData.value = loadData([
|
||||||
|
// {
|
||||||
|
// targetProduction: 1220,
|
||||||
|
// nowProduction: 8,
|
||||||
|
// targetYield: null,
|
||||||
|
// nowYield: null,
|
||||||
|
// },
|
||||||
|
// ]);
|
||||||
|
websocketData.value = loadData(store.data2.dailyTarget);
|
||||||
|
if (!websocketData.value) {
|
||||||
|
displayProductionChart.value = false;
|
||||||
|
displayRateChart.value = false;
|
||||||
|
} else {
|
||||||
|
/** 阻止 targetProduction == 0 */
|
||||||
|
if (!websocketData.value.targetProduction) {
|
||||||
|
displayProductionChart.value = false;
|
||||||
|
} else {
|
||||||
|
displayProductionChart.value = true;
|
||||||
|
}
|
||||||
|
/** 阻止 targetYield == 0 */
|
||||||
|
if (!websocketData.value.targetYield) {
|
||||||
|
displayRateChart.value = false;
|
||||||
|
} else {
|
||||||
|
displayRateChart.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 订阅
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
// const d = loadData([
|
||||||
|
// {
|
||||||
|
// targetProduction: 100,
|
||||||
|
// nowProduction: 66,
|
||||||
|
// targetYield: 13,
|
||||||
|
// nowYield: 3,
|
||||||
|
// },
|
||||||
|
// ]);
|
||||||
|
websocketData.value = loadData(state.data2.dailyTarget);
|
||||||
|
if (!websocketData.value) {
|
||||||
|
displayProductionChart.value = false;
|
||||||
|
displayRateChart.value = false;
|
||||||
|
} else {
|
||||||
|
/** 阻止 targetProduction == 0 */
|
||||||
|
if (!websocketData.value.targetProduction) {
|
||||||
|
displayProductionChart.value = false;
|
||||||
|
} else {
|
||||||
|
if (refreshToken.value > 100000) refreshToken.value = 0;
|
||||||
|
refreshToken.value += 1;
|
||||||
|
displayProductionChart.value = true;
|
||||||
|
}
|
||||||
|
/** 阻止 targetYield == 0 */
|
||||||
|
if (!websocketData.value.targetYield) {
|
||||||
|
displayRateChart.value = false;
|
||||||
|
} else {
|
||||||
|
if (refreshToken.value > 100000) refreshToken.value = 0;
|
||||||
|
refreshToken.value += 1;
|
||||||
|
displayRateChart.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// utils
|
||||||
|
function loadData(dailyTarget) {
|
||||||
|
if (dailyTarget == undefined || !dailyTarget[0]) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
// 目标产量
|
||||||
|
targetProduction: dailyTarget[0].targetProduction,
|
||||||
|
// 当前产量
|
||||||
|
nowProduction: dailyTarget[0].nowProduction,
|
||||||
|
// 目标成品率
|
||||||
|
targetYield: dailyTarget[0].targetYield,
|
||||||
|
// 当前成品率
|
||||||
|
nowYield: dailyTarget[0].nowYield,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Container class="chart" title="本日生产线情况" icon="cube">
|
||||||
|
<!-- <div
|
||||||
|
ref="chartContainer"
|
||||||
|
class="chart-chart"
|
||||||
|
:style="{ opacity: show ? 1 : 0 }"
|
||||||
|
></div>
|
||||||
|
<p v-show="!show" class="empty-data-hint">暂无数据</p> -->
|
||||||
|
<div class="container-body__h-full">
|
||||||
|
<yield-chart
|
||||||
|
:key="refreshToken + '_yield_chart_linetoday'"
|
||||||
|
:raw-data="websocketData"
|
||||||
|
/>
|
||||||
|
<rate-chart
|
||||||
|
:display-placeholder="!displayRateChart"
|
||||||
|
:key="refreshToken + '_rate_chart_linetoday'"
|
||||||
|
:raw-data="websocketData"
|
||||||
|
:isOnlyChild="!displayProductionChart"
|
||||||
|
/>
|
||||||
|
<!-- <p
|
||||||
|
v-if="!displayProductionChart && !displayRateChart"
|
||||||
|
style="
|
||||||
|
height: 100%;
|
||||||
|
line-height: 350px;
|
||||||
|
user-select: none;
|
||||||
|
flex: 1;
|
||||||
|
color: #fffc;
|
||||||
|
font-size: 24px;
|
||||||
|
text-align: center;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
暂无数据
|
||||||
|
</p> -->
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chart {
|
||||||
|
/* height: 300px; */
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-chart {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-body__h-full {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
192
src/components/datapage/LineTodayOptions.js
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
export const options = {
|
||||||
|
color: ["#99D66C", "#5B9BFF", "#8167F6", "#FF00B2"],
|
||||||
|
grid: {
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
},
|
||||||
|
title: [
|
||||||
|
{
|
||||||
|
text: "当前产量:" + 118 + " 片",
|
||||||
|
left: "27%",
|
||||||
|
textAlign: "center",
|
||||||
|
top: "70%",
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: "#fffd",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "目标产量:" + 213 + " 片",
|
||||||
|
left: "27%",
|
||||||
|
textAlign: "center",
|
||||||
|
top: "85%",
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: "#fffd",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "当前成品率:" + 78 + "%",
|
||||||
|
left: "72%",
|
||||||
|
textAlign: "center",
|
||||||
|
top: "70%",
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: "#fffd",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "目标成品率:" + 90 + "%",
|
||||||
|
left: "72%",
|
||||||
|
textAlign: "center",
|
||||||
|
top: "85%",
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: "#fffd",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: "gauge",
|
||||||
|
startAngle: 90,
|
||||||
|
center: ["27%", "35%"],
|
||||||
|
endAngle: -270,
|
||||||
|
radius: "55%",
|
||||||
|
progress: {
|
||||||
|
show: true,
|
||||||
|
width: 24,
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
width: 24,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pointer: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
valueAnimation: true,
|
||||||
|
fontSize: 16,
|
||||||
|
offsetCenter: [0, "0%"],
|
||||||
|
formatter: "{value}%",
|
||||||
|
color: "rgba(255, 255, 255, 1)",
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
// value: (nowProduction / targetProduction * 100).toFixed(1),
|
||||||
|
value: 89.78,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "gauge",
|
||||||
|
startAngle: 90,
|
||||||
|
center: ["73%", "35%"],
|
||||||
|
endAngle: -270,
|
||||||
|
radius: "55%",
|
||||||
|
progress: {
|
||||||
|
show: true,
|
||||||
|
width: 24,
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
width: 24,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pointer: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
show: true,
|
||||||
|
valueAnimation: true,
|
||||||
|
fontSize: 16,
|
||||||
|
offsetCenter: [0, "0%"],
|
||||||
|
// formatter: 0 + "%",
|
||||||
|
// formatter: (nowYield / targetYield * 100).toFixed(1) + '%',
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
// value: targetYield,
|
||||||
|
value: 78,
|
||||||
|
name: "Perfect",
|
||||||
|
title: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
show: false,
|
||||||
|
valueAnimation: true,
|
||||||
|
offsetCenter: ["0%", "-20%"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 90,
|
||||||
|
name: "Good",
|
||||||
|
title: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
show: false,
|
||||||
|
valueAnimation: true,
|
||||||
|
offsetCenter: ["0%", "10%"],
|
||||||
|
formatter: "99.23%",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0,
|
||||||
|
detail: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
export default function setup(echartInstance, data) {
|
||||||
|
const new_options = { ...options };
|
||||||
|
new_options.title[0].text = "当前产量:" + data.nowProduction + " 片";
|
||||||
|
new_options.title[1].text = "目标产量:" + data.targetProduction + " 片";
|
||||||
|
new_options.title[2].text = "当前成品率:" + data.nowYield + "%";
|
||||||
|
new_options.title[3].text = "目标成品率:" + data.targetYield + "%";
|
||||||
|
new_options.series[0].data[0].value =
|
||||||
|
data.nowProduction != null &&
|
||||||
|
data.targetProduction != null &&
|
||||||
|
data.targetProduction != 0
|
||||||
|
? ((data.nowProduction / data.targetProduction) * 100).toFixed(1)
|
||||||
|
: 0;
|
||||||
|
new_options.series[1].data[0].value = data.targetYield;
|
||||||
|
new_options.series[1].data[1].value = data.nowYield;
|
||||||
|
new_options.series[1].detail.formatter =
|
||||||
|
data.nowYield != null && data.targetYield != null && data.targetYield != 0
|
||||||
|
? ((data.nowYield / data.targetYield) * 100).toFixed(2) + "%"
|
||||||
|
: "0%";
|
||||||
|
echartInstance.setOption(new_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "targetProduction": 99,
|
||||||
|
// "nowProduction": 58,
|
||||||
|
// "targetYield": 12,
|
||||||
|
// "nowYield": 9
|
||||||
|
// }
|
||||||
84
src/components/datapage/TeamChartDay.vue
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, nextTick } from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
import Container from "../Base/Container.vue";
|
||||||
|
import { useWsStore } from "../../store";
|
||||||
|
import setupFn from "./TeamChartDayOptions";
|
||||||
|
|
||||||
|
const store = useWsStore();
|
||||||
|
const chartChart = ref(null);
|
||||||
|
const chart = ref(null);
|
||||||
|
const showChartDom = ref(false);
|
||||||
|
|
||||||
|
/** 无状态,处理数据 */
|
||||||
|
function loadData(yieldArray) {
|
||||||
|
const result = [];
|
||||||
|
if (yieldArray == undefined || yieldArray?.length == 0) return null;
|
||||||
|
for (let i = 0; i < yieldArray.length; ++i) {
|
||||||
|
if (yieldArray[i].teamName == "A组") {
|
||||||
|
result[0] = parseInt(yieldArray[i].yield);
|
||||||
|
} else if (yieldArray[i].teamName == "B组") {
|
||||||
|
result[1] = parseInt(yieldArray[i].yield);
|
||||||
|
} else if (yieldArray[i].teamName == "C组") {
|
||||||
|
result[2] = parseInt(yieldArray[i].yield);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupChart(chart, dom, data) {
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
nextTick(() => {
|
||||||
|
chart.value = echarts.init(dom);
|
||||||
|
setupFn(chart.value, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 有状态,处理数据 */
|
||||||
|
function __apply(yieldArray) {
|
||||||
|
const d = loadData(yieldArray);
|
||||||
|
// const d = loadData([
|
||||||
|
// { teamName: "A组", yield: 11 },
|
||||||
|
// { teamName: "B组", yield: 23 },
|
||||||
|
// { teamName: "C组", yield: 14 },
|
||||||
|
// ]);
|
||||||
|
if (!d) {
|
||||||
|
showChartDom.value = false;
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showChartDom.value = true;
|
||||||
|
setupChart(chart, chartChart.value, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订阅
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
__apply(state.data2.classTodayProductYield);
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
chartChart.value.classList.add("h-full");
|
||||||
|
// __apply();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Container class="chart" title="本日班组情况" icon="cube">
|
||||||
|
<div
|
||||||
|
ref="chartChart"
|
||||||
|
class="chart-chart"
|
||||||
|
:style="{ opacity: showChartDom ? 1 : 0 }"
|
||||||
|
></div>
|
||||||
|
<p v-show="!chart" class="empty-data-hint">暂无数据</p>
|
||||||
|
</Container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chart {
|
||||||
|
/* height: 300px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-chart {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
59
src/components/datapage/TeamChartDayOptions.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
export const options = {
|
||||||
|
color: ['#a4c9d1', '#72340b', '#ffd601' ],
|
||||||
|
grid: {
|
||||||
|
top: 8,
|
||||||
|
bottom: 20,
|
||||||
|
left: 42,
|
||||||
|
right: 28,
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
max: 100,
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: "#fff2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: "#e5e5e5a3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: "category",
|
||||||
|
data: ["A组", "B组", "C组"],
|
||||||
|
inverse: true,
|
||||||
|
max: 2, // only the largest 3 bars will be displayed
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: "#e5e5e5a3",
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: "#e5e5e5",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: "bar",
|
||||||
|
data: [34, 2, 23],
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: "right",
|
||||||
|
formatter: "{c}%",
|
||||||
|
color: "#fff",
|
||||||
|
fontSize: 16,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function setup(echartInstance, dataArr) {
|
||||||
|
const new_options = { ...options };
|
||||||
|
new_options.series[0].data = dataArr;
|
||||||
|
echartInstance.setOption(new_options);
|
||||||
|
}
|
||||||
84
src/components/datapage/TeamChartMonth.vue
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, nextTick } from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
import Container from "../Base/Container.vue";
|
||||||
|
import { useWsStore } from "../../store";
|
||||||
|
import setupFn from "./TeamChartMonthOptions";
|
||||||
|
|
||||||
|
const store = useWsStore();
|
||||||
|
const chartChart = ref(null);
|
||||||
|
const chart = ref(null);
|
||||||
|
const showChartDom = ref(false);
|
||||||
|
|
||||||
|
/** 无状态,处理数据 */
|
||||||
|
function loadData(yieldArray) {
|
||||||
|
if (yieldArray == undefined || yieldArray?.length == 0) return null;
|
||||||
|
const result = [];
|
||||||
|
for (let i = 0; i < yieldArray.length; ++i) {
|
||||||
|
if (yieldArray[i].teamName == "A组") {
|
||||||
|
result[0] = parseInt(yieldArray[i].yield);
|
||||||
|
} else if (yieldArray[i].teamName == "B组") {
|
||||||
|
result[1] = parseInt(yieldArray[i].yield);
|
||||||
|
} else if (yieldArray[i].teamName == "C组") {
|
||||||
|
result[2] = parseInt(yieldArray[i].yield);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupChart(chart, dom, data) {
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
nextTick(() => {
|
||||||
|
chart.value = echarts.init(dom);
|
||||||
|
setupFn(chart.value, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 有状态,处理数据 */
|
||||||
|
function __apply(yieldArray) {
|
||||||
|
const d = loadData(yieldArray);
|
||||||
|
// const d = loadData([
|
||||||
|
// { teamName: "A组", yield: 11 },
|
||||||
|
// { teamName: "B组", yield: 23 },
|
||||||
|
// { teamName: "C组", yield: 14 },
|
||||||
|
// ]);
|
||||||
|
if (!d) {
|
||||||
|
showChartDom.value = false;
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showChartDom.value = true;
|
||||||
|
setupChart(chart, chartChart.value, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订阅
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
__apply(state.data2.lineTeamMonthYieldList);
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
chartChart.value.classList.add("h-full");
|
||||||
|
// __apply();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Container class="chart" title="本月班组情况" icon="cube">
|
||||||
|
<div
|
||||||
|
ref="chartChart"
|
||||||
|
class="chart-chart"
|
||||||
|
:style="{ opacity: showChartDom ? 1 : 0 }"
|
||||||
|
></div>
|
||||||
|
<p v-show="!chart" class="empty-data-hint">暂无数据</p>
|
||||||
|
</Container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chart {
|
||||||
|
/* height: 300px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-chart {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
59
src/components/datapage/TeamChartMonthOptions.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
export const options = {
|
||||||
|
color: ['#a4c9d1', '#72340b', '#ffd601' ],
|
||||||
|
grid: {
|
||||||
|
top: 8,
|
||||||
|
bottom: 20,
|
||||||
|
left: 42,
|
||||||
|
right: 28,
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
max: 100,
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: "#fff2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: "#e5e5e5a3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: "category",
|
||||||
|
data: ["A组", "B组", "C组"],
|
||||||
|
inverse: true,
|
||||||
|
max: 2, // only the largest 3 bars will be displayed
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: "#e5e5e5a3",
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: "#e5e5e5",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: "bar",
|
||||||
|
data: [34, 2, 23],
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: "right",
|
||||||
|
formatter: "{c}%",
|
||||||
|
color: "#fff",
|
||||||
|
fontSize: 16,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function setup(echartInstance, dataArr) {
|
||||||
|
const new_options = { ...options };
|
||||||
|
new_options.series[0].data = dataArr;
|
||||||
|
echartInstance.setOption(new_options);
|
||||||
|
}
|
||||||
152
src/components/mainscreen/SumRate.vue
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, nextTick } from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
import Container from "../Base/Container.vue";
|
||||||
|
import { useWsStore } from "../../store";
|
||||||
|
|
||||||
|
const setupFn = (chart, datalist = [0.0, 0.0, 0.0]) => {
|
||||||
|
const option = {
|
||||||
|
color: ["#F3908B"],
|
||||||
|
tooltip: {
|
||||||
|
trigger: "axis",
|
||||||
|
axisPointer: {
|
||||||
|
type: "shadow",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: "5%",
|
||||||
|
bottom: "5%",
|
||||||
|
left: "3%",
|
||||||
|
right: "5%",
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: "value",
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: "#ccc6",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: "category",
|
||||||
|
data: ["钢1线", "钢2线", "钢3线"],
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: "#ccc6",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: "line",
|
||||||
|
data: datalist,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: "top",
|
||||||
|
// formatter: (params) => {
|
||||||
|
// console.log("params", datalist[params.dataIndex]);
|
||||||
|
// },
|
||||||
|
formatter: "{c}%",
|
||||||
|
color: "#fff",
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
chart.setOption(option);
|
||||||
|
};
|
||||||
|
|
||||||
|
const store = useWsStore();
|
||||||
|
const chartChart = ref(null);
|
||||||
|
const chart = ref(null);
|
||||||
|
const showChartDom = ref(false);
|
||||||
|
|
||||||
|
/** 无状态,处理数据 */
|
||||||
|
function loadData(yieldArray) {
|
||||||
|
// lineSumProductYield
|
||||||
|
const result = [];
|
||||||
|
if (yieldArray == undefined || yieldArray?.length == 0) return null;
|
||||||
|
for (let i = 0; i < yieldArray.length; ++i) {
|
||||||
|
if (yieldArray[i].name == "钢1线") {
|
||||||
|
result[0] = parseFloat(yieldArray[i].data);
|
||||||
|
} else if (yieldArray[i].name == "钢2线") {
|
||||||
|
result[1] = parseFloat(yieldArray[i].data);
|
||||||
|
} else if (yieldArray[i].name == "钢3线") {
|
||||||
|
result[2] = parseFloat(yieldArray[i].data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupChart(chart, dom, data) {
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
nextTick(() => {
|
||||||
|
chart.value = echarts.init(dom);
|
||||||
|
setupFn(chart.value, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 有状态,处理数据 */
|
||||||
|
function __apply(yieldArray) {
|
||||||
|
const d = loadData(yieldArray);
|
||||||
|
if (!d) {
|
||||||
|
showChartDom.value = false;
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showChartDom.value = true;
|
||||||
|
setupChart(chart, chartChart.value, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订阅
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
__apply(state.mainDataChart.lineSumProductYield);
|
||||||
|
// __apply([
|
||||||
|
// { name: "钢1线", data: 0.32 },
|
||||||
|
// { name: "钢2线", data: 0.91 },
|
||||||
|
// { name: "钢3线", data: 0.54 },
|
||||||
|
// ]);
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
chartChart.value.classList.add("h-full");
|
||||||
|
__apply([
|
||||||
|
{ name: "钢1线", data: "0%" },
|
||||||
|
{ name: "钢2线", data: "0%" },
|
||||||
|
{ name: "钢3线", data: "0%" },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Container class="chart" title="累计生产线成品率" icon="cube">
|
||||||
|
<div
|
||||||
|
ref="chartChart"
|
||||||
|
class="chart-chart"
|
||||||
|
:style="{ opacity: showChartDom ? 1 : 0 }"
|
||||||
|
></div>
|
||||||
|
<p v-show="!chart" class="empty-data-hint">暂无数据</p>
|
||||||
|
</Container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chart {
|
||||||
|
/* height: 300px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-chart {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
157
src/components/mainscreen/SumYield.vue
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, nextTick } from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
import Container from "../Base/Container.vue";
|
||||||
|
import { useWsStore } from "../../store";
|
||||||
|
|
||||||
|
const setupFn = (chart, datalist = [0.0, 0.0, 0.0, 0.0]) => {
|
||||||
|
console.log("datalist", datalist);
|
||||||
|
const option = {
|
||||||
|
color: ["#3398FB"],
|
||||||
|
tooltip: {
|
||||||
|
trigger: "axis",
|
||||||
|
axisPointer: {
|
||||||
|
type: "shadow",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: "5%",
|
||||||
|
bottom: "5%",
|
||||||
|
left: "3%",
|
||||||
|
right: "5%",
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: "value",
|
||||||
|
boundaryGap: [0, 0.01],
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: "#fff",
|
||||||
|
rotate: 32,
|
||||||
|
margin: 12
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: "#ccc6",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: "category",
|
||||||
|
data: ["钢1线", "钢2线", "钢3线", "合计"],
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: "#ccc6",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: "bar",
|
||||||
|
data: datalist,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: "right",
|
||||||
|
formatter: "{c}",
|
||||||
|
color: "#fff",
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
chart.setOption(option);
|
||||||
|
};
|
||||||
|
|
||||||
|
const store = useWsStore();
|
||||||
|
const chartChart = ref(null);
|
||||||
|
const chart = ref(null);
|
||||||
|
const showChartDom = ref(false);
|
||||||
|
|
||||||
|
/** 无状态,处理数据 */
|
||||||
|
function loadData(yieldArray) {
|
||||||
|
const result = [];
|
||||||
|
if (yieldArray == undefined || yieldArray?.length == 0) return null;
|
||||||
|
for (let i = 0; i < yieldArray.length; ++i) {
|
||||||
|
if (yieldArray[i].name == "钢1线") {
|
||||||
|
result[0] = parseFloat(yieldArray[i].data) || 0;
|
||||||
|
} else if (yieldArray[i].name == "钢2线") {
|
||||||
|
result[1] = parseFloat(yieldArray[i].data) || 0;
|
||||||
|
} else if (yieldArray[i].name == "钢3线") {
|
||||||
|
result[2] = parseFloat(yieldArray[i].data) || 0;
|
||||||
|
} else {
|
||||||
|
// 合计
|
||||||
|
result[3] = parseFloat(yieldArray[i].data) || 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupChart(chart, dom, data) {
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
nextTick(() => {
|
||||||
|
chart.value = echarts.init(dom);
|
||||||
|
setupFn(chart.value, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 有状态,处理数据 */
|
||||||
|
function __apply(yieldArray) {
|
||||||
|
const d = loadData(yieldArray);
|
||||||
|
if (!d) {
|
||||||
|
showChartDom.value = false;
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showChartDom.value = true;
|
||||||
|
setupChart(chart, chartChart.value, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订阅
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
__apply(state.mainDataChart.lineSumProductData);
|
||||||
|
// __apply([
|
||||||
|
// { name: "钢1线", data: 11 },
|
||||||
|
// { name: "钢2线", data: 22 },
|
||||||
|
// { name: "钢3线", data: 33 },
|
||||||
|
// { name: "合计", data: 66 },
|
||||||
|
// ]);
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
chartChart.value.classList.add("h-full");
|
||||||
|
__apply([
|
||||||
|
{ name: "钢1线", data: 0 },
|
||||||
|
{ name: "钢2线", data: 0 },
|
||||||
|
{ name: "钢3线", data: 0 },
|
||||||
|
{ name: "合计", data: 0 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Container class="chart" title="累计生产线产量" icon="cube">
|
||||||
|
<div
|
||||||
|
ref="chartChart"
|
||||||
|
class="chart-chart"
|
||||||
|
:style="{ opacity: showChartDom ? 1 : 0 }"
|
||||||
|
></div>
|
||||||
|
<p v-show="!chart" class="empty-data-hint">暂无数据</p>
|
||||||
|
</Container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chart {
|
||||||
|
/* height: 300px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-chart {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
153
src/components/mainscreen/TodayRate.vue
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, nextTick } from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
import Container from "../Base/Container.vue";
|
||||||
|
import { useWsStore } from "../../store";
|
||||||
|
|
||||||
|
const setupFn = (chart, datalist = [0.0, 0.0, 0.0]) => {
|
||||||
|
const option = {
|
||||||
|
color: ["#F3908B"],
|
||||||
|
tooltip: {
|
||||||
|
trigger: "axis",
|
||||||
|
axisPointer: {
|
||||||
|
type: "shadow",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: "5%",
|
||||||
|
bottom: "5%",
|
||||||
|
left: "3%",
|
||||||
|
right: "5%",
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: "value",
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: "#ccc6",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: "category",
|
||||||
|
data: ["钢1线", "钢2线", "钢3线"],
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: "#ccc6",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: "line",
|
||||||
|
data: datalist,
|
||||||
|
// data: datalist.map((item) => item * 100),
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: "top",
|
||||||
|
// formatter: (params) => {
|
||||||
|
// console.log("params", datalist[params.dataIndex]);
|
||||||
|
// },
|
||||||
|
formatter: "{c}%",
|
||||||
|
color: "#fff",
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
chart.setOption(option);
|
||||||
|
};
|
||||||
|
|
||||||
|
const store = useWsStore();
|
||||||
|
const chartChart = ref(null);
|
||||||
|
const chart = ref(null);
|
||||||
|
const showChartDom = ref(false);
|
||||||
|
|
||||||
|
/** 无状态,处理数据 */
|
||||||
|
function loadData(yieldArray) {
|
||||||
|
// lineTodayProductYield
|
||||||
|
const result = [];
|
||||||
|
if (yieldArray == undefined || yieldArray?.length == 0) return null;
|
||||||
|
for (let i = 0; i < yieldArray.length; ++i) {
|
||||||
|
if (yieldArray[i].name == "钢1线") {
|
||||||
|
result[0] = parseFloat(yieldArray[i].data) || 0.0;
|
||||||
|
} else if (yieldArray[i].name == "钢2线") {
|
||||||
|
result[1] = parseFloat(yieldArray[i].data) || 0.0;
|
||||||
|
} else if (yieldArray[i].name == "钢3线") {
|
||||||
|
result[2] = parseFloat(yieldArray[i].data) || 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupChart(chart, dom, data) {
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
nextTick(() => {
|
||||||
|
chart.value = echarts.init(dom);
|
||||||
|
setupFn(chart.value, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 有状态,处理数据 */
|
||||||
|
function __apply(yieldArray) {
|
||||||
|
const d = loadData(yieldArray);
|
||||||
|
if (!d) {
|
||||||
|
showChartDom.value = false;
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showChartDom.value = true;
|
||||||
|
setupChart(chart, chartChart.value, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订阅
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
__apply(state.mainDataChart.lineTodayProductYield);
|
||||||
|
// __apply([
|
||||||
|
// { name: "钢1线", data: 0.32 },
|
||||||
|
// { name: "钢2线", data: 0.91 },
|
||||||
|
// { name: "钢3线", data: 0.54 },
|
||||||
|
// ]);
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
chartChart.value.classList.add("h-full");
|
||||||
|
__apply([
|
||||||
|
{ name: "钢1线", data: "0%" },
|
||||||
|
{ name: "钢2线", data: "0%" },
|
||||||
|
{ name: "钢3线", data: "0%" },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Container class="chart" title="今日生产线成品率" icon="cube">
|
||||||
|
<div
|
||||||
|
ref="chartChart"
|
||||||
|
class="chart-chart"
|
||||||
|
:style="{ opacity: showChartDom ? 1 : 0 }"
|
||||||
|
></div>
|
||||||
|
<p v-show="!chart" class="empty-data-hint">暂无数据</p>
|
||||||
|
</Container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chart {
|
||||||
|
/* height: 300px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-chart {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
161
src/components/mainscreen/TodayYield.vue
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, nextTick } from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
import Container from "../Base/Container.vue";
|
||||||
|
import { useWsStore } from "../../store";
|
||||||
|
|
||||||
|
const setupFn = (chart, datalist = [0.0, 0.0, 0.0, 0.0]) => {
|
||||||
|
console.log("datalist", datalist);
|
||||||
|
const option = {
|
||||||
|
color: ["#3398FB"],
|
||||||
|
tooltip: {
|
||||||
|
trigger: "axis",
|
||||||
|
axisPointer: {
|
||||||
|
type: "shadow",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: "5%",
|
||||||
|
bottom: "5%",
|
||||||
|
left: "3%",
|
||||||
|
right: "5%",
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: "value",
|
||||||
|
boundaryGap: [0, 0.01],
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: "#fff",
|
||||||
|
rotate: 32,
|
||||||
|
margin: 12
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: "#ccc6",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: "category",
|
||||||
|
data: ["钢1线", "钢2线", "钢3线", "合计"],
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: "#ccc6",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: "bar",
|
||||||
|
data: datalist,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: "right",
|
||||||
|
formatter: "{c}",
|
||||||
|
color: "#fff",
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
chart.setOption(option);
|
||||||
|
};
|
||||||
|
|
||||||
|
const store = useWsStore();
|
||||||
|
const chartChart = ref(null);
|
||||||
|
const chart = ref(null);
|
||||||
|
const showChartDom = ref(false);
|
||||||
|
|
||||||
|
/** 无状态,处理数据 */
|
||||||
|
function loadData(yieldArray) {
|
||||||
|
// lineTodayProductData
|
||||||
|
const result = [];
|
||||||
|
if (yieldArray == undefined || yieldArray?.length == 0) return null;
|
||||||
|
for (let i = 0; i < yieldArray.length; ++i) {
|
||||||
|
if (yieldArray[i].name == "钢1线") {
|
||||||
|
result[0] = parseFloat(yieldArray[i].data) || 0;
|
||||||
|
} else if (yieldArray[i].name == "钢2线") {
|
||||||
|
result[1] = parseFloat(yieldArray[i].data) || 0;
|
||||||
|
} else if (yieldArray[i].name == "钢3线") {
|
||||||
|
result[2] = parseFloat(yieldArray[i].data) || 0;
|
||||||
|
} else {
|
||||||
|
// 合计
|
||||||
|
result[3] = parseFloat(yieldArray[i].data) || 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupChart(chart, dom, data) {
|
||||||
|
if (chart.value) {
|
||||||
|
chart.value.dispose();
|
||||||
|
chart.value = null;
|
||||||
|
}
|
||||||
|
nextTick(() => {
|
||||||
|
chart.value = echarts.init(dom);
|
||||||
|
setupFn(chart.value, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 有状态,处理数据 */
|
||||||
|
function __apply(yieldArray) {
|
||||||
|
const d = loadData(yieldArray);
|
||||||
|
if (!d) {
|
||||||
|
showChartDom.value = false;
|
||||||
|
if (chart.value) chart.value.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showChartDom.value = true;
|
||||||
|
setupChart(chart, chartChart.value, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订阅
|
||||||
|
store.$subscribe((mutation, state) => {
|
||||||
|
__apply(state.mainDataChart.lineTodayProductData);
|
||||||
|
// __apply([
|
||||||
|
// { name: "钢1线", data: 11 },
|
||||||
|
// { name: "钢2线", data: 22 },
|
||||||
|
// { name: "钢3线", data: 33 },
|
||||||
|
// { name: "合计", data: 66 },
|
||||||
|
// ]);
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
chartChart.value.classList.add("h-full");
|
||||||
|
__apply([
|
||||||
|
{ name: "钢1线", data: 0 },
|
||||||
|
{ name: "钢2线", data: 0 },
|
||||||
|
{ name: "钢3线", data: 0 },
|
||||||
|
{ name: "合计", data: 0 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Container class="chart" title="今日生产线产量" icon="cube">
|
||||||
|
<div
|
||||||
|
ref="chartChart"
|
||||||
|
class="chart-chart"
|
||||||
|
:style="{ opacity: showChartDom ? 1 : 0 }"
|
||||||
|
></div>
|
||||||
|
<p v-show="!chart" class="empty-data-hint">暂无数据</p>
|
||||||
|
</Container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chart {
|
||||||
|
/* height: 300px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-chart {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
180
src/full-eq-list.css
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
#main-container__fulleq {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: url(./assets/full-lines.png) 100% / cover no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name-tag {
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background: #ccc3;
|
||||||
|
backdrop-filter: blur(3px);
|
||||||
|
color: #000a;
|
||||||
|
font-size: 12px;
|
||||||
|
/* font-weight: 600; */
|
||||||
|
transition: background 0.1s ease-out;
|
||||||
|
user-select: none;
|
||||||
|
width: 72px;
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
/* cursor: pointer; */
|
||||||
|
/* transform: rotate(-45deg); */
|
||||||
|
box-shadow: 0 0 5px 2px #0003;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .name-tag:hover {
|
||||||
|
background: #666c;
|
||||||
|
} */
|
||||||
|
|
||||||
|
.tag-container > .name-tag:first-child {
|
||||||
|
bottom: 214px;
|
||||||
|
left: -128px;
|
||||||
|
}
|
||||||
|
.tag-container > .name-tag:nth-child(2) {
|
||||||
|
bottom: 182px;
|
||||||
|
left: -100px;
|
||||||
|
}
|
||||||
|
.tag-container > .name-tag:nth-child(3) {
|
||||||
|
bottom: 150px;
|
||||||
|
left: -88px;
|
||||||
|
}
|
||||||
|
.tag-container > .name-tag:nth-child(4) {
|
||||||
|
bottom: 118px;
|
||||||
|
left: -68px;
|
||||||
|
}
|
||||||
|
.tag-container > .name-tag:nth-child(5) {
|
||||||
|
bottom: 86px;
|
||||||
|
left: -52px;
|
||||||
|
}
|
||||||
|
.tag-container > .name-tag:nth-child(6) {
|
||||||
|
bottom: 32px;
|
||||||
|
left: -20px;
|
||||||
|
}
|
||||||
|
.tag-container > .name-tag:nth-child(7) {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.absolute {
|
||||||
|
position: absolute;
|
||||||
|
padding: 8px;
|
||||||
|
z-index: 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-1 {
|
||||||
|
bottom: 160px;
|
||||||
|
left: 430px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-2 {
|
||||||
|
bottom: 200px;
|
||||||
|
left: 480px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-3 {
|
||||||
|
bottom: 250px;
|
||||||
|
left: 620px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-1 > .name-tag:first-child {
|
||||||
|
bottom: 205px;
|
||||||
|
left: -155px;
|
||||||
|
}
|
||||||
|
.z-1 > .name-tag:nth-child(2) {
|
||||||
|
bottom: 180px;
|
||||||
|
left: -130px;
|
||||||
|
}
|
||||||
|
.v-4 {
|
||||||
|
bottom: 300px;
|
||||||
|
left: 730px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-5 {
|
||||||
|
bottom: 340px;
|
||||||
|
left: 780px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-6 {
|
||||||
|
bottom: 360px;
|
||||||
|
left: 840px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-2 > .name-tag:first-child {
|
||||||
|
bottom: 205px;
|
||||||
|
left: -140px;
|
||||||
|
}
|
||||||
|
.z-2 > .name-tag:nth-child(2) {
|
||||||
|
bottom: 180px;
|
||||||
|
left: -110px;
|
||||||
|
}
|
||||||
|
.z-2 > .name-tag:nth-child(3) {
|
||||||
|
bottom: 152px;
|
||||||
|
left: -70px;
|
||||||
|
}
|
||||||
|
.z-2 > .name-tag:nth-child(4) {
|
||||||
|
bottom: 128px;
|
||||||
|
left: -50px;
|
||||||
|
}
|
||||||
|
.z-2 > .name-tag:nth-child(5) {
|
||||||
|
bottom: 100px;
|
||||||
|
left: -36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-7 {
|
||||||
|
bottom: 380px;
|
||||||
|
left: 880px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-8 {
|
||||||
|
bottom: 410px;
|
||||||
|
left: 930px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-9 {
|
||||||
|
bottom: 440px;
|
||||||
|
left: 1020px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-10 {
|
||||||
|
bottom: 260px;
|
||||||
|
left: 1100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-3 {
|
||||||
|
bottom: 550px;
|
||||||
|
left: 1400px;
|
||||||
|
/* background: #c003; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-3 > .name-tag:first-child {
|
||||||
|
bottom: 235px;
|
||||||
|
left: -155px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-3 > .name-tag:nth-child(2) {
|
||||||
|
bottom: 188px;
|
||||||
|
left: -85px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-3 > .name-tag:nth-child(3) {
|
||||||
|
bottom: 120px;
|
||||||
|
left: 35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.b-1 {
|
||||||
|
bottom: 570px;
|
||||||
|
left: 1440px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.b-2 {
|
||||||
|
bottom: 600px;
|
||||||
|
left: 1490px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.b-3 {
|
||||||
|
bottom: 620px;
|
||||||
|
left: 1530px;
|
||||||
|
}
|
||||||
23
src/main.js
@@ -1,16 +1,19 @@
|
|||||||
import { createApp } from 'vue';
|
import { createApp } from "vue";
|
||||||
import { createPinia } from 'pinia'
|
import { createPinia } from "pinia";
|
||||||
|
|
||||||
|
import "./style.css";
|
||||||
|
import ElementPlus from "element-plus";
|
||||||
|
import "element-plus/dist/index.css";
|
||||||
|
import Vue3Marquee from "vue3-marquee";
|
||||||
|
import App from "./App.vue";
|
||||||
|
const pinia = createPinia();
|
||||||
|
|
||||||
import './style.css';
|
setTimeout(() => {
|
||||||
import ElementPlus from 'element-plus';
|
window.location.reload();
|
||||||
import 'element-plus/dist/index.css';
|
}, 60 * 60 * 1000);
|
||||||
import Vue3Marquee from 'vue3-marquee';
|
|
||||||
import App from './App.vue';
|
|
||||||
const pinia = createPinia()
|
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
app.use(pinia);
|
app.use(pinia);
|
||||||
app.use(ElementPlus);
|
app.use(ElementPlus);
|
||||||
app.use(Vue3Marquee, { name: 'ScrollText' });
|
app.use(Vue3Marquee, { name: "ScrollText" });
|
||||||
app.mount('#app');
|
app.mount("#app");
|
||||||
|
|||||||
2304
src/pages/3D.vue
@@ -3,18 +3,23 @@
|
|||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useWsStore } from "../store";
|
import { useWsStore } from "../store";
|
||||||
import Container from "../components/Base/Container.vue";
|
import Container from "../components/Base/Container.vue";
|
||||||
const alarmList = ref([]);
|
import ThreeD from './3D.vue'
|
||||||
const store = useWsStore();
|
|
||||||
|
|
||||||
alarmList.value = (store.data1.alarmArrList ?? []).map((item, index) => ({
|
const props = defineProps({
|
||||||
|
line: {
|
||||||
|
type: Number,
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const store = useWsStore();
|
||||||
|
const alarmList = ref((store.data1.alarmArrList || []).map((item, index) => ({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
eqName: item.equipmentName,
|
eqName: item.equipmentName,
|
||||||
eqIndex: index + 1,
|
eqIndex: index + 1,
|
||||||
alarmGrade: item.alarmLevel,
|
alarmGrade: item.alarmLevel,
|
||||||
alarmDetail: item.alarmDetails,
|
alarmDetail: item.alarmDetails,
|
||||||
position: `${item.productLine} - ${item.segment}`,
|
position: `${item.productLine} - ${item.segment}`,
|
||||||
}));
|
})));
|
||||||
|
|
||||||
store.$subscribe((mutation, state) => {
|
store.$subscribe((mutation, state) => {
|
||||||
alarmList.value = state.data1.alarmArrList.map((item, index) => ({
|
alarmList.value = state.data1.alarmArrList.map((item, index) => ({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
@@ -25,43 +30,29 @@ store.$subscribe((mutation, state) => {
|
|||||||
position: `${item.productLine} - ${item.segment}`,
|
position: `${item.productLine} - ${item.segment}`,
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// function handleIgnore() {
|
||||||
|
// alarmList.value.splice(0)
|
||||||
|
// }
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="alert-list-page">
|
<div class="alert-list-page">
|
||||||
|
<div style="position: absolute; top: 0; left: -279px; width: calc(100% + 279px); height: 100%;">
|
||||||
|
<ThreeD :line="line ?? '1'" />
|
||||||
|
</div>
|
||||||
<Container class="alert-list" title="报警列表" icon="cube">
|
<Container class="alert-list" title="报警列表" icon="cube">
|
||||||
<div class="alert-list__table" style="">
|
<div class="alert-list__table" style="">
|
||||||
<el-table
|
<el-table class="dark-table" :data="alarmList" :show-overflow-tooltip="true" row-class-name="dark-row"
|
||||||
class="dark-table"
|
header-row-class-name="dark-header">
|
||||||
:data="alarmList"
|
<el-table-column prop="eqName" label="设备名" width="80"></el-table-column>
|
||||||
:show-overflow-tooltip="true"
|
<el-table-column prop="eqIndex" label="序号" width="60"></el-table-column>
|
||||||
row-class-name="dark-row"
|
<el-table-column prop="alarmGrade" label="报警等级" width="100"></el-table-column>
|
||||||
header-row-class-name="dark-header"
|
<el-table-column prop="alarmDetail" label="报警细节" width="144"></el-table-column>
|
||||||
>
|
|
||||||
<el-table-column
|
|
||||||
prop="eqName"
|
|
||||||
label="设备名"
|
|
||||||
width="78"
|
|
||||||
></el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
prop="eqIndex"
|
|
||||||
label="序号"
|
|
||||||
width="56"
|
|
||||||
></el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
prop="alarmGrade"
|
|
||||||
label="报警等级"
|
|
||||||
width="90"
|
|
||||||
></el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
prop="alarmDetail"
|
|
||||||
label="报警细节"
|
|
||||||
width="144"
|
|
||||||
></el-table-column>
|
|
||||||
<el-table-column prop="position" label="定位"></el-table-column>
|
<el-table-column prop="position" label="定位"></el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
<button class="alert-btn">忽略</button>
|
<!-- <button @click="handleIgnore" class="alert-btn">忽略</button> -->
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -72,19 +63,31 @@ store.$subscribe((mutation, state) => {
|
|||||||
/* height: 72%; */
|
/* height: 72%; */
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-row {
|
.dark-row {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: #005eff25 !important;
|
background: #006ACD32 !important;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-row > td.el-table__cell {
|
.dark-row:nth-child(odd) {
|
||||||
|
background: #020D2D32 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-row>td.el-table__cell {
|
||||||
border: none;
|
border: none;
|
||||||
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-row:hover > td.el-table__cell {
|
.dark-row>td.el-table__cell:not(:last-child) {
|
||||||
background-color: #005effaa !important;
|
border-right: 1px solid #0003;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-row:hover>td.el-table__cell {
|
||||||
|
/* background-color: #020D2D20 !important; */
|
||||||
|
background-color: #fff1 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-header {
|
.dark-header {
|
||||||
@@ -92,14 +95,19 @@ store.$subscribe((mutation, state) => {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-header > th.el-table__cell.is-leaf {
|
.dark-header>th.el-table__cell.is-leaf {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
background-color: #005eff95 !important;
|
background-color: #006ACD32 !important;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-header > th.el-table__cell {
|
.dark-header>th.el-table__cell {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-header>th.el-table__cell:not(:last-child) {
|
||||||
|
border-right: 1px solid #0003;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@@ -121,12 +129,18 @@ store.$subscribe((mutation, state) => {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:fullscreen .alert-list {
|
||||||
|
width: 35%;
|
||||||
|
top: 32px;
|
||||||
|
height: calc(100% - 64px);
|
||||||
|
}
|
||||||
|
|
||||||
.alert-list__table {
|
.alert-list__table {
|
||||||
height: calc(100% - 72px);
|
height: calc(100% - 72px);
|
||||||
/* background: linear-gradient(to right, transparent, #0ba6ff80); */
|
/* background: linear-gradient(to right, transparent, #0ba6ff80); */
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-list__table >>> .el-table__inner-wrapper::before {
|
.alert-list__table>>>.el-table__inner-wrapper::before {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useWsStore } from "../store";
|
import { useWsStore } from "../store";
|
||||||
|
import IconBack from "../assets/menu_icon/IconBack.vue";
|
||||||
const emit = defineEmits(["home"]);
|
const emit = defineEmits(["home"]);
|
||||||
|
|
||||||
// load 公告
|
// load 公告
|
||||||
@@ -39,36 +40,49 @@ const handleClose = () => {
|
|||||||
<div class="announcement-page">
|
<div class="announcement-page">
|
||||||
<h1 class="announcement-title">公告栏</h1>
|
<h1 class="announcement-title">公告栏</h1>
|
||||||
<main class="announcement-content">
|
<main class="announcement-content">
|
||||||
<ScrollText :vertical="true" :duration="10" :pause-on-hover="true">
|
<ScrollText :vertical="true" :duration="120" :pause-on-hover="false">
|
||||||
<div v-html="vertical_content"></div>
|
<div v-html="vertical_content"></div>
|
||||||
</ScrollText>
|
</ScrollText>
|
||||||
</main>
|
</main>
|
||||||
<div class="announcement-footer">
|
<div class="announcement-footer">
|
||||||
<button
|
<button id="return-btn" style="
|
||||||
style="position: absolute; left: 0; bottom: 10px"
|
position: absolute;
|
||||||
@click="handleClose"
|
right: 32px;
|
||||||
>
|
top: 56px;
|
||||||
返回
|
appearance: none;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
" @click="handleClose">
|
||||||
|
<IconBack color="#f00" />
|
||||||
</button>
|
</button>
|
||||||
<ScrollText> {{ horizontal_content }} </ScrollText>
|
<ScrollText :duration="50"> {{ horizontal_content }} </ScrollText>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#return-btn:hover #back-btn__inner #back-btn {
|
||||||
|
fill: #F008 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.announcement-page {
|
.announcement-page {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #000;
|
background: url(../assets/line.png) 0 0 / 100% 100% no-repeat, #000;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
color: #f00;
|
color: #f00;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.announcement-title {
|
.announcement-title {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 72px;
|
font-size: 72px;
|
||||||
|
line-height: 144px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
letter-spacing: 2px;
|
letter-spacing: 2px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -82,16 +96,25 @@ const handleClose = () => {
|
|||||||
font-family: serif;
|
font-family: serif;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:fullscreen .announcement-content {
|
||||||
|
margin-bottom: 5%;
|
||||||
|
padding: 56px 80px 12px 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.announcement-footer {
|
.announcement-footer {
|
||||||
height: 128px;
|
height: 144px;
|
||||||
/* background: #ccc1; */
|
/* background: #ccc1; */
|
||||||
font-size: 64px;
|
font-size: 64px;
|
||||||
padding: 0 80px;
|
padding: 0 80px;
|
||||||
line-height: 128px;
|
line-height: 128px;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
position: relative;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:fullscreen .announcement-footer {
|
||||||
|
line-height: 80px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,17 +1,28 @@
|
|||||||
<!-- 实时数据页面 -->
|
<!-- 实时数据页面 -->
|
||||||
<script setup>
|
<script setup>
|
||||||
import HourChart from "../components/HourChart.vue";
|
import HourChart from "../components/datapage/HourChart.vue";
|
||||||
import TeamChartDay from "../components/TeamChartDay.vue";
|
// import TeamChartDay from "../components/datapage/TeamChartDay.vue";
|
||||||
import TeamChartMonth from "../components/TeamChartMonth.vue";
|
// import TeamChartMonth from "../components/datapage/TeamChartMonth.vue";
|
||||||
|
import LatestWeekYield from '../components/datapage/LatestWeekYield.vue'
|
||||||
|
import LineToday from '../components/datapage/LineToday.vue';
|
||||||
|
import LineMonth from '../components/datapage/LineMonth.vue';
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="data-page">
|
<div class="data-page">
|
||||||
<div class="data-list">
|
<!-- 小时数据 -->
|
||||||
<HourChart />
|
<HourChart />
|
||||||
<TeamChartDay />
|
<!-- 近7日产量 -->
|
||||||
<TeamChartMonth />
|
<LatestWeekYield />
|
||||||
</div>
|
<!-- 本日生产线情况 -->
|
||||||
|
<LineToday />
|
||||||
|
<!-- 本月生产线情况 -->
|
||||||
|
<LineMonth />
|
||||||
|
<!-- 本日班组情况 -->
|
||||||
|
<!-- <TeamChartDay /> -->
|
||||||
|
<!-- 本月班组情况 -->
|
||||||
|
<!-- <TeamChartMonth /> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -19,18 +30,23 @@ import TeamChartMonth from "../components/TeamChartMonth.vue";
|
|||||||
.data-page {
|
.data-page {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
grid-template-rows: 1fr 1fr;
|
||||||
|
gap: 24px;
|
||||||
|
padding: 32px 56px;
|
||||||
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-list {
|
/*
|
||||||
height: 100%;
|
:fullscreen .data-list {
|
||||||
width: 480px;
|
width: 35%;
|
||||||
|
gap: 32px;
|
||||||
position: absolute;
|
padding: 32px 0;
|
||||||
top: 0;
|
|
||||||
right: 32px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:fullscreen .data-list>div {
|
||||||
|
flex: 1;
|
||||||
|
} */
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
60
src/pages/ThreeDimension.vue
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<!-- 实时数据页面 -->
|
||||||
|
<script setup>
|
||||||
|
import HourChart from "../components/HourChart.vue";
|
||||||
|
import TeamChartDay from "../components/TeamChartDay.vue";
|
||||||
|
import TeamChartMonth from "../components/TeamChartMonth.vue";
|
||||||
|
import LatestWeekYield from '../components/LatestWeekYield.vue'
|
||||||
|
import ThreeD from './3D.vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
line: {
|
||||||
|
type: Number,
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="data-page">
|
||||||
|
<div style="position: absolute; top: 0; left: -279px; width: calc(100% + 279px); height: 100%;">
|
||||||
|
<ThreeD :line="line ?? '1'" />
|
||||||
|
</div>
|
||||||
|
<div class="data-list">
|
||||||
|
<HourChart />
|
||||||
|
<LatestWeekYield />
|
||||||
|
<!-- <TeamChartDay />
|
||||||
|
<TeamChartMonth /> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.data-page {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-list {
|
||||||
|
/* height: 100%; */
|
||||||
|
width: 480px;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top: 24px;
|
||||||
|
right: 32px;
|
||||||
|
gap: 24px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
:fullscreen .data-list {
|
||||||
|
width: 35%;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 32px 0;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
:fullscreen .data-list>div {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
166
src/pages/eqMaps.js
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
export const initState = {
|
||||||
|
// 钢一线
|
||||||
|
M1上片: "",
|
||||||
|
M2上片: "",
|
||||||
|
M1磨边机: "",
|
||||||
|
M2磨边机: "",
|
||||||
|
M1清洗机: "",
|
||||||
|
M1清洗机: "",
|
||||||
|
S1丝印机: "",
|
||||||
|
S2丝印机: "",
|
||||||
|
S1前储片台: "",
|
||||||
|
S2前储片台: "",
|
||||||
|
S1清洗机: "",
|
||||||
|
S2清洗机: "",
|
||||||
|
Z1钻孔机: "",
|
||||||
|
Z2钻孔机: "",
|
||||||
|
B1前储片台: "",
|
||||||
|
B1后储片台: "",
|
||||||
|
B1下片: "",
|
||||||
|
B1清洗机: "",
|
||||||
|
//
|
||||||
|
M3清洗机: "",
|
||||||
|
M4清洗机: "",
|
||||||
|
M5清洗机: "",
|
||||||
|
M3磨边机: "",
|
||||||
|
M4磨边机: "",
|
||||||
|
M5磨边机: "",
|
||||||
|
M3上片: "",
|
||||||
|
M4上片: "",
|
||||||
|
M5上片: "",
|
||||||
|
Z3钻孔机: "",
|
||||||
|
Z4钻孔机: "",
|
||||||
|
Z5钻孔机: "",
|
||||||
|
S3清洗机: "",
|
||||||
|
S4清洗机: "",
|
||||||
|
S5清洗机: "",
|
||||||
|
S3前储片台: "",
|
||||||
|
S4前储片台: "",
|
||||||
|
S5前储片台: "",
|
||||||
|
S3丝印机: "",
|
||||||
|
S4丝印机: "",
|
||||||
|
S5丝印机: "",
|
||||||
|
S3固化机: "",
|
||||||
|
S4固化机: "",
|
||||||
|
S5固化机: "",
|
||||||
|
S3后储片台: "",
|
||||||
|
S4后储片台: "",
|
||||||
|
S5后储片台: "",
|
||||||
|
B2前储片台: "",
|
||||||
|
B2后储片台: "",
|
||||||
|
B2下片: "",
|
||||||
|
B2清洗机: "",
|
||||||
|
//
|
||||||
|
M6上片: "",
|
||||||
|
M7上片: "",
|
||||||
|
M6磨边机: "",
|
||||||
|
M7磨边机: "",
|
||||||
|
M6清洗机: "",
|
||||||
|
M7清洗机: "",
|
||||||
|
Z6钻孔机: "",
|
||||||
|
Z7钻孔机: "",
|
||||||
|
S6清洗机: "",
|
||||||
|
S7清洗机: "",
|
||||||
|
S6前储片台: "",
|
||||||
|
S7前储片台: "",
|
||||||
|
S6丝印机: "",
|
||||||
|
S7丝印机: "",
|
||||||
|
S6固化炉: "",
|
||||||
|
S7固化炉: "",
|
||||||
|
S6后储片台: "",
|
||||||
|
S7后储片台: "",
|
||||||
|
B3前储片台: "",
|
||||||
|
B3后储片台: "",
|
||||||
|
B3清洗机: "",
|
||||||
|
B3下片: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const statusMap = [
|
||||||
|
"error", // 关机
|
||||||
|
"work", // 工作
|
||||||
|
"warn", // 未工作
|
||||||
|
"error", // 错误
|
||||||
|
];
|
||||||
|
|
||||||
|
export const eqMap = {
|
||||||
|
// 钢一线
|
||||||
|
C1LR1: "M1上片",
|
||||||
|
C1LR2: "M2上片",
|
||||||
|
C1MM1: "M1磨边机",
|
||||||
|
C1MM2: "M2磨边机",
|
||||||
|
C1ECM1: "M1清洗机",
|
||||||
|
C1ECM2: "M2清洗机",
|
||||||
|
"s1--": "S1丝印机",
|
||||||
|
"s2--": "S2丝印机",
|
||||||
|
C1ST1: "S1前储片台",
|
||||||
|
C1ST2: "S2前储片台",
|
||||||
|
C1SCM1: "S1清洗机",
|
||||||
|
C1SCM2: "S2清洗机",
|
||||||
|
C1HP1: "Z1钻孔机",
|
||||||
|
C1HP2: "Z2钻孔机",
|
||||||
|
C3ST1: "B1前储片台",
|
||||||
|
C3ST2: "B1后储片台",
|
||||||
|
C3UL1: "B1下片",
|
||||||
|
C3UL1: "B1下片1",
|
||||||
|
C3UL2: "B1下片2",
|
||||||
|
C3UCM1: "B1清洗机",
|
||||||
|
//
|
||||||
|
B1ECM1: "M3清洗机",
|
||||||
|
B1ECM2: "M4清洗机",
|
||||||
|
B1ECM3: "M5清洗机",
|
||||||
|
B1MM1: "M3磨边机",
|
||||||
|
B1MM2: "M4磨边机",
|
||||||
|
B1MM3: "M5磨边机",
|
||||||
|
B1LR1: "M3上片",
|
||||||
|
B1LR2: "M4上片",
|
||||||
|
B1LR3: "M5上片",
|
||||||
|
B1HP1: "Z3钻孔机",
|
||||||
|
B1HP2: "Z4钻孔机",
|
||||||
|
B1HP3: "Z5钻孔机",
|
||||||
|
B1SCM1: "S3清洗机",
|
||||||
|
B1SCM2: "S4清洗机",
|
||||||
|
B1SCM3: "S5清洗机",
|
||||||
|
B1ST1: "S3前储片台",
|
||||||
|
B1ST2: "S4前储片台",
|
||||||
|
B1ST3: "S5前储片台",
|
||||||
|
B1SP1: "S3丝印机",
|
||||||
|
B1SP2: "S4丝印机",
|
||||||
|
B1SP3: "S5丝印机",
|
||||||
|
B2CO1: "S3固化炉",
|
||||||
|
B2CO2: "S4固化炉",
|
||||||
|
B2CO3: "S5固化炉",
|
||||||
|
B2ST1: "S3后储片台",
|
||||||
|
B2ST2: "S4后储片台",
|
||||||
|
B2ST3: "S5后储片台",
|
||||||
|
B3ST1: "B2前储片台",
|
||||||
|
B3ST2: "B2后储片台",
|
||||||
|
B3UL1: "B2下片",
|
||||||
|
B3UL1: "B2下片1",
|
||||||
|
B3UL2: "B2下片2",
|
||||||
|
B3UCM1: "B2清洗机",
|
||||||
|
//
|
||||||
|
A1LR1: "M6上片",
|
||||||
|
A1LR2: "M7上片",
|
||||||
|
A1MM1: "M6磨边机",
|
||||||
|
A1MM2: "M7磨边机",
|
||||||
|
A1ECM1: "M6清洗机",
|
||||||
|
A1ECM2: "M7清洗机",
|
||||||
|
A1HP1: "Z6钻孔机",
|
||||||
|
A1HP2: "Z7钻孔机",
|
||||||
|
A1SCM1: "S6清洗机",
|
||||||
|
A1SCM2: "S7清洗机",
|
||||||
|
A1ST1: "S6前储片台",
|
||||||
|
A1ST2: "S7前储片台",
|
||||||
|
A1SP1: "S6丝印机",
|
||||||
|
A1SP2: "S7丝印机",
|
||||||
|
A2CO1: "S6固化炉",
|
||||||
|
A2CO2: "S7固化炉",
|
||||||
|
A2ST1: "S6后储片台",
|
||||||
|
A2ST2: "S7后储片台",
|
||||||
|
A3ST1: "B3前储片台",
|
||||||
|
A3ST2: "B3后储片台",
|
||||||
|
A3UCM1: "B3清洗机",
|
||||||
|
A3UL1: "B3下片",
|
||||||
|
A3UL1: "B3下片1",
|
||||||
|
A3UL2: "B3下片2",
|
||||||
|
};
|
||||||
@@ -1,41 +1,34 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { ref } from 'vue';
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
|
||||||
export const useWsStore = defineStore("wsData", () => {
|
export const useWsStore = defineStore("wsData", () => {
|
||||||
const data1 = ref({ test: 'hello world'});
|
const data1 = ref({});
|
||||||
const data2 = ref({});
|
const data2 = ref({});
|
||||||
const data3 = ref({});
|
const data3 = ref({});
|
||||||
|
const mainDataChart = ref({});
|
||||||
|
const mainDataAlarm = ref({});
|
||||||
|
|
||||||
function updateData(category, data) {
|
function updateData(category, data) {
|
||||||
console.log('update', data)
|
|
||||||
switch (category) {
|
switch (category) {
|
||||||
case "1":
|
case "1":
|
||||||
data1.value = data;
|
data1.value = { ...data1.value, ...data };
|
||||||
break;
|
break;
|
||||||
case "2":
|
case "2":
|
||||||
data2.value = data;
|
data2.value = { ...data2.value, ...data };
|
||||||
break;
|
break;
|
||||||
case "3":
|
case "3":
|
||||||
data3.value = data;
|
data3.value = { ...data3.value, ...data };
|
||||||
|
break;
|
||||||
|
case "main-chart":
|
||||||
|
mainDataChart.value = { ...mainDataChart.value, ...data };
|
||||||
|
break;
|
||||||
|
case "main-alarm":
|
||||||
|
mainDataAlarm.value = { ...mainDataAlarm.value, ...data };
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { data1, data2, data3, updateData };
|
return { data1, data2, data3, mainDataChart, mainDataAlarm, updateData };
|
||||||
});
|
});
|
||||||
// export const useWsStore = defineStore('wsData', {
|
|
||||||
// state: () => ({
|
|
||||||
// data1: {
|
|
||||||
// test: 'hello world'
|
|
||||||
// },
|
|
||||||
// data2: null,
|
|
||||||
// data3: null,
|
|
||||||
// }),
|
|
||||||
// actions: {
|
|
||||||
// updateData(category, data) {
|
|
||||||
// this[category] = data
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
|
|||||||
91
src/store/settings.js
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import { defineStore } from "pinia";
|
||||||
|
import { ref, watch } from "vue";
|
||||||
|
|
||||||
|
export const useSettings = defineStore("settings", () => {
|
||||||
|
const initialSettings = localStorage.getItem("settings");
|
||||||
|
const settings = ref(
|
||||||
|
initialSettings
|
||||||
|
? JSON.parse(initialSettings)
|
||||||
|
: {
|
||||||
|
resolution: {
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
},
|
||||||
|
carousel: true,
|
||||||
|
carouselTime: 30, // s
|
||||||
|
carouselPages: ["3d", "data", "realtime", "alert", "announcement"],
|
||||||
|
fullscreen: false,
|
||||||
|
eqStatus: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const clearFullscreenFlag = (e) => {
|
||||||
|
if (!document.fullscreenElement) {
|
||||||
|
settings.value.fullscreen = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => settings.value.fullscreen,
|
||||||
|
(val) => {
|
||||||
|
// const mainContainer = document.getElementById("main-container");
|
||||||
|
const mainContainer = document.documentElement;
|
||||||
|
if (val) {
|
||||||
|
mainContainer.requestFullscreen().then(() => {
|
||||||
|
document.removeEventListener("fullscreenchange", clearFullscreenFlag);
|
||||||
|
document.addEventListener("fullscreenchange", clearFullscreenFlag);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (document.fullscreenElement) document.exitFullscreen();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => settings.value,
|
||||||
|
(val) => {
|
||||||
|
localStorage.setItem("settings", JSON.stringify(val));
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
deep: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
function rewriteSettings(payload) {
|
||||||
|
settings.value = payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSettings({ type, value }) {
|
||||||
|
switch (type) {
|
||||||
|
case "carousel":
|
||||||
|
settings.value.carousel = !settings.value.carousel;
|
||||||
|
break;
|
||||||
|
case "fullscreen":
|
||||||
|
settings.value.fullscreen = !settings.value.fullscreen;
|
||||||
|
break;
|
||||||
|
case "eq":
|
||||||
|
settings.value.eqStatus = !settings.value.eqStatus;
|
||||||
|
break;
|
||||||
|
case "resolution":
|
||||||
|
settings.value.resolution.height = value.height;
|
||||||
|
settings.value.resolution.width = value.width;
|
||||||
|
break;
|
||||||
|
case "carousel-page":
|
||||||
|
const exists = settings.value.carouselPages.includes(value);
|
||||||
|
if (exists)
|
||||||
|
settings.value.carouselPages = settings.value.carouselPages.filter(
|
||||||
|
(page) => page !== value
|
||||||
|
);
|
||||||
|
else {
|
||||||
|
settings.value.carouselPages.splice(
|
||||||
|
["3d", "data", "realtime", "alert", "announcement"].indexOf(value),
|
||||||
|
0,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { settings, updateSettings, rewriteSettings };
|
||||||
|
});
|
||||||
@@ -1,4 +1,9 @@
|
|||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
font-family: '黑体', Arial, Helvetica, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
206
src/utils/glass.js
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
import glassImgSrc from "../assets/glass.png";
|
||||||
|
import { connect0 } from "./useWebsocket";
|
||||||
|
import { ref, watchEffect, onMounted, h } from "vue";
|
||||||
|
|
||||||
|
const positionMapping = {
|
||||||
|
A1: {
|
||||||
|
M101: [640, 420, -26, 150], // top, left, angle, distance(px)
|
||||||
|
M201: [675, 420, -26, 150],
|
||||||
|
M105_1: [530, 680, -28, 128],
|
||||||
|
M205_1: [560, 680, -28, 138],
|
||||||
|
},
|
||||||
|
A2: {
|
||||||
|
M101_1: [440, 880, -28, 100],
|
||||||
|
M201_1: [470, 880, -28, 60],
|
||||||
|
// M201_1: {
|
||||||
|
// // 分段
|
||||||
|
// 0: [0, 0, 60, 400],
|
||||||
|
// 1: [0, 0, 60, 400],
|
||||||
|
// 2: [0, 0, 60, 400],
|
||||||
|
// },
|
||||||
|
},
|
||||||
|
A3: {
|
||||||
|
M101_1: [285, 1250, -32, 140],
|
||||||
|
},
|
||||||
|
B1: {
|
||||||
|
M101: [720, 410, -27, 190],
|
||||||
|
M201: [760, 410, -27, 215],
|
||||||
|
M301: [800, 410, -27, 240],
|
||||||
|
M105_1: [590, 710, -28, 140],
|
||||||
|
M205_1: [615, 730, -29, 145],
|
||||||
|
M305_1: [640, 750, -29, 150],
|
||||||
|
},
|
||||||
|
B2: {
|
||||||
|
M101: [490, 930, -30, 60],
|
||||||
|
M201: [515, 960, -30, 80],
|
||||||
|
M301: [530, 990, -30, 50],
|
||||||
|
},
|
||||||
|
B3: {
|
||||||
|
M101: [350, 1310, -32, 180],
|
||||||
|
},
|
||||||
|
C1: {
|
||||||
|
M101: [825, 510, -27, 190],
|
||||||
|
M201: [870, 510, -27, 210],
|
||||||
|
M104_1: [705, 760, -26, 150],
|
||||||
|
M204_1: [740, 775, -26, 165],
|
||||||
|
},
|
||||||
|
C2: {
|
||||||
|
// M101: { 0: [], 1: [] },
|
||||||
|
M101: [590, 980, -28, 30],
|
||||||
|
M201: [620, 1000, -29, 150],
|
||||||
|
},
|
||||||
|
C3: {
|
||||||
|
M101: [415, 1400, -34, 210],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function calcPosition(positionString = "") {
|
||||||
|
const lineId = positionString.slice(0, 2).toUpperCase(); // A1 B1 C1
|
||||||
|
const subLineId = positionString.slice(2).toUpperCase(); // M1 M206 M3
|
||||||
|
|
||||||
|
return {
|
||||||
|
top: positionMapping[lineId][subLineId][0],
|
||||||
|
left: positionMapping[lineId][subLineId][1],
|
||||||
|
angle: positionMapping[lineId][subLineId][2],
|
||||||
|
distance: positionMapping[lineId][subLineId][3],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Glass {
|
||||||
|
el = null;
|
||||||
|
distance = 100;
|
||||||
|
valid = true;
|
||||||
|
|
||||||
|
constructor(positionStr, size, bgColor) {
|
||||||
|
const { left, top, angle, distance } = calcPosition(positionStr);
|
||||||
|
// this.el = document.createElement("img");
|
||||||
|
// this.el.src = glassImgSrc;
|
||||||
|
this.el = document.createElement("div");
|
||||||
|
this.el.style.background = bgColor || "#f00";
|
||||||
|
this.el.style.position = "absolute";
|
||||||
|
this.el.style.top = top ? `${top}px` : "740px";
|
||||||
|
this.el.style.left = left ? `${left}px` : "380px";
|
||||||
|
this.distance = distance || 100;
|
||||||
|
// this.el.style.border = "3px solid red";
|
||||||
|
// this.el.style.display = "none";
|
||||||
|
this.el.style.borderRadius = "2px";
|
||||||
|
this.el.style.boxShadow = "0 0 10px 2px #000";
|
||||||
|
this.el.style.width = size ? `${size}px` : "16px";
|
||||||
|
this.el.style.height = size ? `${size}px` : "16px";
|
||||||
|
this.el.style.transformOrigin = "center";
|
||||||
|
this.el.style.transition = `all ${distance / 10}s linear`;
|
||||||
|
this.el.style.zIndex = "100";
|
||||||
|
this.el.style.pointerEvents = "none";
|
||||||
|
// this.el.style.transform = `rotate(${angle}deg) skew(32deg, 8deg)`;
|
||||||
|
this.el.style.transform = `rotate(${angle}deg) skew(${
|
||||||
|
-1 * angle
|
||||||
|
}deg, ${Math.floor((-1 * angle) / 4.5)}deg)`;
|
||||||
|
// debugger;
|
||||||
|
document.getElementById("glass-layer").appendChild(this.el);
|
||||||
|
this.el.addEventListener("transitionend", () => {
|
||||||
|
// document.body.removeChild(this.el);
|
||||||
|
this.el.style.opacity = 0;
|
||||||
|
this.valid = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get visible() {
|
||||||
|
return this.visibleOnScreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
move() {
|
||||||
|
const getTranslate = (d) => `${d}px ${-1 * Math.floor(Math.cos(24) * d)}px`;
|
||||||
|
this.el.style.translate = getTranslate(this.distance);
|
||||||
|
this.el.style.opacity = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 允许展示的工段 */
|
||||||
|
const allowedList = [
|
||||||
|
"c2m101",
|
||||||
|
"c2m201",
|
||||||
|
"c1m104_1",
|
||||||
|
"c1m204_1",
|
||||||
|
"c2m101",
|
||||||
|
"c2m201",
|
||||||
|
"a3m101_1",
|
||||||
|
"b3m101",
|
||||||
|
"c3m101",
|
||||||
|
"a2m101_1",
|
||||||
|
"a2m201_1",
|
||||||
|
"b2m101",
|
||||||
|
"b2m201",
|
||||||
|
"b2m301",
|
||||||
|
"a1m105_1",
|
||||||
|
"a1m205_1",
|
||||||
|
"b1m105_1",
|
||||||
|
"b1m205_1",
|
||||||
|
"b1m305_1",
|
||||||
|
"a1m101",
|
||||||
|
"a1m201",
|
||||||
|
"b1m101",
|
||||||
|
"b1m201",
|
||||||
|
"b1m301",
|
||||||
|
"c1m101",
|
||||||
|
"c1m201",
|
||||||
|
].map((item) => item.toUpperCase());
|
||||||
|
|
||||||
|
export function useGlass(store) {
|
||||||
|
onMounted(() => {
|
||||||
|
connect0(store);
|
||||||
|
});
|
||||||
|
|
||||||
|
const grassArr = ref({});
|
||||||
|
const doRender = (data) => {
|
||||||
|
return setTimeout(() => {
|
||||||
|
const commingData = data
|
||||||
|
.filter((item) => item.haveGlass)
|
||||||
|
.filter((item) => allowedList.includes(item.lightCode));
|
||||||
|
|
||||||
|
if (commingData.length != 0) {
|
||||||
|
/** 清空之前的状态 */
|
||||||
|
document.getElementById("glass-layer").innerHTML = "";
|
||||||
|
document.getElementById("glass-layer").innerHTML = "";
|
||||||
|
grassArr.value = {};
|
||||||
|
|
||||||
|
commingData.forEach((item) => {
|
||||||
|
const n = new Glass(
|
||||||
|
item.lightCode,
|
||||||
|
item.lightCode.includes("A3") ||
|
||||||
|
item.lightCode.includes("B3") ||
|
||||||
|
item.lightCode.includes("C3")
|
||||||
|
? 12
|
||||||
|
: undefined,
|
||||||
|
"#0F0D"
|
||||||
|
);
|
||||||
|
setTimeout(() => {
|
||||||
|
n.move();
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
grassArr.value[item.lightCode] = n;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
watchEffect((onInvalidate) => {
|
||||||
|
const timer = doRender(
|
||||||
|
store.mainDataAlarm.orbitalPositioningArrayList || []
|
||||||
|
);
|
||||||
|
onInvalidate(() => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return h("div", {
|
||||||
|
id: "glass-layer",
|
||||||
|
style: {
|
||||||
|
position: "absolute",
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
pointerEvents: "none",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
import Client from "./ws";
|
import Client from "./ws";
|
||||||
|
|
||||||
export default function useWebsocket(store, path) {
|
export default function useWebsocket(store, path, excludePaths = []) {
|
||||||
|
if (excludePaths.includes(path)) return;
|
||||||
// connect0(store);
|
// connect0(store);
|
||||||
connectPath(store, path);
|
connectPath(store, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = "ws://192.168.1.101:8082/QbMonitoring/websocket";
|
// const url = "ws://192.168.1.101:8082/QbMonitoring/websocket";
|
||||||
|
const url = "ws://192.168.0.254:8082/QbMonitoring/websocket";
|
||||||
function connectPath(store, path) {
|
function connectPath(store, path) {
|
||||||
new Client(
|
new Client(
|
||||||
{
|
{
|
||||||
@@ -15,19 +17,15 @@ function connectPath(store, path) {
|
|||||||
(message) => {
|
(message) => {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(message.data);
|
const data = JSON.parse(message.data);
|
||||||
console.log("message", JSON.parse(message.data));
|
|
||||||
|
|
||||||
if ("specificationChanges" in data) {
|
if ("specificationChanges" in data) {
|
||||||
console.log("[*] setting data1");
|
|
||||||
// 分屏推送1数据
|
// 分屏推送1数据
|
||||||
store.updateData("1", data);
|
store.updateData("1", data);
|
||||||
} else if ("deliveryNotification" in data) {
|
} else if ("deliveryNotification" in data) {
|
||||||
// 分屏推送3数据
|
// 分屏推送3数据
|
||||||
console.log("[*] setting data3");
|
|
||||||
store.updateData("3", data);
|
store.updateData("3", data);
|
||||||
} else {
|
} else {
|
||||||
// 分屏推送2数据
|
// 分屏推送2数据
|
||||||
console.log("[*] setting data2");
|
|
||||||
store.updateData("2", data);
|
store.updateData("2", data);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -37,7 +35,8 @@ function connectPath(store, path) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function connect0(store) {
|
export function connect0(store) {
|
||||||
|
console.log("[*] Connecting main screen........");
|
||||||
new Client(
|
new Client(
|
||||||
{
|
{
|
||||||
url: url + "/0",
|
url: url + "/0",
|
||||||
@@ -47,6 +46,14 @@ function connect0(store) {
|
|||||||
try {
|
try {
|
||||||
const data = JSON.parse(message.data);
|
const data = JSON.parse(message.data);
|
||||||
console.log("message --- 0 ---> ", JSON.parse(message.data));
|
console.log("message --- 0 ---> ", JSON.parse(message.data));
|
||||||
|
|
||||||
|
if ("lineSumProductYield" in data) {
|
||||||
|
// 主屏推送 图表数据
|
||||||
|
store.updateData("main-chart", data);
|
||||||
|
} else {
|
||||||
|
// 主屏推送 报警数据
|
||||||
|
store.updateData("main-alarm", data);
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("[x] 未解析的ws数据: ", err);
|
console.log("[x] 未解析的ws数据: ", err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ export default class XClient {
|
|||||||
heartbeat() {
|
heartbeat() {
|
||||||
if (this.hb) clearInterval(this.hb);
|
if (this.hb) clearInterval(this.hb);
|
||||||
return setInterval(() => {
|
return setInterval(() => {
|
||||||
console.log(`${this.name} ping...`);
|
|
||||||
if (this.ws.readyState == WebSocket.OPEN) {
|
if (this.ws.readyState == WebSocket.OPEN) {
|
||||||
this.ws.send("ping");
|
this.ws.send("ping");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -4,4 +4,8 @@ import vue from '@vitejs/plugin-vue'
|
|||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [vue()],
|
plugins: [vue()],
|
||||||
|
server: {
|
||||||
|
host: '0.0.0.0',
|
||||||
|
port: '5173'
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|||||||