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.

265 lines
7.3 KiB
Vue

<template>
<div class="bg-basic-content">
<div class="device-status-wrap">
<div class="device-status-header mt-[32px]">
<div class="mt-[24px] py-[16px] pl-[69px] flex items-center">
<div class="fg-title">设备状态</div>
</div>
</div>
<div class="px-[24px] device-status-content-box">
<div class="mt-[16px] bg-transparent baseTable_wrap full_table">
<BaseTable
class="bg-transparent baseTable_box"
:total="pagination.total"
:pageSize="pagination.pageSize"
:dataSource="listData"
:isFixedPagination="true"
:columns="columns"
:page="pagination.currentPage"
@change="handleTableChange"
>
<template v-slot:actionBar="{ row }">
<ul class="flex table_action_box">
<li
class="flex items-center mr-[12px]"
@click="openCurrent(row)"
>
<div class="fg-button-primary1">即时视频</div>
</li>
<li class="flex items-center" @click="openHistory(row)">
<div class="fg-button-primary">查看详情</div>
</li>
</ul>
</template>
</BaseTable>
</div>
</div>
<RealVideoModal
v-model:value="isRealOpen"
:info="currentRow"
@close="isRealOpen = false"
/>
<HistoryVideoModal
ref="historyModalRef"
v-model:value="isHistoryOpen"
:info="currentRow"
:historyVideos="historyVideos"
@close="isHistoryOpen = false"
/>
<AlarmModal
v-model:value="isAlarmOpen"
:info="currentDetailRow"
:image="currFileList"
@close="isAlarmOpen = false"
/>
</div>
</div>
</template>
<script setup lang="tsx">
import { BaseTable } from "@/components/CustomTable";
import ContentHeader from "@/components/ContentHeader.vue";
import HistoryVideoModal from "./components/HistoryVideoModal.vue";
import RealVideoModal from "./components/RealVideoModal.vue";
import onLineIcon from "@/assets/common/online_icon.png";
import outLineIcon from "@/assets/common/outline_icon.png";
import errorIcon from "@/assets/common/error_icon.png";
import { getDeviceStatusApi } from "@/api/dashboard";
import { isSuccessApi } from "@/utils/forApi";
import AlarmModal from "./components/AlarmModal.vue";
import { useWebSocketStore } from "@/stores/websocketStore";
import { onBeforeRouteLeave } from "vue-router";
defineOptions({
name: "DeviceStatusIndex",
});
const alarmLevelStatusEnum = {
online: {
color: "#52C41A",
className: "device-status-tag-online",
value: "1",
label: "在线",
isDelete: true,
icon: onLineIcon,
id: "1",
},
offline: {
color: "#999999",
className: "device-status-tag-outline",
value: "2",
label: "离线",
isDelete: false,
icon: outLineIcon,
id: "2",
},
error: {
color: "#E80D0D",
className: "device-status-tag-error",
value: "3",
label: "故障",
isDelete: false,
icon: errorIcon,
id: "3",
},
notFound: {
// 未获取到设备状态
color: "#E80D0D",
className: "device-status-tag-error",
value: "4444",
label: "未知",
isDelete: false,
icon: errorIcon,
id: "4444",
},
};
const currentRow = ref<Record<string, any>>({});
const isRealOpen = ref<Boolean>(false); // 实时视频弹窗
const isHistoryOpen = ref<Boolean>(false); // 历史视频弹窗
const historyVideos = ref<Record<string, any>[]>([]); //历史视频数据
const historyModalRef = ref(null);
const isAlarmOpen = ref<Boolean>(false); //详情弹窗
const currentDetailRow = ref<Record<string, any>>({}); // 当前选中行
const currFileList = ref<Record<string, any>[]>([]); // 详情的文件列表
const websocketStore = useWebSocketStore();
// 监听 messages 的变化
watch(
() => websocketStore.messages,
(newMessages: string[], oldMessages: string[]) => {
if (newMessages?.length > 0 && !isAlarmOpen.value) {
currentDetailRow.value = newMessages[newMessages?.length - 1];
currFileList.value = newMessages[newMessages?.length - 1]?.images;
isAlarmOpen.value = true;
}
},
{ deep: true, immediate: true }
);
const columns = [
{
label: "设备名称",
property: "device_name",
},
{
label: "设备ID",
property: "device_number",
},
{
label: "设备位置",
property: "device_position",
width: 550,
},
{
label: "设备状态",
property: "device_status",
formatter: (val) => {
console.log(val);
const currentLevelObj =
alarmLevelStatusEnum[val?.device_status] ||
alarmLevelStatusEnum.notFound;
return (
<div className={currentLevelObj.className}>
<span className="dot"></span>
<span>{currentLevelObj?.label}</span>
</div>
);
},
},
{
type: "action",
label: "操作",
width: 210,
},
];
const pagination = ref({ currentPage: 1, pageSize: 10, total: 0 });
const listData = ref([]);
const getList = async () => {
try {
const { currentPage, pageSize } = pagination.value;
const res = await getDeviceStatusApi({ current: currentPage, pageSize });
console.log(res.data, "getList_data");
if (isSuccessApi(res)) {
listData.value = res.data.data;
pagination.value = {
...pagination.value,
total: res.data.total,
};
}
} catch (error) {
console.error("获取数据失败:", error);
}
};
function handleTableChange(record) {
console.log("handleTableChange_record", record);
pagination.value = {
...pagination.value,
currentPage: record.page,
pageSize: record.pageSize,
};
getList();
}
/**打开实时视频 */
function openCurrent(row) {
console.log(row, "openCurrent");
currentRow.value = row;
isRealOpen.value = true;
}
/**打开历史视频 */
// getDeviceHistoryDetailApi
// const fetchHistoryList = async () => {
// try {
// const res = await getDeviceStatusApi({ device_id: currentRow.value?.id })
// if (isSuccessApi(res)) {
// historyVideos.value = res.data.data;
// isHistoryOpen.value = true;
// nextTick(() => {
// historyModalRef.value.loadData()
// })
// console.log(res, 'fetchHistoryList_data')
// }
// } catch (error) {
// console.error('获取数据失败:', error)
// }
// }
// TODO mock 获取视频列表数据
const fetchHistoryList = async () => {
try {
const resAll = await fetch("/api/v1/device/device_history/", {
method: "POST",
});
const res = await resAll.json();
if (isSuccessApi(res)) {
historyVideos.value = res.data;
isHistoryOpen.value = true;
nextTick(() => {
historyModalRef.value.loadData();
});
console.log(res, "fetchHistoryList_data");
}
} catch (error) {
console.error("获取数据失败:", error);
}
};
function openHistory(row) {
console.log(row, "openHistory");
currentRow.value = row;
fetchHistoryList();
}
onBeforeRouteLeave(() => {
isAlarmOpen.value = false;
currentDetailRow.value = {};
currFileList.value = [];
});
onMounted(() => {
getList();
});
</script>
<style lang="scss">
@import url("./DeviceStatus.scss");
</style>