Compare commits
82 Commits
3d765b4026
...
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 |
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
@@ -6,8 +6,12 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + Vue</title>
|
||||
</head>
|
||||
<body>
|
||||
<body style="position: relative">
|
||||
<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>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
14
package-lock.json
generated
@@ -11,6 +11,7 @@
|
||||
"echarts": "^5.4.3",
|
||||
"element-plus": "^2.4.4",
|
||||
"pinia": "^2.1.7",
|
||||
"screenfull": "^6.0.2",
|
||||
"vue": "^3.3.11",
|
||||
"vue3-marquee": "^4.1.0"
|
||||
},
|
||||
@@ -1123,6 +1124,14 @@
|
||||
"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": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||
@@ -1888,6 +1897,11 @@
|
||||
"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": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"echarts": "^5.4.3",
|
||||
"element-plus": "^2.4.4",
|
||||
"pinia": "^2.1.7",
|
||||
"screenfull": "^6.0.2",
|
||||
"vue": "^3.3.11",
|
||||
"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>
|
||||
46
src/App.vue
@@ -1,47 +1,55 @@
|
||||
<script setup>
|
||||
import { ref, onMounted } from "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 { useWsStore } from "./store";
|
||||
|
||||
const store = useWsStore();
|
||||
|
||||
const excludePaths = ["/alert-list", "/main-screen"];
|
||||
// use websocket
|
||||
let urlPath = ref(document.location.pathname);
|
||||
if (urlPath.value === "/") {
|
||||
urlPath.value = "/1-1";
|
||||
}
|
||||
useWebsocket(store, urlPath.value);
|
||||
useWebsocket(store, urlPath.value, excludePaths);
|
||||
|
||||
// size setting
|
||||
const size = ref(80);
|
||||
onMounted(() => {
|
||||
setSize(size.value);
|
||||
});
|
||||
// const size = ref(80);
|
||||
// onMounted(() => {
|
||||
// setSize(size.value);
|
||||
// });
|
||||
|
||||
// style update
|
||||
const styles = ref({});
|
||||
function setSize(value) {
|
||||
const v = (value / 100).toFixed(2);
|
||||
styles.value = {
|
||||
transform: `scale(${v})`,
|
||||
// transform: `scale(${v * 24 / 33}, ${v})`,
|
||||
transformOrigin: "top left",
|
||||
};
|
||||
}
|
||||
// const styles = ref({});
|
||||
// function setSize(value) {
|
||||
// const v = (value / 100).toFixed(2);
|
||||
// styles.value = {
|
||||
// transform: `scale(${v})`,
|
||||
// // transform: `scale(${v * 24 / 33}, ${v})`,
|
||||
// transformOrigin: "top left",
|
||||
// };
|
||||
// }
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div id="app-container">
|
||||
<MainPage :style="styles" :path="urlPath" />
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
#app-container {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
/* width: 100vw;
|
||||
height: 100vh; */
|
||||
background: #fff;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
}
|
||||
</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>
|
||||
152
src/MainPage.vue
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { ref, watch } from "vue";
|
||||
import { ref, onMounted } from "vue";
|
||||
import Tools from "./components/Tools.vue";
|
||||
import NavMenu from "./components/NavMenu.vue";
|
||||
import AnnoucementPage from "./pages/AnnouncementPage.vue";
|
||||
@@ -8,34 +8,126 @@ import AppHeader from "./components/Base/Header.vue";
|
||||
import AlertListPage from "./pages/AlertListPage.vue";
|
||||
import DataPage from "./pages/DataPage.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 pathMap = {
|
||||
'/1-1': 1,
|
||||
'/1-2': 2,
|
||||
'/1-3': 3,
|
||||
'/1-4': 4,
|
||||
'/2-1': 5,
|
||||
'/2-2': 6,
|
||||
'/2-3': 7,
|
||||
'/2-4': 8,
|
||||
'/3-1': 9,
|
||||
'/3-2': 10,
|
||||
'/3-3': 11,
|
||||
'/3-4': 12
|
||||
}
|
||||
|
||||
const pages = ["3d", "data", "realtime", "alert", "announcement"];
|
||||
const currentPage = ref("3d");
|
||||
const handlePageChange = (page) => {
|
||||
currentPage.value = page;
|
||||
};
|
||||
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>
|
||||
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<div id="main-container" ref="mainContainer" class="main-container">
|
||||
<DatetimeTool v-if="currentPage !== 'announcement'" />
|
||||
<Tools v-if="currentPage !== 'announcement'" />
|
||||
<Tools
|
||||
v-if="currentPage !== 'announcement'"
|
||||
@change-resolution="handleResolutionChange"
|
||||
/>
|
||||
<AppHeader v-if="currentPage !== 'announcement'" />
|
||||
<AnnoucementPage
|
||||
v-if="currentPage === 'announcement'"
|
||||
@@ -43,11 +135,21 @@ const handlePageChange = (page) => {
|
||||
@home="() => handlePageChange('3d')"
|
||||
/>
|
||||
<div v-else class="pages-wrapper">
|
||||
<NavMenu @change="handlePageChange" />
|
||||
<TriplePage v-if="currentPage === '3d'" :line="pathMap[path] ?? '1'" />
|
||||
<DataPage v-if="currentPage === 'data'" />
|
||||
<AlertListPage v-if="currentPage === 'alert'" />
|
||||
<RealtimePage v-if="currentPage === 'realtime'" />
|
||||
<NavMenu @change="handlePageChange" :value="currentPage" />
|
||||
<!-- <TriplePage v-if="currentPage === '3d'" :line="pathMap[path] ?? '1'" /> -->
|
||||
<ThreeDimension
|
||||
v-if="currentPage === '3d'"
|
||||
: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>
|
||||
</template>
|
||||
@@ -60,10 +162,6 @@ const handlePageChange = (page) => {
|
||||
position: relative;
|
||||
display: flex;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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 |
@@ -43,7 +43,7 @@ defineProps({
|
||||
<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"
|
||||
id="back-btn"
|
||||
fill="#50A1EC"
|
||||
:fill="color ?? '#50A1EC'"
|
||||
></path>
|
||||
</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"?>
|
||||
<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>
|
||||
<defs>
|
||||
<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"?>
|
||||
<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>
|
||||
<defs>
|
||||
<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"?>
|
||||
<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>
|
||||
<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">
|
||||
|
||||
|
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"?>
|
||||
<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>
|
||||
<defs>
|
||||
<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="container-header">
|
||||
<Icon :name="icon" />
|
||||
<span>{{ title }}</span>
|
||||
<span class="container-header__title">{{ title }}</span>
|
||||
</div>
|
||||
<div class="container-body">
|
||||
<slot />
|
||||
@@ -105,6 +105,10 @@ const props = defineProps({
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
.container-header__title {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.container-body {
|
||||
background: #ffffff11;
|
||||
backdrop-filter: blur(2px);
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<header class="header">
|
||||
<div>
|
||||
<Icon htmlRole="logo" icon="logo" />
|
||||
<div class="icon"></div>
|
||||
<h1 class="header__title">郴州旗滨光伏光电玻璃有限公司</h1>
|
||||
</div>
|
||||
</header>
|
||||
@@ -18,18 +17,29 @@ import { ref, computed } from 'vue';
|
||||
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 {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
/** width: 520px; **/
|
||||
width: 480px;
|
||||
width: 520px;
|
||||
top: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.header__title {
|
||||
font-weight: 400;
|
||||
font-size: 30px;
|
||||
letter-spacing: 2px;
|
||||
color: #fff;
|
||||
user-select: none;
|
||||
|
||||
@@ -41,9 +41,8 @@ const icon = computed(() => {
|
||||
|
||||
<style scoped>
|
||||
.icon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
background: #fff3;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
display: flex;
|
||||
justify-content: 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;
|
||||
right: 420px;
|
||||
font-size: 24px;
|
||||
color: #69B4FF;
|
||||
color: #69b4ff;
|
||||
line-height: 1;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -9,9 +9,14 @@ const store = useWsStore();
|
||||
const chartChart = ref(null);
|
||||
const chart = ref(null);
|
||||
// 小时数据
|
||||
const hourData = ref([]);
|
||||
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) => {
|
||||
console.log("=======>", state.data2.lineHourList?.length);
|
||||
if (
|
||||
state.data2.lineHourList == undefined ||
|
||||
state.data2.lineHourList?.length == 0
|
||||
@@ -20,11 +25,10 @@ store.$subscribe((mutation, state) => {
|
||||
if (chart.value) chart.value.dispose();
|
||||
return;
|
||||
}
|
||||
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.floor(Math.random() * 100),
|
||||
hour: item.hour || "__",
|
||||
data: item.num || 0,
|
||||
}));
|
||||
setupChart();
|
||||
});
|
||||
@@ -59,6 +63,7 @@ function setupChart() {
|
||||
|
||||
onMounted(() => {
|
||||
chartChart.value.classList.add("h-full");
|
||||
// setupChart();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -77,10 +82,7 @@ onMounted(() => {
|
||||
|
||||
<style scoped>
|
||||
.chart {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.chart-inner {
|
||||
height: 450px;
|
||||
}
|
||||
|
||||
.chart-chart {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
export const options = {
|
||||
color: ["#FFD160", "#99D66C", "#5B9BFF", "#2760FF", "#8167F6", "#FF00B2"],
|
||||
grid: {
|
||||
top: "10",
|
||||
bottom: "10",
|
||||
left: "10",
|
||||
right: "10",
|
||||
top: 10,
|
||||
bottom: 0,
|
||||
left: 12,
|
||||
right: 10,
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
@@ -37,15 +38,30 @@ export const options = {
|
||||
fontSize: 16,
|
||||
color: '#fff8'
|
||||
},
|
||||
minInterval: 1,
|
||||
max: 100,
|
||||
min: 1
|
||||
// minInterval: 1,
|
||||
// max: 100,
|
||||
// min: 1,
|
||||
max: function(value) {
|
||||
return value.max + Math.floor(value.max / 5)
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: Array.from({ length: 7 }, () => Math.random() * 100),
|
||||
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)",
|
||||
},
|
||||
|
||||
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 IconRealtime from "../assets/menu_icon/IconRealtime.vue";
|
||||
import IconAnnounce from "../assets/menu_icon/IconAnnouncement.vue";
|
||||
|
||||
const props = defineProps(['value'])
|
||||
const emit = defineEmits(["change"]);
|
||||
const handleClick = (page) => {
|
||||
emit("change", page);
|
||||
@@ -17,27 +17,32 @@ const handleClick = (page) => {
|
||||
<ul class="flex-list">
|
||||
<li>
|
||||
<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>
|
||||
</li>
|
||||
<li>
|
||||
<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>
|
||||
</li>
|
||||
<li>
|
||||
<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>
|
||||
</li>
|
||||
<li>
|
||||
<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>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button" @click="(e) => handleClick('announcement')">
|
||||
<span style="">公告页面</span><IconAnnounce class="nav-icon" />
|
||||
<span style="">公告页面</span>
|
||||
<IconAnnounce class="nav-icon" />
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -54,8 +59,13 @@ const handleClick = (page) => {
|
||||
position: relative;
|
||||
top: 72px;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* :fullscreen .nav-menu {
|
||||
top: 25%;
|
||||
} */
|
||||
|
||||
.flex-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -84,7 +94,7 @@ li {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.nav-menu button > span {
|
||||
.nav-menu button>span {
|
||||
font-size: 32px;
|
||||
letter-spacing: 3px;
|
||||
line-height: 45px;
|
||||
@@ -92,18 +102,19 @@ li {
|
||||
text-shadow: 0 5px 1px #001124;
|
||||
/* text-shadow: 0 5px 1px #004969; */
|
||||
}
|
||||
.nav-menu button:hover > span {
|
||||
color: #b1daff;
|
||||
|
||||
.nav-menu button:hover>span {
|
||||
color: #b1daff !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.nav-menu button:hover > .nav-icon #icon3d-g,
|
||||
.nav-menu button:hover > .nav-icon #alert-rect,
|
||||
.nav-menu button:hover > .nav-icon #alert-dot,
|
||||
.nav-menu button:hover > .nav-icon #realtime-main,
|
||||
.nav-menu button:hover > .nav-icon #announce-main,
|
||||
.nav-menu button:hover > .nav-icon #chart-main {
|
||||
.nav-menu button:hover>.nav-icon #icon3d-g,
|
||||
.nav-menu button:hover>.nav-icon #alert-rect,
|
||||
.nav-menu button:hover>.nav-icon #alert-dot,
|
||||
.nav-menu button:hover>.nav-icon #realtime-main,
|
||||
.nav-menu button:hover>.nav-icon #announce-main,
|
||||
.nav-menu button:hover>.nav-icon #chart-main {
|
||||
fill: #b1daff !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -41,7 +41,7 @@ const options = {
|
||||
axisLabel: { show: false },
|
||||
axisTick: { show: false },
|
||||
splitLine: { show: false },
|
||||
data: ["废片", "阶段成品"],
|
||||
data: ["阶段成品", "废片"],
|
||||
axisLabel: {
|
||||
fontSize: 24,
|
||||
color: "#fff",
|
||||
|
||||
@@ -3,8 +3,26 @@
|
||||
import { ref } from "vue";
|
||||
import { useWsStore } from "../store";
|
||||
|
||||
const listData = ref([]);
|
||||
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) => {
|
||||
listData.value = (state.data2.lineDetailData || Array(3).fill({})).map(
|
||||
(item, index) => ({
|
||||
@@ -30,13 +48,8 @@ store.$subscribe((mutation, state) => {
|
||||
|
||||
<template>
|
||||
<div class="realtime-table">
|
||||
<el-table
|
||||
class="dark-table"
|
||||
:data="listData"
|
||||
:show-overflow-tooltip="true"
|
||||
row-class-name="dark-row"
|
||||
header-row-class-name="dark-header"
|
||||
>
|
||||
<el-table class="dark-table" :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="mbt" label="磨边上"></el-table-column>
|
||||
<el-table-column prop="mbb" label="磨边下"></el-table-column>
|
||||
@@ -58,7 +71,7 @@ store.$subscribe((mutation, state) => {
|
||||
|
||||
<style scoped>
|
||||
.realtime-table {
|
||||
background: #00f3;
|
||||
/* background: #00f3; */
|
||||
height: 160px;
|
||||
width: 80%;
|
||||
align-self: self-start;
|
||||
@@ -68,7 +81,7 @@ store.$subscribe((mutation, state) => {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.dark-table >>> .el-table__inner-wrapper::before {
|
||||
.dark-table>>>.el-table__inner-wrapper::before {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
</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,5 +1,5 @@
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { ref, onMounted, nextTick } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
import Container from "./Base/Container.vue";
|
||||
import { useWsStore } from "../store";
|
||||
@@ -8,43 +8,57 @@ import setupFn from "./TeamChartDayOptions";
|
||||
const store = useWsStore();
|
||||
const chartChart = ref(null);
|
||||
const chart = ref(null);
|
||||
const showChartDom = ref(false);
|
||||
|
||||
const dayData = ref([]);
|
||||
store.$subscribe((mutation, state) => {
|
||||
if (
|
||||
state.data2.classTodayProductYield == undefined ||
|
||||
state.data2.classTodayProductYield?.length == 0
|
||||
) {
|
||||
dayData.value.splice(0);
|
||||
if (chart.value) chart.value.dispose();
|
||||
return;
|
||||
}
|
||||
console.log(
|
||||
"classTodayProductYield ===> ",
|
||||
state.data2.classTodayProductYield
|
||||
);
|
||||
for (let i = 0; i < state.data2.classTodayProductYield.length; ++i) {
|
||||
if (state.data2.classTodayProductYield[i].teamName == "A组") {
|
||||
dayData.value[0] = parseInt(state.data2.classTodayProductYield[i].yield);
|
||||
} else if (state.data2.classTodayProductYield[i].teamName == "B组") {
|
||||
dayData.value[1] = parseInt(state.data2.classTodayProductYield[i].yield);
|
||||
} else if (state.data2.classTodayProductYield[i].teamName == "C组") {
|
||||
dayData.value[2] = parseInt(state.data2.classTodayProductYield[i].yield);
|
||||
/** 无状态,处理数据 */
|
||||
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);
|
||||
}
|
||||
}
|
||||
setupChart();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function setupChart() {
|
||||
function setupChart(chart, dom, data) {
|
||||
if (chart.value) chart.value.dispose();
|
||||
nextTick(() => {
|
||||
chart.value = echarts.init(chartChart.value);
|
||||
setupFn(chart.value, dayData.value);
|
||||
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>
|
||||
|
||||
@@ -53,11 +67,9 @@ onMounted(() => {
|
||||
<div
|
||||
ref="chartChart"
|
||||
class="chart-chart"
|
||||
style="{opacity: (dayData && dayData.length > 0) ? 1 : 0}"
|
||||
:style="{ opacity: showChartDom ? 1 : 0 }"
|
||||
></div>
|
||||
<p v-show="!dayData || dayData.length === 0" class="empty-data-hint">
|
||||
暂无数据
|
||||
</p>
|
||||
<p v-show="!chart" class="empty-data-hint">暂无数据</p>
|
||||
</Container>
|
||||
</template>
|
||||
|
||||
@@ -66,9 +78,6 @@ onMounted(() => {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.chart-inner {
|
||||
}
|
||||
|
||||
.chart-chart {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -1,58 +1,55 @@
|
||||
export const options = {
|
||||
color: ['#a4c9d1', '#72340b', '#ffd601' ],
|
||||
grid: {
|
||||
top: "10",
|
||||
bottom: "10",
|
||||
left: "10",
|
||||
right: "10",
|
||||
containLabel: true,
|
||||
top: 8,
|
||||
bottom: 20,
|
||||
left: 42,
|
||||
right: 28,
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
},
|
||||
xAxis: {
|
||||
max: 100,
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: "#fff2",
|
||||
},
|
||||
},
|
||||
axisLabel: {
|
||||
fontSize: 22,
|
||||
color: "#e5e5e533",
|
||||
fontSize: 16,
|
||||
color: "#e5e5e5a3",
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: "category",
|
||||
data: ["A组", "B组", "C组"],
|
||||
inverse: true,
|
||||
animationDuration: 300,
|
||||
animationDurationUpdate: 300,
|
||||
max: 2, // only the largest 3 bars will be displayed
|
||||
axisLabel: {
|
||||
fontSize: 22,
|
||||
color: "#e5e5e533",
|
||||
fontSize: 16,
|
||||
color: "#e5e5e5a3",
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
color: "#e5e5e533",
|
||||
lineStyle: {
|
||||
color: "#e5e5e5",
|
||||
},
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
realtimeSort: true,
|
||||
name: "X",
|
||||
type: "bar",
|
||||
data: [10, 20, 30],
|
||||
data: [34, 2, 23],
|
||||
label: {
|
||||
show: true,
|
||||
position: "right",
|
||||
valueAnimation: true,
|
||||
formatter: "{c}%",
|
||||
color: "#fff8",
|
||||
fontWeight: "bold",
|
||||
fontSize: 22,
|
||||
color: "#fff",
|
||||
fontSize: 16,
|
||||
},
|
||||
},
|
||||
],
|
||||
legend: {
|
||||
show: false,
|
||||
},
|
||||
animationDuration: 0,
|
||||
animationDurationUpdate: 3000,
|
||||
animationEasing: "linear",
|
||||
animationEasingUpdate: "linear",
|
||||
|
||||
};
|
||||
|
||||
export default function setup(echartInstance, dataArr) {
|
||||
|
||||
@@ -1,52 +1,87 @@
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
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 show = ref(false);
|
||||
const chartContainer = ref(null);
|
||||
const chartInstance = ref(null);
|
||||
const store = useWsStore();
|
||||
const chartChart = ref(null);
|
||||
const chart = ref(null);
|
||||
|
||||
const monthData = ref(null);
|
||||
store.$subscribe((mutation, state) => {
|
||||
if (
|
||||
state.data2.monthlyTarget == undefined ||
|
||||
state.data2.monthlyTarget?.length == 0
|
||||
) {
|
||||
monthData.value = null;
|
||||
if (chart.value) chart.value.dispose();
|
||||
return;
|
||||
}
|
||||
console.log("monthlyTarget ===> ", state.data2.monthlyTarget);
|
||||
const { targetProduction, nowProduction, targetYield, nowYield } =
|
||||
state.data2.monthlyTarget[0];
|
||||
monthData.value = { targetProduction, nowProduction, targetYield, nowYield };
|
||||
setupChart();
|
||||
});
|
||||
|
||||
function setupChart() {
|
||||
if (chart.value) chart.value.dispose();
|
||||
nextTick(() => {
|
||||
chart.value = echarts.init(chartChart.value);
|
||||
setupFn(chart.value, monthData.value);
|
||||
});
|
||||
}
|
||||
|
||||
// 绿色:24FF5E
|
||||
// 黄色:FFB524
|
||||
// 红色:FF3737
|
||||
onMounted(() => {
|
||||
chartChart.value.classList.add("h-full");
|
||||
chartContainer.value.classList.add("h-full");
|
||||
const d = loadData(store.data2.monthlyTarget);
|
||||
// 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>
|
||||
|
||||
<template>
|
||||
<Container class="chart" title="本月班组情况" icon="cube">
|
||||
<div
|
||||
ref="chartChart"
|
||||
ref="chartContainer"
|
||||
class="chart-chart"
|
||||
style="{opacity: (monthData) ? 1 : 0}"
|
||||
:style="{ opacity: show ? 1 : 0 }"
|
||||
></div>
|
||||
<p v-show="!monthData" class="empty-data-hint">暂无数据</p>
|
||||
<p v-show="!show" class="empty-data-hint">暂无数据</p>
|
||||
</Container>
|
||||
</template>
|
||||
|
||||
@@ -55,9 +90,6 @@ onMounted(() => {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.chart-inner {
|
||||
}
|
||||
|
||||
.chart-chart {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -1,43 +1,50 @@
|
||||
export const options = {
|
||||
color: ["#99D66C", "#5B9BFF", "#8167F6", "#FF00B2"],
|
||||
grid: {
|
||||
top: "10%",
|
||||
bottom: "10%",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
},
|
||||
title: [
|
||||
{
|
||||
text: "当前产量:" + 100 + " 片",
|
||||
text: "当前产量:" + 118 + " 片",
|
||||
left: "27%",
|
||||
textAlign: "center",
|
||||
top: "67%",
|
||||
top: "70%",
|
||||
textStyle: {
|
||||
fontSize: 12,
|
||||
fontSize: 16,
|
||||
color: "#fffa",
|
||||
},
|
||||
},
|
||||
{
|
||||
text: "目标产量:" + 100 + " 片",
|
||||
text: "目标产量:" + 213 + " 片",
|
||||
left: "27%",
|
||||
textAlign: "center",
|
||||
top: "82%",
|
||||
top: "85%",
|
||||
textStyle: {
|
||||
fontSize: 12,
|
||||
fontSize: 16,
|
||||
color: "#fffa",
|
||||
},
|
||||
},
|
||||
{
|
||||
text: "当前成品率:" + 22 + "%",
|
||||
left: "73%",
|
||||
text: "当前成品率:" + 78 + "%",
|
||||
left: "72%",
|
||||
textAlign: "center",
|
||||
top: "67%",
|
||||
top: "70%",
|
||||
textStyle: {
|
||||
fontSize: 12,
|
||||
fontSize: 16,
|
||||
color: "#fffa",
|
||||
},
|
||||
},
|
||||
{
|
||||
text: "目标成品率:" + 22 + "%",
|
||||
left: "73%",
|
||||
text: "目标成品率:" + 90 + "%",
|
||||
left: "72%",
|
||||
textAlign: "center",
|
||||
top: "82%",
|
||||
top: "85%",
|
||||
textStyle: {
|
||||
fontSize: 12,
|
||||
fontSize: 16,
|
||||
color: "#fffa",
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -71,7 +78,7 @@ export const options = {
|
||||
},
|
||||
detail: {
|
||||
valueAnimation: true,
|
||||
fontSize: 12,
|
||||
fontSize: 16,
|
||||
offsetCenter: [0, "0%"],
|
||||
formatter: "{value}%",
|
||||
color: "rgba(255, 255, 255, 1)",
|
||||
@@ -79,7 +86,7 @@ export const options = {
|
||||
data: [
|
||||
{
|
||||
// value: (nowProduction / targetProduction * 100).toFixed(1),
|
||||
value: 100,
|
||||
value: 89.78,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -113,16 +120,16 @@ export const options = {
|
||||
detail: {
|
||||
show: true,
|
||||
valueAnimation: true,
|
||||
fontSize: 12,
|
||||
fontSize: 16,
|
||||
offsetCenter: [0, "0%"],
|
||||
formatter: 0 + "%",
|
||||
// formatter: 0 + "%",
|
||||
// formatter: (nowYield / targetYield * 100).toFixed(1) + '%',
|
||||
color: "#fff8",
|
||||
color: "#fff",
|
||||
},
|
||||
data: [
|
||||
{
|
||||
// value: targetYield,
|
||||
value: 100,
|
||||
value: 78,
|
||||
name: "Perfect",
|
||||
title: {
|
||||
show: false,
|
||||
@@ -134,8 +141,7 @@ export const options = {
|
||||
},
|
||||
},
|
||||
{
|
||||
value: 100,
|
||||
// value: nowYield,
|
||||
value: 90,
|
||||
name: "Good",
|
||||
title: {
|
||||
show: false,
|
||||
@@ -144,6 +150,7 @@ export const options = {
|
||||
show: false,
|
||||
valueAnimation: true,
|
||||
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[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[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
|
||||
// }
|
||||
|
||||
@@ -3,18 +3,68 @@ import { ref, watch, onMounted } from "vue";
|
||||
import IconBack from "../assets/menu_icon/IconBack.vue";
|
||||
import IconExchange from "../assets/menu_icon/IconExchange.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.href = '/1-1'
|
||||
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>
|
||||
|
||||
<template>
|
||||
<div class="tools">
|
||||
<button @click="toHome"><IconBack /></button>
|
||||
<button><IconSetting /></button>
|
||||
<button><IconExchange /></button>
|
||||
<div id="tools-bar" class="tools">
|
||||
<button @click="toHome">
|
||||
<IconBack />
|
||||
</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>
|
||||
<Teleport to="body">
|
||||
<SettingDialogVue
|
||||
v-if="visible"
|
||||
@close="visible = false"
|
||||
@change-resolution="handleChangeResolution"
|
||||
/>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@@ -24,7 +74,7 @@ function toHome() {
|
||||
right: 24px;
|
||||
display: flex;
|
||||
gap: 0px;
|
||||
z-index: 3;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
button {
|
||||
@@ -55,7 +105,6 @@ button svg #switch-btn {
|
||||
transition: fill 0.2s ease-out;
|
||||
}
|
||||
|
||||
|
||||
button:hover svg #back-btn,
|
||||
button:hover svg #setting-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 { createPinia } from 'pinia'
|
||||
import { createApp } from "vue";
|
||||
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';
|
||||
import ElementPlus from 'element-plus';
|
||||
import 'element-plus/dist/index.css';
|
||||
import Vue3Marquee from 'vue3-marquee';
|
||||
import App from './App.vue';
|
||||
const pinia = createPinia()
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 60 * 60 * 1000);
|
||||
|
||||
const app = createApp(App);
|
||||
app.use(pinia);
|
||||
app.use(ElementPlus);
|
||||
app.use(Vue3Marquee, { name: 'ScrollText' });
|
||||
app.mount('#app');
|
||||
app.use(Vue3Marquee, { name: "ScrollText" });
|
||||
app.mount("#app");
|
||||
|
||||
2294
src/pages/3D.vue
@@ -3,18 +3,23 @@
|
||||
import { ref } from "vue";
|
||||
import { useWsStore } from "../store";
|
||||
import Container from "../components/Base/Container.vue";
|
||||
const alarmList = ref([]);
|
||||
const store = useWsStore();
|
||||
import ThreeD from './3D.vue'
|
||||
|
||||
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,
|
||||
eqName: item.equipmentName,
|
||||
eqIndex: index + 1,
|
||||
alarmGrade: item.alarmLevel,
|
||||
alarmDetail: item.alarmDetails,
|
||||
position: `${item.productLine} - ${item.segment}`,
|
||||
}));
|
||||
|
||||
})));
|
||||
store.$subscribe((mutation, state) => {
|
||||
alarmList.value = state.data1.alarmArrList.map((item, index) => ({
|
||||
id: item.id,
|
||||
@@ -26,46 +31,28 @@ store.$subscribe((mutation, state) => {
|
||||
}));
|
||||
});
|
||||
|
||||
function handleIgnore(){
|
||||
alarmList.value.splice(0)
|
||||
}
|
||||
// function handleIgnore() {
|
||||
// alarmList.value.splice(0)
|
||||
// }
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<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">
|
||||
<div class="alert-list__table" style="">
|
||||
<el-table
|
||||
class="dark-table"
|
||||
:data="alarmList"
|
||||
:show-overflow-tooltip="true"
|
||||
row-class-name="dark-row"
|
||||
header-row-class-name="dark-header"
|
||||
>
|
||||
<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 class="dark-table" :data="alarmList" :show-overflow-tooltip="true" row-class-name="dark-row"
|
||||
header-row-class-name="dark-header">
|
||||
<el-table-column prop="eqName" label="设备名" width="80"></el-table-column>
|
||||
<el-table-column prop="eqIndex" label="序号" width="60"></el-table-column>
|
||||
<el-table-column prop="alarmGrade" label="报警等级" width="100"></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>
|
||||
</div>
|
||||
<button @click="handleIgnore" class="alert-btn">忽略</button>
|
||||
<!-- <button @click="handleIgnore" class="alert-btn">忽略</button> -->
|
||||
</Container>
|
||||
</div>
|
||||
</template>
|
||||
@@ -76,19 +63,31 @@ function handleIgnore(){
|
||||
/* height: 72%; */
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.dark-row {
|
||||
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;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.dark-row:hover > td.el-table__cell {
|
||||
background-color: #005effaa !important;
|
||||
.dark-row>td.el-table__cell:not(:last-child) {
|
||||
border-right: 1px solid #0003;
|
||||
}
|
||||
|
||||
.dark-row:hover>td.el-table__cell {
|
||||
/* background-color: #020D2D20 !important; */
|
||||
background-color: #fff1 !important;
|
||||
}
|
||||
|
||||
.dark-header {
|
||||
@@ -96,14 +95,19 @@ function handleIgnore(){
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dark-header > th.el-table__cell.is-leaf {
|
||||
.dark-header>th.el-table__cell.is-leaf {
|
||||
border-bottom: none;
|
||||
background-color: #005eff95 !important;
|
||||
background-color: #006ACD32 !important;
|
||||
font-weight: 400;
|
||||
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>
|
||||
|
||||
@@ -125,12 +129,18 @@ function handleIgnore(){
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
:fullscreen .alert-list {
|
||||
width: 35%;
|
||||
top: 32px;
|
||||
height: calc(100% - 64px);
|
||||
}
|
||||
|
||||
.alert-list__table {
|
||||
height: calc(100% - 72px);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,44 +40,49 @@ const handleClose = () => {
|
||||
<div class="announcement-page">
|
||||
<h1 class="announcement-title">公告栏</h1>
|
||||
<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>
|
||||
</ScrollText>
|
||||
</main>
|
||||
<div class="announcement-footer">
|
||||
<button
|
||||
style="
|
||||
<button id="return-btn" style="
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 10px;
|
||||
right: 32px;
|
||||
top: 56px;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
"
|
||||
@click="handleClose"
|
||||
>
|
||||
<IconBack />
|
||||
" @click="handleClose">
|
||||
<IconBack color="#f00" />
|
||||
</button>
|
||||
<ScrollText> {{ horizontal_content }} </ScrollText>
|
||||
<ScrollText :duration="50"> {{ horizontal_content }} </ScrollText>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
#return-btn:hover #back-btn__inner #back-btn {
|
||||
fill: #F008 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
.announcement-page {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: #000;
|
||||
background: url(../assets/line.png) 0 0 / 100% 100% no-repeat, #000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: #f00;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.announcement-title {
|
||||
color: #fff;
|
||||
font-size: 72px;
|
||||
line-height: 144px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 2px;
|
||||
text-align: center;
|
||||
@@ -91,16 +96,25 @@ const handleClose = () => {
|
||||
font-family: serif;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
:fullscreen .announcement-content {
|
||||
margin-bottom: 5%;
|
||||
padding: 56px 80px 12px 80px;
|
||||
}
|
||||
|
||||
.announcement-footer {
|
||||
height: 128px;
|
||||
height: 144px;
|
||||
/* background: #ccc1; */
|
||||
font-size: 64px;
|
||||
padding: 0 80px;
|
||||
line-height: 128px;
|
||||
font-family: sans-serif;
|
||||
position: relative;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
:fullscreen .announcement-footer {
|
||||
line-height: 80px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,17 +1,28 @@
|
||||
<!-- 实时数据页面 -->
|
||||
<script setup>
|
||||
import HourChart from "../components/HourChart.vue";
|
||||
import TeamChartDay from "../components/TeamChartDay.vue";
|
||||
import TeamChartMonth from "../components/TeamChartMonth.vue";
|
||||
import HourChart from "../components/datapage/HourChart.vue";
|
||||
// import TeamChartDay from "../components/datapage/TeamChartDay.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>
|
||||
|
||||
<template>
|
||||
<div class="data-page">
|
||||
<div class="data-list">
|
||||
<HourChart />
|
||||
<TeamChartDay />
|
||||
<TeamChartMonth />
|
||||
</div>
|
||||
<!-- 小时数据 -->
|
||||
<HourChart />
|
||||
<!-- 近7日产量 -->
|
||||
<LatestWeekYield />
|
||||
<!-- 本日生产线情况 -->
|
||||
<LineToday />
|
||||
<!-- 本月生产线情况 -->
|
||||
<LineMonth />
|
||||
<!-- 本日班组情况 -->
|
||||
<!-- <TeamChartDay /> -->
|
||||
<!-- 本月班组情况 -->
|
||||
<!-- <TeamChartMonth /> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -19,18 +30,23 @@ import TeamChartMonth from "../components/TeamChartMonth.vue";
|
||||
.data-page {
|
||||
flex: 1;
|
||||
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%;
|
||||
width: 480px;
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 32px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/*
|
||||
:fullscreen .data-list {
|
||||
width: 35%;
|
||||
gap: 32px;
|
||||
padding: 32px 0;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
:fullscreen .data-list>div {
|
||||
flex: 1;
|
||||
} */
|
||||
</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,40 +1,34 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { ref } from "vue";
|
||||
|
||||
export const useWsStore = defineStore("wsData", () => {
|
||||
const data1 = ref({ test: 'hello world'});
|
||||
const data1 = ref({});
|
||||
const data2 = ref({});
|
||||
const data3 = ref({});
|
||||
const mainDataChart = ref({});
|
||||
const mainDataAlarm = ref({});
|
||||
|
||||
function updateData(category, data) {
|
||||
switch (category) {
|
||||
case "1":
|
||||
data1.value = data;
|
||||
data1.value = { ...data1.value, ...data };
|
||||
break;
|
||||
case "2":
|
||||
data2.value = data;
|
||||
data2.value = { ...data2.value, ...data };
|
||||
break;
|
||||
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:
|
||||
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;
|
||||
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";
|
||||
|
||||
export default function useWebsocket(store, path) {
|
||||
export default function useWebsocket(store, path, excludePaths = []) {
|
||||
if (excludePaths.includes(path)) return;
|
||||
// connect0(store);
|
||||
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) {
|
||||
new Client(
|
||||
{
|
||||
@@ -33,7 +35,8 @@ function connectPath(store, path) {
|
||||
);
|
||||
}
|
||||
|
||||
function connect0(store) {
|
||||
export function connect0(store) {
|
||||
console.log("[*] Connecting main screen........");
|
||||
new Client(
|
||||
{
|
||||
url: url + "/0",
|
||||
@@ -43,6 +46,14 @@ function connect0(store) {
|
||||
try {
|
||||
const data = 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) {
|
||||
console.log("[x] 未解析的ws数据: ", err);
|
||||
}
|
||||
|
||||