update datapage

This commit is contained in:
DESKTOP-FUDKNA8\znjsz 2024-01-26 16:48:51 +08:00
parent 086be4da66
commit c314f4b78e
9 changed files with 650 additions and 34 deletions

View File

@ -8,7 +8,7 @@ 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"]);
@ -114,7 +114,8 @@ function resetScale(elm) {
@home="() => handlePageChange('3d')" />
<div v-else class="pages-wrapper">
<NavMenu @change="handlePageChange" :value="currentPage" />
<TriplePage v-if="currentPage === '3d'" :line="pathMap[path] ?? '1'" />
<!-- <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'" />

View File

@ -0,0 +1,116 @@
<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([
// { 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("[HourChart] =======>", state.data2.lineHourList?.length);
if (
state.data2.lineHourList == undefined ||
state.data2.lineHourList?.length == 0
) {
// console.log("[HourChart] ");
hourData.value.splice(0);
if (chart.value) chart.value.dispose();
return;
}
// console.log("[HourChart] ===> : ", state.data2.lineHourList);
hourData.value = (state.data2?.lineHourList ?? [
// { 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 },
]).map((item, index) => ({
id: `${item.lineName}_${index}`,
hour: item.hour || `${index}`.padStart(2, "0"),
data: item.num || Math.floor(Math.random() * 100),
}));
setupChart();
});
function setupChart() {
if (chart.value) chart.value.dispose();
nextTick(() => {
chart.value = echarts.init(chartChart.value);
// console.log("[HourChart] ===> chart: ", chart.value, hourData.value.map((item) => item.hour), hourData.value.map((item) => item.data));
chartSetup(
chart.value,
hourData.value.map((item) => item.hour),
hourData.value.map((item) => item.data)
);
});
// chart.value.setOption({
// xAxis: {
// type: "category",
// data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
// },
// yAxis: {
// type: "value",
// },
// series: [
// {
// data: [150, 230, 224, 218, 135, 147, 260],
// type: "line",
// },
// ],
// });
}
onMounted(() => {
chartChart.value.classList.add("h-full");
});
</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; */
}
.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>

View File

@ -0,0 +1,63 @@
export const options = {
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
},
series: [
{
data: [],
// data: Array.from({ length: 7 }, () => Math.random() * 100),
type: "bar",
// barWidth: 20,
showBackground: true,
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);
}

View File

@ -0,0 +1,74 @@
<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 dayData = ref([]);
store.$subscribe((mutation, state) => {
console.log("[ChartDay] ===> state: ", state.data2.classTodayProductYield);
if (
state.data2.classTodayProductYield == undefined ||
state.data2.classTodayProductYield?.length == 0
) {
console.log("[ChartDay] ===> 清除状态");
dayData.value.splice(0);
if (chart.value) chart.value.dispose();
return;
}
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);
}
}
console.log("[ChartDay] ===> dayData: ", dayData.value);
setupChart();
});
// onMounted(() => {
// nextTick(() => {
// setupChart();
// })
// })
function setupChart() {
if (chart.value) chart.value.dispose();
nextTick(() => {
chart.value = echarts.init(chartChart.value);
setupFn(chart.value, dayData.value);
});
}
onMounted(() => {
chartChart.value.classList.add("h-full");
});
</script>
<template>
<Container class="chart" title="本日班组情况" icon="cube">
<div ref="chartChart" class="chart-chart" style="{opacity: (dayData && dayData.length > 0) ? 1 : 0}"></div>
<p v-show="!dayData || dayData.length === 0" class="empty-data-hint">
暂无数据
</p>
</Container>
</template>
<style scoped>
.chart {
/* height: 300px; */
}
.chart-chart {
height: 100%;
}
</style>

View File

@ -0,0 +1,68 @@
export const options = {
color: ['#ffd601', '#72340b'],
grid: {
top: 10,
bottom: 0,
left: 0,
right: 28,
containLabel: true,
},
xAxis: {
max: 100,
splitLine: {
lineStyle: {
color: "#fff2",
},
},
axisLabel: {
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: 16,
color: "#e5e5e5a3",
},
splitLine: {
lineStyle: {
color: "#e5e5e5",
},
},
},
series: [
{
realtimeSort: true,
type: "bar",
// data: [10, 20, 30],
data: [],
label: {
show: true,
position: "right",
valueAnimation: true,
formatter: "{c}%",
color: "#fff",
fontSize: 16,
},
},
],
legend: {
show: false,
},
animationDuration: 0,
animationDurationUpdate: 3000,
animationEasing: "linear",
animationEasingUpdate: "linear",
};
export default function setup(echartInstance, dataArr) {
const new_options = { ...options };
new_options.series[0].data = dataArr;
echartInstance.setOption(new_options);
}

View File

@ -0,0 +1,73 @@
<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 monthData = ref(null);
store.$subscribe((mutation, state) => {
console.log("[ChartMonth] ===> state: ", state.data2.monthlyTarget);
if (
state.data2.monthlyTarget == undefined ||
state.data2.monthlyTarget?.length == 0
) {
console.log("[ChartMonth] ===> 清除状态");
monthData.value = null;
if (chart.value) chart.value.dispose();
return;
}
if (!state.data2.monthlyTarget[0]) return;
const { targetProduction, nowProduction, targetYield, nowYield } =
state.data2.monthlyTarget[0];
monthData.value = { targetProduction, nowProduction, targetYield, nowYield };
setupChart();
});
// 绿24FF5E
// FFB524
// FF3737
function setupChart() {
if (chart.value) chart.value.dispose();
nextTick(() => {
console.log("[ChartMonth] ===> 初始化表格: ", monthData.value);
chart.value = echarts.init(chartChart.value);
setupFn(chart.value, monthData.value);
});
}
onMounted(() => {
chartChart.value.classList.add("h-full");
// nextTick(() => {
// setupChart();
// })
});
</script>
<template>
<Container class="chart" title="本月班组情况" icon="cube">
<div ref="chartChart" class="chart-chart" style="{opacity: (monthData) ? 1 : 0}"></div>
<p v-show="!monthData" class="empty-data-hint">暂无数据</p>
</Container>
</template>
<style scoped>
.chart {
/* height: 300px; */
}
.chart-inner {}
.chart-chart {
height: 100%;
}
</style>

View File

@ -0,0 +1,176 @@
export const options = {
grid: {
top: 0,
left: 0,
right: 0,
bottom: 0
},
title: [
{
text: "当前产量:" + 100 + " 片",
left: "27%",
textAlign: "center",
top: "70%",
textStyle: {
fontSize: 16,
color: '#fffa'
},
},
{
text: "目标产量:" + 100 + " 片",
left: "27%",
textAlign: "center",
top: "85%",
textStyle: {
fontSize: 16,
color: '#fffa'
},
},
{
text: "当前成品率:" + 22 + "%",
left: "72%",
textAlign: "center",
top: "70%",
textStyle: {
fontSize: 16,
color: '#fffa'
},
},
{
text: "目标成品率:" + 22 + "%",
left: "72%",
textAlign: "center",
top: "85%",
textStyle: {
fontSize: 16,
color: '#fffa'
},
},
],
series: [
{
type: "gauge",
startAngle: 90,
center: ["27%", "35%"],
endAngle: -270,
radius: "55%",
progress: {
show: true,
width: 12,
},
axisLine: {
lineStyle: {
width: 12,
},
},
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: 12,
},
axisLine: {
lineStyle: {
width: 12,
},
},
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);
}

View File

@ -1,29 +1,20 @@
<!-- 实时数据页面 -->
<script setup>
import HourChart from "../components/HourChart.vue";
import TeamChartDay from "../components/TeamChartDay.vue";
import TeamChartMonth from "../components/TeamChartMonth.vue";
import ThreeD from './3D.vue'
import HourChart from "../components/datapage/HourChart.vue";
import TeamChartDay from "../components/datapage/TeamChartDay.vue";
import TeamChartMonth from "../components/datapage/TeamChartMonth.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 />
<TeamChartDay />
<TeamChartMonth />
</div>
<HourChart />
<TeamChartDay />
<TeamChartMonth />
<HourChart />
<TeamChartDay />
<TeamChartMonth />
</div>
</template>
@ -31,21 +22,16 @@ const props = defineProps({
.data-page {
flex: 1;
position: relative;
background: #cccc;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
gap: 24px;
padding: 32px;
align-items: stretch;
}
.data-list {
height: 100%;
width: 480px;
position: absolute;
top: 0;
right: 32px;
display: flex;
flex-direction: column;
justify-content: space-around;
}
/*
:fullscreen .data-list {
width: 35%;
gap: 32px;
@ -55,5 +41,5 @@ const props = defineProps({
:fullscreen .data-list>div {
flex: 1;
}
} */
</style>

View File

@ -0,0 +1,59 @@
<!-- 实时数据页面 -->
<script setup>
import HourChart from "../components/HourChart.vue";
import TeamChartDay from "../components/TeamChartDay.vue";
import TeamChartMonth from "../components/TeamChartMonth.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 />
<TeamChartDay />
<TeamChartMonth />
</div>
</div>
</template>
<style scoped>
.data-page {
flex: 1;
position: relative;
}
.data-list {
height: 100%;
width: 480px;
position: absolute;
top: 0;
right: 32px;
display: flex;
flex-direction: column;
justify-content: space-around;
}
:fullscreen .data-list {
width: 35%;
gap: 32px;
padding: 32px 0;
justify-content: space-around;
}
:fullscreen .data-list>div {
flex: 1;
}
</style>