You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

361 lines
11 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<script lang="ts" setup>
import * as echarts from "echarts";
import TotalChart from "@/components/Charts/totalChart.vue";
import PoleMonitorChart from "@/components/Charts/poleMonitorChart.vue";
import VehicleMonitorChart from "@/components/Charts/vehicleMonitorChart.vue";
import HomeSubTitle from "@/components/HeaderBar/homeSubTitle.vue";
import DeviceStatus from "./components/DeviceStatus.vue";
import car_device_icon from "@/assets/home/car_device_icon.png";
import pole_device_icon from "@/assets/home/pole_device_icon.png";
import excavator_device_icon from "@/assets/home/excavator_device_icon.png";
import {
getDataOverviewApi,
getDeviceInfowApi,
getRecordFaultApi,
getRealTimeApi,
} from "@/api/dashboard";
import { isSuccessApi } from "@/utils/forApi";
import { isArray } from "@/utils/is";
import AlarmModal from "./components/AlarmModal.vue";
import { dataViewConfig } from "@/config/dataView";
import { useWebSocketStore } from "@/stores/websocketStore";
import { onBeforeRouteLeave } from "vue-router";
defineOptions({
name: "DataOverviewWrap",
});
// TODO 需要转移到mock中
const xData = ref(["1月", "2月", "3月", "4月", "5月"]);
const legendArr = ["车体检测", "撑杆检测"];
const datas = ref([
[1528, 1266.02, 2468.39, 2982.67, 3165.91],
[2844.44, 6505.07, 8016.12, 6350.87, 1474.61],
]);
const colorArr = [
["#3B9FFE", "#5070F2"],
["#FFDA8D", "#FFAC06"],
];
const deviceStatus = ref({
onlineCount: 50,
errorCount: 10,
outlineCount: 10,
});
const searchForm = reactive({
car: "1",
pole: "1",
});
const deviceTotal = ref(0);
const carFaultTotal = ref([]);
const poleFaultTotal = ref([]);
const imageFault = ref([]);
const activeBtn = ref("month");
const isAlarmOpen = ref<Boolean>(false); //详情弹窗
const currentRow = ref<Record<string, any>>({}); // 当前选中行
const currFileList = ref<Record<string, any>[]>([]); // 详情的文件列表
const deviceInfo = reactive({
list: [
{
name: "车体检测设备",
bindVal: {
total: 0,
},
icon: car_device_icon,
},
{
name: "撑杆检测设备",
bindVal: {
total: 0,
},
icon: pole_device_icon,
},
{
name: "钩机检测设备",
bindVal: {
total: 0,
},
icon: excavator_device_icon,
},
],
});
const websocketStore = useWebSocketStore();
// 监听 messages 的变化
watch(
() => websocketStore.messages,
(newMessages: string[], oldMessages: string[]) => {
if (newMessages?.length > 0 && !isAlarmOpen.value) {
currentRow.value = newMessages[newMessages?.length - 1];
currFileList.value = newMessages[newMessages?.length - 1]?.images;
isAlarmOpen.value = true;
}
},
{ deep: true, immediate: true }
);
const getList = async (dateType: string = "month") => {
activeBtn.value = dateType;
const res = await getDataOverviewApi({ dateType });
if (isSuccessApi(res)) {
const { data } = res;
datas.value[0] = data.appearance;
datas.value[1] = data.pole;
if (dateType === "month") {
xData.value = data.dateArr.map((item: any) => {
if (dateType === "month") {
return item + "月";
}
});
} else {
xData.value = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
}
// console.log(data, 'getList_data')
}
};
const getDeviceInfo = async () => {
try {
const res = await getDeviceInfowApi();
if (isSuccessApi(res)) {
const { data } = res;
deviceTotal.value = data.deviceTotal;
deviceInfo.list = [
{
name: "车体检测设备",
bindVal: data?.appearance,
icon: car_device_icon,
},
{
name: "撑杆检测设备",
bindVal: data?.pole,
icon: pole_device_icon,
},
{
name: "钩机检测设备",
bindVal: data?.excavator,
icon: excavator_device_icon,
},
];
}
} catch (error) {
console.error("获取设备信息出错:", error);
}
};
const fetchPoleMonitorData = async () => {
try {
const res = await getRecordFaultApi({
dateType: "month",
value: searchForm.pole,
type: "pole",
});
if (isSuccessApi(res)) {
const { data } = res;
poleFaultTotal.value = data;
// deviceStatus.value = data
console.log(data);
}
} catch (error) {
console.error("获取设备信息出错:", error);
}
};
//
const fetchTrainMonitorData = async () => {
try {
const res = await getRecordFaultApi({
dateType: "month",
value: searchForm.car,
type: "appearance",
});
if (isSuccessApi(res)) {
const { data } = res;
carFaultTotal.value = data;
// deviceStatus.value = data
console.log(data);
}
} catch (error) {
console.error("获取设备信息出错:", error);
}
};
const getRealTime = async () => {
try {
const res = await getRealTimeApi({ deviceType: "" });
if (isSuccessApi(res)) {
const { data } = res;
if (isArray(data)) {
// TODO 暂时使用接口图重复填充
imageFault.value = data.concat(data).concat(data).splice(0, 4);
}
// deviceStatus.value = data
console.log(data);
}
} catch (error) {
console.error("获取设备信息出错:", error);
}
};
onBeforeRouteLeave(() => {
isAlarmOpen.value = false;
currentRow.value = {};
currFileList.value = [];
});
onMounted(() => {
getList();
getDeviceInfo();
fetchTrainMonitorData();
fetchPoleMonitorData();
getRealTime();
});
</script>
<template>
<div class="flex data-overview-wrap">
<!-- 检测总量汇总 -->
<div class="grid-container">
<div class="grid-item">
<div class="module-header">
<HomeSubTitle title="检测总量汇总">
<template #extra>
<div>
<el-button
type="primary"
class="month-btn"
@click="getList('month')"
:class="{ 'active-btn': activeBtn === 'month' }"
>
</el-button>
<el-button
class="week-btn"
@click="getList('week')"
:class="{ 'active-btn': activeBtn === 'week' }"
>
</el-button>
</div>
</template>
</HomeSubTitle>
</div>
<div class="chart-container">
<TotalChart
:xData="xData"
:legendArr="legendArr"
:datas="datas"
:colorArr="colorArr"
/>
</div>
</div>
<div class="grid-item">
<div class="module-header">
<HomeSubTitle title="车体监测">
<template #extra>
<div class="flex items-center text-[14px] px-[16px]">
<span>时间</span>
<el-select
v-model="searchForm.pole"
placeholder="时间"
class="custom-select mini-size"
@change="fetchPoleMonitorData()"
>
<el-option
v-for="v in dataViewConfig.monthArr"
:key="v?.value"
:label="v?.name"
:value="v?.value"
></el-option>
</el-select>
</div>
</template>
</HomeSubTitle>
</div>
<div class="chart-container chart-pie-bg">
<!-- <PieChart :data="carFaultTotal" :colors="[
'#FF7C09',
'#0032FF',
'#04FFF2',
'#D19EFF',
'#FF0103',
'#9EFFF3',
]" /> -->
<VehicleMonitorChart />
</div>
</div>
<div class="grid-item">
<div class="module-header">
<HomeSubTitle title="撑杆监测">
<template #extra>
<div class="flex items-center text-[14px] px-[16px]">
<span>时间:</span>
<el-select
v-model="searchForm.pole"
placeholder="时间"
class="custom-select mini-size"
@change="fetchPoleMonitorData()"
>
<el-option
v-for="v in dataViewConfig.monthArr"
:key="v?.value"
:label="v?.name"
:value="v?.value"
></el-option>
</el-select>
</div>
</template>
</HomeSubTitle>
</div>
<div class="chart-container chart-pie-bg">
<PoleMonitorChart />
<!-- <PieChartSmall :data="poleFaultTotal" :colors="['#9DFFF3', '#FFA179']" /> -->
</div>
</div>
</div>
<!-- 中部检测模块 -->
<div class="realTime-monitor-box">
<div class="w-full h-[35px] fg-title px-[16px] py-[20px]">
实时监测画面
</div>
<ul class="flex monitor-images">
<li class="monitor-images-item" v-for="(v, i) in imageFault" :key="i">
<img :src="v?.url" />
<div class="fault-info">{{ v?.fault_type }}</div>
</li>
</ul>
</div>
<!-- 设备信息 -->
<div class="device-info-box">
<div class="module-header">
<HomeSubTitle title="设备信息"> </HomeSubTitle>
</div>
<div class="device-info">
<div class="flex items-center justify-center total-device">
<div class="device-total-icon mt-[24px]"></div>
<div class="device-count ml-[24px]">
<div class="fg-mark1 text-[32px] font-bold">
{{ deviceTotal }}
</div>
<div class="text-[14px]">设备总数</div>
</div>
</div>
<ul class="device-list">
<li class="device-card" v-for="(v, k) in deviceInfo.list" :key="k">
<div
class="device-card-head text-[16px] flex items-center mb-[12px]"
>
<img :src="v.icon" alt="" class="w-[32px]" />
<span class="ml-[12px]">{{ v.name }}</span>
<span class="font-bold">{{ v.bindVal?.total || 0 }}</span>
</div>
<!-- //TODO 使用echarts重构 https://echarts.zhangmuchen.top/#/detail?cid=164bb-40c1-e483-b7c9b-6cb171ad -->
<DeviceStatus :deviceStatus="v.bindVal" />
</li>
</ul>
</div>
</div>
<AlarmModal
v-model:value="isAlarmOpen"
:info="currentRow"
:image="currFileList"
@close="isAlarmOpen = false"
/>
</div>
</template>
<style scoped lang="scss">
@import url("./DataOverview.scss");
</style>