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.

271 lines
9.0 KiB
Vue

<template>
<div class="bg_basic_content">
<div class="device-status-wrap">
<div class="device-status-header mt-[32px]">
<ContentHeader bgLayout="1855">
<template #title>
<div class="w-[200px] bg_title bg_title_6">
</div>
</template>
</ContentHeader>
</div>
<div class="px-[16px] 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-[16px]" @click="openCurrent(row)">
<el-button text>
<span :style="{
fontSize: '14px',
color: '#37DBFF'
}">
即时视频
</span>
</el-button>
</li>
<li class="flex items-center" @click="openHistory(row)">
<el-button text>
<span :style="{
fontSize: '14px',
color: '#37DBFF'
}">
历史视频
</span>
</el-button>
</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="ts">
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",
value: "1",
label: "在线",
isDelete: true,
icon: onLineIcon,
id: "1"
},
'offline': {
color: "#999999",
value: "2",
label: "离线",
isDelete: false,
icon: outLineIcon,
id: "2"
},
'error': {
color: "#E80D0D",
value: "3",
label: "故障",
isDelete: false,
icon: errorIcon,
id: "3"
},
'notFound': { // 未获取到设备状态
color: "#E80D0D",
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"
},
{
label: "设备状态",
property: "device_status",
formatter: val => {
console.log(val);
const currentLevelObj =
alarmLevelStatusEnum[val?.device_status] || alarmLevelStatusEnum.notFound;
return h(
"div",
{
style: {
fontSize: "14px",
display: "flex",
alignItems: "center",
lineHeight: "20px",
color: currentLevelObj?.color
}
},
[
h('img', {
src: currentLevelObj?.icon,
style: {
width: '20px',
height: '20px',
marginRight: "12px"
}
}),
h(
"span",
{
fontSize: "14px",
},
currentLevelObj?.label
)
]
);
}
},
{
type: "action",
label: "操作"
}
];
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>