feat: 拆分主模块
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 342 KiB |
Before Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 225 KiB |
Before Width: | Height: | Size: 194 KiB |
Before Width: | Height: | Size: 400 KiB |
Before Width: | Height: | Size: 352 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 142 KiB |
Before Width: | Height: | Size: 317 KiB |
Before Width: | Height: | Size: 713 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 248 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 855 B |
Before Width: | Height: | Size: 488 B |
Before Width: | Height: | Size: 112 KiB |
Before Width: | Height: | Size: 106 KiB |
Before Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 915 B |
Before Width: | Height: | Size: 711 B |
Before Width: | Height: | Size: 876 B |
Before Width: | Height: | Size: 922 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 955 B |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 420 B |
Before Width: | Height: | Size: 468 B |
@ -1,26 +0,0 @@
|
|||||||
<svg width="42" height="34" viewBox="0 0 42 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<g filter="url(#filter0_ii_9562_48037)">
|
|
||||||
<path d="M38.582 32.8229H3.93728L1.25977 30.6782V24.4139L2.7611 23.2867L2.78615 10.4887L1.25977 9.26178V3.0673L3.93728 0.932617H38.582L41.2595 3.0673V30.6782L38.582 32.8229Z" fill="#009DFF" fill-opacity="0.1"/>
|
|
||||||
</g>
|
|
||||||
<path opacity="0.6" d="M38.3222 33H3.67751L1 30.848V24.562L2.50134 23.431L2.52638 10.589L1 9.35782V3.14202L3.67751 1H38.3222L40.9997 3.14202V30.848L38.3222 33Z" stroke="#009DFF" stroke-width="0.58" stroke-miterlimit="10"/>
|
|
||||||
<path d="M21 15C22.933 15 24.5 13.433 24.5 11.5C24.5 9.56701 22.933 8 21 8C19.067 8 17.5 9.56701 17.5 11.5C17.5 13.433 19.067 15 21 15Z" fill="#009DFF" stroke="#009DFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M12 25.4V26H30V25.4C30 23.1598 30 22.0397 29.5641 21.184C29.1806 20.4314 28.5686 19.8195 27.816 19.436C26.9603 19 25.8402 19 23.6 19H18.4C16.1598 19 15.0397 19 14.1841 19.436C13.4314 19.8195 12.8195 20.4314 12.436 21.184C12 22.0397 12 23.1598 12 25.4Z" fill="#009DFF" stroke="#009DFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<defs>
|
|
||||||
<filter id="filter0_ii_9562_48037" x="1.25977" y="-1.06738" width="39.9995" height="35.8904" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
|
||||||
<feOffset dy="2"/>
|
|
||||||
<feGaussianBlur stdDeviation="2"/>
|
|
||||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
|
||||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0361115 0 0 0 0 0.4795 0 0 0 0 1 0 0 0 0.4 0"/>
|
|
||||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_9562_48037"/>
|
|
||||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
|
||||||
<feOffset dy="-2"/>
|
|
||||||
<feGaussianBlur stdDeviation="2"/>
|
|
||||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
|
||||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0352941 0 0 0 0 0.478431 0 0 0 0 1 0 0 0 0.4 0"/>
|
|
||||||
<feBlend mode="normal" in2="effect1_innerShadow_9562_48037" result="effect2_innerShadow_9562_48037"/>
|
|
||||||
</filter>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 563 B |
Before Width: | Height: | Size: 208 KiB |
Before Width: | Height: | Size: 112 KiB |
Before Width: | Height: | Size: 189 KiB |
Before Width: | Height: | Size: 214 KiB |
Before Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 800 KiB After Width: | Height: | Size: 800 KiB |
@ -1,171 +0,0 @@
|
|||||||
<!--
|
|
||||||
* @Author: donghao donghao@supervision.ltd
|
|
||||||
* @Date: 2025-03-06 15:42:11
|
|
||||||
* @LastEditors: donghao donghao@supervision.ltd
|
|
||||||
* @LastEditTime: 2025-03-13 10:49:12
|
|
||||||
* @FilePath: \vite-ai\data-dashboard\src\components\Navbar.vue
|
|
||||||
* @Description: 标题栏
|
|
||||||
-->
|
|
||||||
<script setup lang="ts">
|
|
||||||
// import { useNav } from "@/layout/hooks/useNav";
|
|
||||||
// import router, { resetRouter } from "@/router";
|
|
||||||
import { useUserStore } from '@/stores/user'
|
|
||||||
const userStore = useUserStore()
|
|
||||||
|
|
||||||
const logout = () => {
|
|
||||||
userStore.logout()
|
|
||||||
}
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: "DsNavbar"
|
|
||||||
});
|
|
||||||
|
|
||||||
// const { logout } = useNav();
|
|
||||||
//获取并刷新日期
|
|
||||||
const currTime = ref({
|
|
||||||
date: "",
|
|
||||||
time: "",
|
|
||||||
week: ""
|
|
||||||
});
|
|
||||||
|
|
||||||
function _formatNum(value) {
|
|
||||||
if (value <= 9) {
|
|
||||||
return "0" + value;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTime() {
|
|
||||||
const nowDate = new Date();
|
|
||||||
const date =
|
|
||||||
nowDate.getFullYear() +
|
|
||||||
"/" +
|
|
||||||
_formatNum(nowDate.getMonth() + 1) +
|
|
||||||
"/" +
|
|
||||||
_formatNum(nowDate.getDate());
|
|
||||||
const time =
|
|
||||||
_formatNum(nowDate.getHours()) +
|
|
||||||
":" +
|
|
||||||
_formatNum(nowDate.getMinutes())
|
|
||||||
// +
|
|
||||||
// ":" +
|
|
||||||
// _formatNum(nowDate.getSeconds());
|
|
||||||
let week = "";
|
|
||||||
switch (nowDate.getDay()) {
|
|
||||||
case 0:
|
|
||||||
week = "星期天";
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
week = "星期一";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
week = "星期二";
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
week = "星期三";
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
week = "星期四";
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
week = "星期五";
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
week = "星期六";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
date,
|
|
||||||
time,
|
|
||||||
week
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const getDataTime = () => {
|
|
||||||
currTime.value = getTime();
|
|
||||||
setTimeout(getDataTime, 1000);
|
|
||||||
};
|
|
||||||
onMounted(() => {
|
|
||||||
getDataTime();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="flex justify-between h-full align-middle Navbar_wrap">
|
|
||||||
<div class="flex items-center left">
|
|
||||||
<div class="bg_logo_left"></div>
|
|
||||||
</div>
|
|
||||||
<div class="flex">
|
|
||||||
<!-- <div class="center_title" /> -->
|
|
||||||
<h1 class="center_title"></h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex items-center justify-end right">
|
|
||||||
<div class="date_box ff1">
|
|
||||||
<span>{{ currTime.date }}</span><span>{{ currTime.week }}</span><span>{{ currTime.time }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="bg_user_icon" @click="logout" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.Navbar_wrap {
|
|
||||||
// bgNav
|
|
||||||
background: url("@/assets/common/bg_nav.png") no-repeat;
|
|
||||||
background-size: cover;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
width: 100%;
|
|
||||||
height: 64px;
|
|
||||||
line-height: 64px;
|
|
||||||
|
|
||||||
.left {
|
|
||||||
width: 30vw;
|
|
||||||
.bg_logo_left {
|
|
||||||
margin-left: 22px;
|
|
||||||
width: 88px;
|
|
||||||
height: 40px;
|
|
||||||
background-image: url("@/assets/common/logo_left.png");
|
|
||||||
background-size: 100% 100%;
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.center_title {
|
|
||||||
// margin-top: 19px;
|
|
||||||
background: url("@/assets/common/nav_title.png") no-repeat;
|
|
||||||
background-size: contain;
|
|
||||||
background-position: center;
|
|
||||||
width: 547px;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
width: 30vw;
|
|
||||||
|
|
||||||
.date_box {
|
|
||||||
color: #009dff;
|
|
||||||
font-size: 16px;
|
|
||||||
margin-right: 24px;
|
|
||||||
font-family: DingTalk JinBuTi;
|
|
||||||
|
|
||||||
&>span {
|
|
||||||
padding-left: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg_user_icon {
|
|
||||||
background: url("@/assets/common/userIcon.svg") no-repeat;
|
|
||||||
width: 40px;
|
|
||||||
height: 32px;
|
|
||||||
// border: 1px solid #009dff;
|
|
||||||
opacity: 0.6;
|
|
||||||
margin-right: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,121 +0,0 @@
|
|||||||
.appearance-monitor-warp {
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding-top: 32px;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: 20px;
|
|
||||||
// align-items: center;
|
|
||||||
.appearance-monitor-right {
|
|
||||||
box-sizing: border-box;
|
|
||||||
width:970px;
|
|
||||||
// display: flex;
|
|
||||||
background-image: url("@/assets/common/carbtmBg.png");
|
|
||||||
background-size: 100% 100%;
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
.appearance-monitor-search-box {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
margin: 16px 0;
|
|
||||||
}
|
|
||||||
.right-panel{
|
|
||||||
.el-scrollbar__view {
|
|
||||||
background: transparent !important;
|
|
||||||
height: 600px;
|
|
||||||
}
|
|
||||||
.fixed_pagination{
|
|
||||||
padding: 12px 20px 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.appearance-monitor-left {
|
|
||||||
width: 49%;
|
|
||||||
background-image: url("@/assets/common/boderBg.png");
|
|
||||||
background-size: 100% 100%;
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
.monitor-left-top {
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 32px 16px 20px;
|
|
||||||
min-height: 600px;
|
|
||||||
|
|
||||||
.file-preview-screen {
|
|
||||||
width: 100%;
|
|
||||||
height: 590px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 460px;
|
|
||||||
object-fit: cover
|
|
||||||
}
|
|
||||||
video {
|
|
||||||
width: 100%;
|
|
||||||
max-height: calc(100%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.monitor-left-bottom {
|
|
||||||
width: 100%;
|
|
||||||
padding: 0 16px;
|
|
||||||
margin-bottom: 29px;
|
|
||||||
overflow: visible;
|
|
||||||
.swiper {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
.swiper-slide {
|
|
||||||
width: 20%;
|
|
||||||
border-radius:4px;
|
|
||||||
height: 144px;
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
height: 144px;
|
|
||||||
border-radius:4px;
|
|
||||||
object-fit: cover
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.active-slide img,
|
|
||||||
.active-slide video {
|
|
||||||
border-radius:4px;
|
|
||||||
border: 2px solid #2ECCE0;
|
|
||||||
}
|
|
||||||
.swiper-button-prev,
|
|
||||||
.swiper-button-next {
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
color: white;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.swiper-button-prev::after,
|
|
||||||
.swiper-button-next::after {
|
|
||||||
font-size: 12px ;
|
|
||||||
color: #FFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 修改按钮悬停样式 */
|
|
||||||
.swiper-button-prev:hover,
|
|
||||||
.swiper-button-next:hover {
|
|
||||||
background-color: rgba(0, 0, 0, 0.8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.empty-bg {
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 892px;
|
|
||||||
height: 815px;
|
|
||||||
background-image: url("@/assets/common/emptyBg.png");
|
|
||||||
background-size: 156px 102px;
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
|
|
||||||
.device-status-wrap{
|
|
||||||
height: 813px;
|
|
||||||
background-image: url("@/assets/common/device_status_bg_line.png");
|
|
||||||
background-size: 100% 100%;
|
|
||||||
background-position: bottom;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
.device-status-content-box{
|
|
||||||
|
|
||||||
.el-scrollbar__view {
|
|
||||||
background: transparent !important;
|
|
||||||
height: 600px;
|
|
||||||
}
|
|
||||||
.el-table__inner-wrapper{
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
|
||||||
.el-table__body-wrapper, .el-scrollbar__wrap, .el-scrollbar{
|
|
||||||
background: transparent !important;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,270 +0,0 @@
|
|||||||
<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>
|
|
@ -1,117 +0,0 @@
|
|||||||
.pole-monitor-wrap {
|
|
||||||
background-image: url("@/assets/common/bg_banner_1.png");
|
|
||||||
background-size: cover;
|
|
||||||
background-position: bottom;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
height: 823px;
|
|
||||||
.search-section {
|
|
||||||
padding: 16px 0;
|
|
||||||
}
|
|
||||||
.pole-main-content {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pole-monitor-search-box {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
margin: 16px 0;
|
|
||||||
}
|
|
||||||
.right-panel {
|
|
||||||
.el-scrollbar__view {
|
|
||||||
background: transparent !important;
|
|
||||||
height: 600px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.pole-monitor-main {
|
|
||||||
.left-panel {
|
|
||||||
width: 870px;
|
|
||||||
margin-right: 16px;
|
|
||||||
&.empty-bg {
|
|
||||||
height: 680px;
|
|
||||||
background-image: url("@/assets/common/emptyBg.png");
|
|
||||||
background-size: 312px 204px;
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
.main-image {
|
|
||||||
box-sizing: border-box;
|
|
||||||
height: 511px;
|
|
||||||
position: relative;
|
|
||||||
background-color: #090f48;
|
|
||||||
border-radius: 4px;
|
|
||||||
.file-preview-screen {
|
|
||||||
height: calc(100%);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 460px;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
video {
|
|
||||||
width: 100%;
|
|
||||||
max-height: calc(100%);
|
|
||||||
}
|
|
||||||
.image-info {
|
|
||||||
position: absolute;
|
|
||||||
height: 52px;
|
|
||||||
line-height: 52px;
|
|
||||||
bottom: 0;
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 0 16px;
|
|
||||||
& > span {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.thumbnail-container {
|
|
||||||
width: 100%;
|
|
||||||
overflow: visible;
|
|
||||||
.swiper {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
.swiper-slide {
|
|
||||||
width: 20%;
|
|
||||||
border-radius: 4px;
|
|
||||||
height: 144px;
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
height: 144px;
|
|
||||||
border-radius: 4px;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.active-slide img,
|
|
||||||
.active-slide video {
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 2px solid #2ecce0;
|
|
||||||
}
|
|
||||||
.swiper-button-prev,
|
|
||||||
.swiper-button-next {
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
color: white;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.swiper-button-prev::after,
|
|
||||||
.swiper-button-next::after {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 修改按钮悬停样式 */
|
|
||||||
.swiper-button-prev:hover,
|
|
||||||
.swiper-button-next:hover {
|
|
||||||
background-color: rgba(0, 0, 0, 0.8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,390 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="pole-monitor-wrap mt-[32px]">
|
|
||||||
<div class="module-header">
|
|
||||||
<ContentHeader bgLayout="1855">
|
|
||||||
<template #title>
|
|
||||||
<div class="w-[200px] bg_title bg_title_3">
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #extra>
|
|
||||||
<div></div>
|
|
||||||
</template>
|
|
||||||
</ContentHeader>
|
|
||||||
</div>
|
|
||||||
<div class="pole-main-content px-[16px]">
|
|
||||||
<!-- 搜索区域 -->
|
|
||||||
<div class="pole-monitor-search-box">
|
|
||||||
<el-select v-model="searchForm.station" placeholder="站点" class="custom-select">
|
|
||||||
<el-option label="小觉站" value="小觉站"></el-option>
|
|
||||||
<el-option label="东西站" value="东西站"></el-option>
|
|
||||||
<el-option label="立杆区" value="立杆区"></el-option>
|
|
||||||
</el-select>
|
|
||||||
<el-input v-model="searchForm.train_number" placeholder="请输入列车号" class="custom-input" clearable />
|
|
||||||
<el-input v-model="searchForm.train_carriage_number" placeholder="请输入车厢号" class="custom-input"
|
|
||||||
clearable />
|
|
||||||
<el-select v-model="searchForm.fault_type" placeholder="故障类型" class="custom-select" clearable>
|
|
||||||
<el-option label="撑杆弯曲" value="撑杆弯曲"></el-option>
|
|
||||||
<el-option label="撑杆断折" value="撑杆断折"></el-option>
|
|
||||||
</el-select>
|
|
||||||
<el-button type="primary" @click="handleQuery" class="basic-btn query-btn">
|
|
||||||
<span class="icon"></span> 查询
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="handleReset" class="basic-btn reset-btn">
|
|
||||||
<span class="icon"></span> 重置
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
<!-- 主体内容区域 -->
|
|
||||||
<div class="flex justify-between pole-monitor-main">
|
|
||||||
<!-- 左侧视频与缩略图区域 -->
|
|
||||||
<div class="left-panel" v-if="currFileList?.length">
|
|
||||||
<!-- 主图显示 -->
|
|
||||||
<div class="main-image">
|
|
||||||
<!-- <img src="https://picsum.phfotos/300/200?random=1" alt="监控画面"> -->
|
|
||||||
<!-- <video ref="refVideo" controls muted :src="currFile?.video_url" width="100%" height="100%" style="object-fit: fill;"></video> -->
|
|
||||||
<div class="file-preview-screen">
|
|
||||||
<Player :src="currFile?.video_url" :is-playing="isPlaying" v-if="currFile?.video_url"
|
|
||||||
@play="isPlaying = true" @pause="isPlaying = false" />
|
|
||||||
<img :src="currFile?.image_url" v-else-if="currFile?.image_url">
|
|
||||||
<div v-else>
|
|
||||||
<!-- //TODO 视频【图片】加载失败 -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="image-info" v-if="currFile?.image_url">
|
|
||||||
<!-- //TODO 参数单位和待确认 -->
|
|
||||||
<span>长: {{ currFile?.length }}</span>
|
|
||||||
<span>宽: {{ currFile?.width }}</span>
|
|
||||||
<span>高: {{ currFile?.height }}</span>
|
|
||||||
<span>体积: {{ currFile?.volume }}</span>
|
|
||||||
<span>重量: {{ currFile?.weight }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- 缩略图区域 -->
|
|
||||||
<div class="thumbnail-container mt-[16px] w-[870px]">
|
|
||||||
<swiper ref="swiperRef" :modules="modules" :slides-per-view="3" :space-between="10" navigation
|
|
||||||
:scrollbar="{ draggable: false }" :centered-slides="false" :observer="true"
|
|
||||||
:observeParents="true" @swiper="onSwiper" @slideChange="onSlideChange">
|
|
||||||
<swiper-slide v-for="(file, index) in currFileList" :key="index"
|
|
||||||
@click="handleSlideClick(index)" :class="{ 'active-slide': activeIndex === index }">
|
|
||||||
<img :src="file?.image_url" v-if="file?.image_url" class="cursor-pointer" />
|
|
||||||
<SwiperPlayer class="cursor-pointer" :videoUrl="file?.video_url"
|
|
||||||
v-else-if="file?.video_url" :isPlaying="isPlaying && (activeIndex === index)" />
|
|
||||||
<div v-else>
|
|
||||||
<!-- //TODO 视频【图片】加载失败 -->
|
|
||||||
</div>
|
|
||||||
</swiper-slide>
|
|
||||||
</swiper>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="left-panel empty-bg" v-else></div>
|
|
||||||
<!-- 右侧表格区域 -->
|
|
||||||
<div class="flex-1 right-panel">
|
|
||||||
<div class="bg-transparent baseTable_wrap">
|
|
||||||
<BaseTable class="bg-transparent baseTable_box" :total="pagination.total"
|
|
||||||
:pageSize="pagination.pageSize" :dataSource="listData" :isFixedPagination="true"
|
|
||||||
:columns="columns" :page="pagination.currentPage" @change="handleTableChange"
|
|
||||||
:row-class-name="handleRowClassName" @row-click="handleRowClick">
|
|
||||||
</BaseTable>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<AlarmModal v-model:value="isAlarmOpen" :info="currentRow" :image="currFileList" @close="isAlarmOpen = false" />
|
|
||||||
<DeleteModal v-model:value="isDeleteOpen" @delete-success="getList()" :info="currentRow" @close="isDeleteOpen = false" />
|
|
||||||
<!-- <div class="bg_footer_desp">
|
|
||||||
</div> -->
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { onBeforeRouteLeave } from 'vue-router';
|
|
||||||
import Player from '@/components/videoPlayer/Player.vue'
|
|
||||||
import ContentHeader from '@/components/ContentHeader.vue';
|
|
||||||
import { BaseTable } from "@/components/CustomTable";
|
|
||||||
import SwiperPlayer from './components/SwiperPlayer.vue'
|
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
|
||||||
import { Navigation, Scrollbar } from "swiper/modules";
|
|
||||||
import { getAppearanceMonitorApi, getAppearanceMonitorDetailApi } from '@/api/dashboard';
|
|
||||||
import { isSuccessApi } from "@/utils/forApi";
|
|
||||||
import AlarmModal from './components/AlarmModal.vue'
|
|
||||||
import DeleteModal from './components/DeleteModal.vue'
|
|
||||||
import { useWebSocketStore } from '@/stores/websocketStore';
|
|
||||||
import "swiper/css";
|
|
||||||
import 'swiper/scss';
|
|
||||||
import 'swiper/scss/navigation';
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: "PoleMonitorIndex"
|
|
||||||
});
|
|
||||||
const modules = [Navigation, Scrollbar];
|
|
||||||
const activeIndex = ref(-1);
|
|
||||||
const swiperRef = ref(null);
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
label: "站点",
|
|
||||||
property: "station",
|
|
||||||
width: 80,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "车号",
|
|
||||||
property: "train_number",
|
|
||||||
width: 155,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "车型",
|
|
||||||
property: "train_model",
|
|
||||||
width: 70,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "车厢号",
|
|
||||||
property: "train_carriage_number",
|
|
||||||
width: 95,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "告警类型",
|
|
||||||
property: "alarm_type",
|
|
||||||
width: 90,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "故障类型",
|
|
||||||
property: "fault_type",
|
|
||||||
width: 100,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "等级",
|
|
||||||
property: "level",
|
|
||||||
width: 60,
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// label: "复核",
|
|
||||||
// property: "is_reviewed",
|
|
||||||
// formatter: ({ is_reviewed }) => {
|
|
||||||
// return is_reviewed === true
|
|
||||||
// ? "是"
|
|
||||||
// : "否";
|
|
||||||
// },
|
|
||||||
// width: 80,
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
label: "时间",
|
|
||||||
property: "created_at"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slot: "operation",
|
|
||||||
label: "操作",
|
|
||||||
width: 120,
|
|
||||||
formatter: (row) => {
|
|
||||||
return h(
|
|
||||||
"div",
|
|
||||||
{
|
|
||||||
style: {
|
|
||||||
fontSize: "14px",
|
|
||||||
color:"#37EBFF"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[
|
|
||||||
// h("i", {
|
|
||||||
// class: `iconfont icon-zishebeizu pr-[8px]`
|
|
||||||
// }),
|
|
||||||
h(
|
|
||||||
"span",
|
|
||||||
{
|
|
||||||
fontSize: "14px",
|
|
||||||
class: "pf-1",
|
|
||||||
},
|
|
||||||
[
|
|
||||||
h("i",
|
|
||||||
{
|
|
||||||
style: {
|
|
||||||
fontSize: "14px",
|
|
||||||
letterSpacing: "2px",
|
|
||||||
marginRight: "4px",
|
|
||||||
color:"#009DFF"
|
|
||||||
},
|
|
||||||
onClick: (row) => {
|
|
||||||
// console.log(row.id);
|
|
||||||
// 这里可以添加按钮点击后的具体逻辑
|
|
||||||
isAlarmOpen.value = true;
|
|
||||||
currentRow.value = row;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"详情"
|
|
||||||
),
|
|
||||||
h("i",
|
|
||||||
{
|
|
||||||
style: {
|
|
||||||
fontSize: "14px",
|
|
||||||
letterSpacing: "2px",
|
|
||||||
marginRight: "4px",
|
|
||||||
color:"#FF2727"
|
|
||||||
},
|
|
||||||
onClick: (row) => {
|
|
||||||
// console.log(row.id);
|
|
||||||
// 这里可以添加按钮点击后的具体逻辑
|
|
||||||
isDeleteOpen.value = true;
|
|
||||||
currentRow.value = row;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"删除"
|
|
||||||
),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const pagination = ref({ currentPage: 1, pageSize: 10, total: 0 });
|
|
||||||
const listData = ref<Record<string, any>[]>([]); // 列表数据
|
|
||||||
const currentRow = ref<Record<string, any>>({}); // 当前选中行
|
|
||||||
const currFileList = ref<Record<string, any>[]>([]); // 详情的文件列表
|
|
||||||
const currFile = ref<Record<string, any>>({}); // 详情数据
|
|
||||||
const isPlaying = ref<boolean>(false); // 是否播放
|
|
||||||
const searchForm = reactive({
|
|
||||||
train_number: "",
|
|
||||||
train_carriage_number: "",
|
|
||||||
fault_type: "",
|
|
||||||
station: "",
|
|
||||||
type: "pole"
|
|
||||||
});
|
|
||||||
const dataLoading = ref(true);
|
|
||||||
const isAlarmOpen = ref<Boolean>(false); //详情弹窗
|
|
||||||
const isDeleteOpen = ref<Boolean>(false); //删除弹窗
|
|
||||||
|
|
||||||
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 isCurrPlaying = computed(() => {
|
|
||||||
// return (index) => {
|
|
||||||
// return isPlaying.value && (activeIndex === index)
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
|
|
||||||
const togglePlay = () => {
|
|
||||||
isPlaying.value = !isPlaying.value;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSlideClick = (index) => {
|
|
||||||
if (activeIndex.value === index) {
|
|
||||||
togglePlay() // 播放 暂停
|
|
||||||
} else {
|
|
||||||
isPlaying.value = false;
|
|
||||||
activeIndex.value = index;
|
|
||||||
currFile.value = currFileList.value[index]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const onSwiper = (swiper) => {
|
|
||||||
swiperRef.value = swiper;
|
|
||||||
console.log('Swiper 实例已获取:', swiper);
|
|
||||||
};
|
|
||||||
const onSlideChange = () => {
|
|
||||||
console.log("slide change");
|
|
||||||
};
|
|
||||||
// 文件详情
|
|
||||||
const getFileList = async () => {
|
|
||||||
try {
|
|
||||||
const res = await getAppearanceMonitorDetailApi({ id: currentRow.value?.id, current: 1, pageSize: 1000 })
|
|
||||||
console.log(res.data, 'getDetailList_data')
|
|
||||||
if (isSuccessApi(res)) {
|
|
||||||
currFileList.value = res.data.data;
|
|
||||||
currFile.value = res.data.data[0];
|
|
||||||
activeIndex.value = 0;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error, 'getDetailList_error')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO mock 获取视频列表数据
|
|
||||||
// const getFileList = async () => {
|
|
||||||
// try {
|
|
||||||
// const resAll = await fetch('/api/v1/record/record_detail_list/', {
|
|
||||||
// method: 'POST'
|
|
||||||
// })
|
|
||||||
// const res = await resAll.json()
|
|
||||||
// if (isSuccessApi(res)) {
|
|
||||||
// currFileList.value = res.data.data;
|
|
||||||
// currFile.value = res.data.data[0];
|
|
||||||
// activeIndex.value = 0;
|
|
||||||
// }
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error('获取数据失败:', error)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
function loadDetail() {
|
|
||||||
currentRow.value = listData.value[0]
|
|
||||||
getFileList()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取列表
|
|
||||||
const getList = async () => {
|
|
||||||
try {
|
|
||||||
const { currentPage, pageSize } = pagination.value;
|
|
||||||
const res = await getAppearanceMonitorApi({ ...searchForm, current: currentPage, pageSize })
|
|
||||||
console.log(res.data, 'getList_data')
|
|
||||||
if (isSuccessApi(res)) {
|
|
||||||
listData.value = res.data.data;
|
|
||||||
if (listData.value?.length > 0) {
|
|
||||||
loadDetail()
|
|
||||||
pagination.value = {
|
|
||||||
...pagination.value,
|
|
||||||
total: res.data.total
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取数据失败:', error)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 查询方法
|
|
||||||
const handleQuery = () => {
|
|
||||||
getList()
|
|
||||||
};
|
|
||||||
|
|
||||||
// 重置方法
|
|
||||||
const handleReset = () => {
|
|
||||||
searchForm.train_number = '';
|
|
||||||
searchForm.station = '';
|
|
||||||
searchForm.train_carriage_number = '';
|
|
||||||
searchForm.fault_type = '';
|
|
||||||
getList()
|
|
||||||
};
|
|
||||||
// 分页表格切换参数
|
|
||||||
function handleTableChange(record) {
|
|
||||||
console.log("handleTableChange_record", record);
|
|
||||||
pagination.value = {
|
|
||||||
...pagination.value,
|
|
||||||
currentPage: record.page,
|
|
||||||
pageSize: record.pageSize
|
|
||||||
};
|
|
||||||
getList();
|
|
||||||
}
|
|
||||||
// 定义行类名方法
|
|
||||||
const handleRowClassName = ({ row }) => {
|
|
||||||
return row.id === currentRow.value.id ? 'selected-row' : '';
|
|
||||||
};
|
|
||||||
|
|
||||||
// 行点击事件处理
|
|
||||||
const handleRowClick = (row, event, rowIndex) => {
|
|
||||||
currentRow.value = row;
|
|
||||||
getFileList()
|
|
||||||
};
|
|
||||||
onBeforeRouteLeave(() => {
|
|
||||||
isAlarmOpen.value = false;
|
|
||||||
currentRow.value = {};
|
|
||||||
currFileList.value = [];
|
|
||||||
});
|
|
||||||
onMounted(() => {
|
|
||||||
getList();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<style lang="scss">
|
|
||||||
@import url('./PoleMonitor.scss');
|
|
||||||
</style>
|
|
@ -1,21 +0,0 @@
|
|||||||
|
|
||||||
.vehicl-management-wrap{
|
|
||||||
height: 813px;
|
|
||||||
background-image: url("@/assets/common/device_status_bg_line.png");
|
|
||||||
background-size: 100% 100%;
|
|
||||||
background-position: bottom;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
.vehicl-management-content-box{
|
|
||||||
|
|
||||||
.el-scrollbar__view {
|
|
||||||
background: transparent !important;
|
|
||||||
height: 600px;
|
|
||||||
}
|
|
||||||
.el-table__inner-wrapper{
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
|
||||||
.el-table__body-wrapper, .el-scrollbar__wrap, .el-scrollbar{
|
|
||||||
background: transparent !important;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,145 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="bg_basic_content">
|
|
||||||
<div class="vehicl-management-wrap">
|
|
||||||
<div class="vehicl-management-header mt-[32px]">
|
|
||||||
<ContentHeader bgLayout="1855">
|
|
||||||
<template #title>
|
|
||||||
<div class="w-[200px] bg_title bg_title_7">
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</ContentHeader>
|
|
||||||
</div>
|
|
||||||
<div class="px-[16px] vehicl-management-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>
|
|
||||||
</ul>
|
|
||||||
</template>
|
|
||||||
</BaseTable>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<VehiclModal v-model:value="isVehiclOpen" :info="currentRow" :image="currFileList" @close="isVehiclOpen = 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 { getVehiclManagementApi } from '@/api/dashboard';
|
|
||||||
import { isSuccessApi } from "@/utils/forApi";
|
|
||||||
import AlarmModal from './components/AlarmModal.vue'
|
|
||||||
import { useWebSocketStore } from '@/stores/websocketStore';
|
|
||||||
import { onBeforeRouteLeave } from 'vue-router';
|
|
||||||
import VehiclModal from "./components/VehiclModal.vue";
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: "VehiclManagementWrap"
|
|
||||||
});
|
|
||||||
const currentRow = ref<Record<string, any>>({});
|
|
||||||
const isAlarmOpen = ref<Boolean>(false); //详情弹窗
|
|
||||||
const isVehiclOpen = 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: "车辆ID",
|
|
||||||
property: "train_id"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "车厢数量",
|
|
||||||
property: "carriage_account"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "入场时间",
|
|
||||||
property: "arrive_at"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "出场时间",
|
|
||||||
property: "leave_at"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "停留时间",
|
|
||||||
property: "stay_duration"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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 getVehiclManagementApi({ 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;
|
|
||||||
isVehiclOpen.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeRouteLeave(() => {
|
|
||||||
isAlarmOpen.value = false;
|
|
||||||
currentDetailRow.value = {};
|
|
||||||
currFileList.value = [];
|
|
||||||
});
|
|
||||||
onMounted(() => {
|
|
||||||
getList();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
@import url('./VehiclManagement.scss');
|
|
||||||
</style>
|
|
@ -1,320 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { onMounted, onUnmounted, ref, watch, nextTick } from "vue";
|
|
||||||
import * as echarts from "echarts";
|
|
||||||
|
|
||||||
// 定义组件接收的props
|
|
||||||
const props = defineProps({
|
|
||||||
xData: {
|
|
||||||
type: Array as PropType<Array<string>>,
|
|
||||||
default: () => [],
|
|
||||||
},
|
|
||||||
legendArr: {
|
|
||||||
type: Array as PropType<Array<string>>,
|
|
||||||
default: () => [],
|
|
||||||
},
|
|
||||||
datas: {
|
|
||||||
type: Array as PropType<Array<Array<number>>>,
|
|
||||||
default: () => [],
|
|
||||||
},
|
|
||||||
colorArr: {
|
|
||||||
type: Array as PropType<Array<Array<string>>>,
|
|
||||||
default: () => [],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const chartContainer = ref<HTMLDivElement | null>(null);
|
|
||||||
let chartInstance: echarts.ECharts | null = null;
|
|
||||||
|
|
||||||
// 自定义3D形状
|
|
||||||
const CubeLeft = echarts.graphic.extendShape({
|
|
||||||
shape: { x: 0, y: 0 },
|
|
||||||
buildPath: (ctx, shape) => {
|
|
||||||
const { xAxisPoint } = shape;
|
|
||||||
const [c0, c1, c2, c3] = [
|
|
||||||
[shape.x, shape.y],
|
|
||||||
[shape.x - 12, shape.y - 6],
|
|
||||||
[xAxisPoint[0] - 12, xAxisPoint[1] - 6],
|
|
||||||
[xAxisPoint[0], xAxisPoint[1]],
|
|
||||||
];
|
|
||||||
ctx
|
|
||||||
.moveTo(c0[0], c0[1])
|
|
||||||
.lineTo(c1[0], c1[1])
|
|
||||||
.lineTo(c2[0], c2[1])
|
|
||||||
.lineTo(c3[0], c3[1])
|
|
||||||
.closePath();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const CubeRight = echarts.graphic.extendShape({
|
|
||||||
shape: { x: 0, y: 0 },
|
|
||||||
buildPath: (ctx, shape) => {
|
|
||||||
const { xAxisPoint } = shape;
|
|
||||||
const [c1, c2, c3, c4] = [
|
|
||||||
[shape.x, shape.y],
|
|
||||||
[xAxisPoint[0], xAxisPoint[1]],
|
|
||||||
[xAxisPoint[0] + 12, xAxisPoint[1] - 6],
|
|
||||||
[shape.x + 12, shape.y - 6],
|
|
||||||
];
|
|
||||||
ctx
|
|
||||||
.moveTo(c1[0], c1[1])
|
|
||||||
.lineTo(c2[0], c2[1])
|
|
||||||
.lineTo(c3[0], c3[1])
|
|
||||||
.lineTo(c4[0], c4[1])
|
|
||||||
.closePath();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const CubeTop = echarts.graphic.extendShape({
|
|
||||||
shape: { x: 0, y: 0 },
|
|
||||||
buildPath: (ctx, shape) => {
|
|
||||||
const [c1, c2, c3, c4] = [
|
|
||||||
[shape.x, shape.y],
|
|
||||||
[shape.x + 12, shape.y - 6],
|
|
||||||
[shape.x, shape.y - 12],
|
|
||||||
[shape.x - 12, shape.y - 6],
|
|
||||||
];
|
|
||||||
ctx
|
|
||||||
.moveTo(c1[0], c1[1])
|
|
||||||
.lineTo(c2[0], c2[1])
|
|
||||||
.lineTo(c3[0], c3[1])
|
|
||||||
.lineTo(c4[0], c4[1])
|
|
||||||
.closePath();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// 注册三个面图形
|
|
||||||
echarts.graphic.registerShape("CubeLeft", CubeLeft);
|
|
||||||
echarts.graphic.registerShape("CubeRight", CubeRight);
|
|
||||||
echarts.graphic.registerShape("CubeTop", CubeTop);
|
|
||||||
|
|
||||||
// 初始化图表
|
|
||||||
const initChart = () => {
|
|
||||||
if (!chartContainer.value) return;
|
|
||||||
|
|
||||||
chartInstance = echarts.init(chartContainer.value);
|
|
||||||
setTimeout(() => {
|
|
||||||
chartInstance?.resize();
|
|
||||||
updateChart();
|
|
||||||
}, 500);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 更新图表配置
|
|
||||||
const updateChart = () => {
|
|
||||||
if (!chartInstance) return;
|
|
||||||
const series = props.datas
|
|
||||||
.map((item, index) => [
|
|
||||||
{
|
|
||||||
type: "custom",
|
|
||||||
name: props.legendArr[index],
|
|
||||||
renderItem: (params, api) => ({
|
|
||||||
type: "group",
|
|
||||||
x: (index - props.datas.length / 2) * 30 + 15,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: "CubeLeft",
|
|
||||||
shape: {
|
|
||||||
api,
|
|
||||||
xValue: api.value(0),
|
|
||||||
yValue: api.value(1),
|
|
||||||
x: api.coord([api.value(0), api.value(1)])[0],
|
|
||||||
y: api.coord([api.value(0), api.value(1)])[1],
|
|
||||||
xAxisPoint: api.coord([api.value(0), 0]),
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
||||||
{
|
|
||||||
offset: 0,
|
|
||||||
color: props.colorArr[index % props.colorArr.length][1],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
offset: 1,
|
|
||||||
color: props.colorArr[index % props.colorArr.length][0],
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "CubeRight",
|
|
||||||
shape: {
|
|
||||||
api,
|
|
||||||
xValue: api.value(0),
|
|
||||||
yValue: api.value(1),
|
|
||||||
x: api.coord([api.value(0), api.value(1)])[0],
|
|
||||||
y: api.coord([api.value(0), api.value(1)])[1],
|
|
||||||
xAxisPoint: api.coord([api.value(0), 0]),
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
||||||
{
|
|
||||||
offset: 0,
|
|
||||||
color: props.colorArr[index % props.colorArr.length][1],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
offset: 1,
|
|
||||||
color: props.colorArr[index % props.colorArr.length][0],
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "CubeTop",
|
|
||||||
shape: {
|
|
||||||
api,
|
|
||||||
xValue: api.value(0),
|
|
||||||
yValue: api.value(1),
|
|
||||||
x: api.coord([api.value(0), api.value(1)])[0],
|
|
||||||
y: api.coord([api.value(0), api.value(1)])[1],
|
|
||||||
xAxisPoint: api.coord([api.value(0), 0]),
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
||||||
{
|
|
||||||
offset: 0,
|
|
||||||
color: props.colorArr[index % props.colorArr.length][1],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
offset: 1,
|
|
||||||
color: props.colorArr[index % props.colorArr.length][1],
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
data: item,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "bar",
|
|
||||||
name: props.legendArr[index],
|
|
||||||
barWidth: 25,
|
|
||||||
// label: {
|
|
||||||
// normal: {
|
|
||||||
// show: true,
|
|
||||||
// position: "top",
|
|
||||||
// fontSize: 16,
|
|
||||||
// color: "#fff",
|
|
||||||
// offset: [0, -10],
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
itemStyle: { color: "transparent" },
|
|
||||||
data: item,
|
|
||||||
yAxisIndex: 0, // 使用左y轴
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "bar",
|
|
||||||
name: props.legendArr[index],
|
|
||||||
barWidth: 25,
|
|
||||||
itemStyle: { color: "transparent" },
|
|
||||||
data: item,
|
|
||||||
yAxisIndex: 1, // 使用左y轴
|
|
||||||
},
|
|
||||||
])
|
|
||||||
.flat();
|
|
||||||
|
|
||||||
chartInstance.setOption({
|
|
||||||
tooltip: {
|
|
||||||
trigger: "axis",
|
|
||||||
borderWidth: 0,
|
|
||||||
backgroundColor: "rgba(8,36,68,.9)",
|
|
||||||
color: "#fff",
|
|
||||||
textStyle: { color: "#fff" },
|
|
||||||
formatter: (params) => {
|
|
||||||
let str = params[0].name + "</br>";
|
|
||||||
params.forEach((item, index) => {
|
|
||||||
if (item.seriesType === "custom") {
|
|
||||||
str += `
|
|
||||||
<div style='display:flex;justify-content:space-between;align-items:center'>
|
|
||||||
<div style='margin-right:20px;'>
|
|
||||||
<span style="display:inline-block;width:10px;height:10px;border-radius:5px;background-color:${
|
|
||||||
props.colorArr[index % props.colorArr.length][0]
|
|
||||||
}"></span>
|
|
||||||
${item.seriesName}
|
|
||||||
</div>
|
|
||||||
<span> ${item.value ? item.value : "-"}</span>
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return str;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
left: "5%",
|
|
||||||
right: "5%",
|
|
||||||
top: "5%",
|
|
||||||
bottom: "10%",
|
|
||||||
containLabel: true,
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
left: "center",
|
|
||||||
top: "90%",
|
|
||||||
itemWidth: 12, // 图例项宽度
|
|
||||||
itemHeight: 8,
|
|
||||||
textStyle: { color: "#fff", fontSize: 12 },
|
|
||||||
data: props.legendArr.map((name, index) => ({
|
|
||||||
name,
|
|
||||||
textStyle: { color: "#fff", fontSize: 12 },
|
|
||||||
itemStyle: { color: props.colorArr[index % props.colorArr.length][1] },
|
|
||||||
})),
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: "category",
|
|
||||||
data: props.xData,
|
|
||||||
axisLine: { lineStyle: { color: "rgba(239, 247, 253, .1)" } },
|
|
||||||
axisLabel: { fontSize: 12, color: "#fff", margin: 12 },
|
|
||||||
},
|
|
||||||
yAxis: [
|
|
||||||
{
|
|
||||||
// name: "kWh",
|
|
||||||
// nameTextStyle: { color: "#fff", fontSize: 12 },
|
|
||||||
splitLine: {
|
|
||||||
lineStyle: { type: "dashed", color: "rgba(80,112,242,0.3)" },
|
|
||||||
},
|
|
||||||
axisLabel: { textStyle: { color: "#8C8C8C" }, fontSize: 12 },
|
|
||||||
// axisLine: { lineStyle: { color: "#8C8C8C" } },
|
|
||||||
// scale: true, // 同步刻度
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// name: "kWh",
|
|
||||||
// nameTextStyle: { color: "#fff", fontSize: 12 },
|
|
||||||
splitLine: { lineStyle: { color: "transparent" } },
|
|
||||||
axisLabel: { textStyle: { color: "#8C8C8C" }, fontSize: 12 },
|
|
||||||
// axisLine: { lineStyle: { color: "#8C8C8C" } },
|
|
||||||
position: "right",
|
|
||||||
// scale: true, // 同步刻度
|
|
||||||
},
|
|
||||||
],
|
|
||||||
series,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
const handleResize = () => {
|
|
||||||
chartInstance?.resize();
|
|
||||||
};
|
|
||||||
// 生命周期管理
|
|
||||||
onMounted(async () => {
|
|
||||||
await nextTick();
|
|
||||||
initChart();
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
if (chartInstance) {
|
|
||||||
chartInstance.dispose();
|
|
||||||
chartInstance = null;
|
|
||||||
chartInstance?.resize();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 响应式更新
|
|
||||||
watch(
|
|
||||||
() => props,
|
|
||||||
async () => {
|
|
||||||
await nextTick();
|
|
||||||
updateChart();
|
|
||||||
// delay(600).then(() => resize());
|
|
||||||
},
|
|
||||||
{
|
|
||||||
deep: true,
|
|
||||||
immediate: true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<div ref="chartContainer" style="width: 100%; height: 100%" />
|
|
||||||
</template>
|
|
@ -1,106 +0,0 @@
|
|||||||
<!--
|
|
||||||
* @Author: donghao donghao@supervision.ltd
|
|
||||||
* @Date: 2025-03-10 18:00:44
|
|
||||||
* @LastEditors: donghao donghao@supervision.ltd
|
|
||||||
* @LastEditTime: 2025-03-18 11:31:05
|
|
||||||
* @FilePath: \5G-Loading-Bay-Web\src\views\dashboard\components\DeviceStatus.vue
|
|
||||||
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
|
||||||
-->
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref } from "vue";
|
|
||||||
defineOptions({
|
|
||||||
name: "DeviceStatus"
|
|
||||||
});
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
deviceStatus: {
|
|
||||||
type: Object,
|
|
||||||
default: () => {}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const deviceStatusOptions = ref<Record<string, any>[]>([
|
|
||||||
{
|
|
||||||
label: "在线",
|
|
||||||
color: "#52C41A",
|
|
||||||
bgColor: "#52C41A",
|
|
||||||
valueKey: "onlineCount" // 在线数量
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "离线",
|
|
||||||
color: "#ccc",
|
|
||||||
bgColor: "#999999",
|
|
||||||
valueKey: "outlineCount" // 故障数量
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "故障",
|
|
||||||
color: "#E80D0D",
|
|
||||||
bgColor: "#E80D0D",
|
|
||||||
valueKey: "errorCount" // 故障数量
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<ul class="w-full text-sm deviceStatus_box">
|
|
||||||
<li
|
|
||||||
class="flex items-center justify-between w-full"
|
|
||||||
:style="{
|
|
||||||
marginBottom: '16px'
|
|
||||||
}"
|
|
||||||
v-for="(v, k) in deviceStatusOptions"
|
|
||||||
:key="k"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="flex items-center justify-center"
|
|
||||||
:style="{
|
|
||||||
backgroundColor: v.bgColor,
|
|
||||||
width: '40px',
|
|
||||||
height: '40px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
marginRight: '12px'
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<div v-if="v.valueKey === 'onlineCount'" class="deviceStatusOnline"></div>
|
|
||||||
<div v-if="v.valueKey === 'errorCount'" class="deviceStatusError"></div>
|
|
||||||
<div v-if="v.valueKey === 'outlineCount'" class="deviceStatusOutline"></div>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col flex-1">
|
|
||||||
<div class="flex justify-between" style="margin-bottom: 4px">
|
|
||||||
<span>{{ v.label }}</span>
|
|
||||||
<span>{{ deviceStatus?.[v.valueKey] }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="w-full">
|
|
||||||
<el-progress
|
|
||||||
:show-text="false"
|
|
||||||
:stroke-width="8"
|
|
||||||
:percentage="deviceStatus?.[v.valueKey]"
|
|
||||||
:color="v.color"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</template>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.deviceStatus_box {
|
|
||||||
li {
|
|
||||||
div {
|
|
||||||
.deviceStatusOnline {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
background: url('@/assets/svg/deviceStatus/online.svg') no-repeat center center;
|
|
||||||
}
|
|
||||||
.deviceStatusError {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
background: url('@/assets/svg/deviceStatus/error.svg') no-repeat center center;
|
|
||||||
}
|
|
||||||
.deviceStatusOutline {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
background: url('@/assets/svg/deviceStatus/outline.svg') no-repeat center center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,92 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { onMounted, onUnmounted, ref, watch } from "vue";
|
|
||||||
import * as echarts from "echarts";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
data: {
|
|
||||||
type: Array as PropType<Array<{ value: number; name: string }>>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
colors: { type: Array as PropType<Array<string>>, default: () => [] },
|
|
||||||
});
|
|
||||||
|
|
||||||
const chartContainer = ref<HTMLDivElement | null>(null);
|
|
||||||
let chartInstance: echarts.ECharts | null = null;
|
|
||||||
const colorsArr = ['#FFCC4A','#028FF5','#06EA7C','#8500FF','#FF7D05','#00D1FF']
|
|
||||||
// 初始化图表
|
|
||||||
const initChart = () => {
|
|
||||||
if (!chartContainer.value) return;
|
|
||||||
chartInstance = echarts.init(chartContainer.value);
|
|
||||||
setTimeout(() => {
|
|
||||||
chartInstance?.resize();
|
|
||||||
updateChart();
|
|
||||||
}, 500);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 更新图表配置
|
|
||||||
const updateChart = () => {
|
|
||||||
if (!chartInstance) return;
|
|
||||||
|
|
||||||
chartInstance.setOption({
|
|
||||||
legend: {
|
|
||||||
type: "scroll",
|
|
||||||
orient: "vertical",
|
|
||||||
left: "70%",
|
|
||||||
align: "left",
|
|
||||||
top: "middle",
|
|
||||||
itemWidth: 16, // 图例项宽度
|
|
||||||
itemHeight: 8,
|
|
||||||
textStyle: { color: "#FFF" },
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: "pie",
|
|
||||||
radius: ["30%", "80%"],
|
|
||||||
center: ["35%", "50%"],
|
|
||||||
label: { show: false },
|
|
||||||
itemStyle: {
|
|
||||||
color: (params) =>
|
|
||||||
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
|
||||||
{ offset: 0, color: props.colors[params.dataIndex] },
|
|
||||||
{ offset: 1, color: colorsArr[params.dataIndex] },
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
data: props.data,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 生命周期管理
|
|
||||||
onMounted(() => {
|
|
||||||
initChart();
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
if (chartInstance) {
|
|
||||||
chartInstance.dispose();
|
|
||||||
chartInstance = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 响应式更新
|
|
||||||
watch(
|
|
||||||
() => props.data,
|
|
||||||
async () => {
|
|
||||||
await nextTick();
|
|
||||||
updateChart();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 窗口大小监听
|
|
||||||
// onMounted(() => {
|
|
||||||
// window.addEventListener("resize", () => chartInstance?.resize());
|
|
||||||
// });
|
|
||||||
|
|
||||||
// onUnmounted(() => {
|
|
||||||
// window.removeEventListener("resize", () => chartInstance?.resize());
|
|
||||||
// });
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<div ref="chartContainer" style="width: 100%; height: 100%" />
|
|
||||||
</template>
|
|
@ -1,92 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { onMounted, onUnmounted, ref, watch } from "vue";
|
|
||||||
import * as echarts from "echarts";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
data: {
|
|
||||||
type: Array as PropType<Array<{ value: number; name: string }>>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
colors: { type: Array as PropType<Array<string>>, default: () => [] },
|
|
||||||
});
|
|
||||||
|
|
||||||
const chartContainer = ref<HTMLDivElement | null>(null);
|
|
||||||
let chartInstance: echarts.ECharts | null = null;
|
|
||||||
const colorsArr = ['#3FE3FA','#FF4D00']
|
|
||||||
// 初始化图表
|
|
||||||
const initChart = () => {
|
|
||||||
if (!chartContainer.value) return;
|
|
||||||
chartInstance = echarts.init(chartContainer.value);
|
|
||||||
setTimeout(() => {
|
|
||||||
chartInstance?.resize();
|
|
||||||
updateChart();
|
|
||||||
}, 500);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 更新图表配置
|
|
||||||
const updateChart = () => {
|
|
||||||
if (!chartInstance) return;
|
|
||||||
|
|
||||||
chartInstance.setOption({
|
|
||||||
legend: {
|
|
||||||
type: "scroll",
|
|
||||||
orient: "vertical",
|
|
||||||
left: "70%",
|
|
||||||
align: "left",
|
|
||||||
top: "middle",
|
|
||||||
itemWidth: 16, // 图例项宽度
|
|
||||||
itemHeight: 8,
|
|
||||||
textStyle: { color: "#FFF" },
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: "pie",
|
|
||||||
radius: ["40%", "80%"],
|
|
||||||
center: ["35%", "50%"],
|
|
||||||
label: { show: false },
|
|
||||||
itemStyle: {
|
|
||||||
color: (params) =>
|
|
||||||
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
|
||||||
{ offset: 0, color: props.colors[params.dataIndex] },
|
|
||||||
{ offset: 1, color: colorsArr[params.dataIndex] },
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
data: props.data,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 生命周期管理
|
|
||||||
onMounted(() => {
|
|
||||||
initChart();
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
if (chartInstance) {
|
|
||||||
chartInstance.dispose();
|
|
||||||
chartInstance = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 响应式更新
|
|
||||||
watch(
|
|
||||||
() => props.data,
|
|
||||||
async () => {
|
|
||||||
await nextTick();
|
|
||||||
updateChart();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 窗口大小监听
|
|
||||||
// onMounted(() => {
|
|
||||||
// window.addEventListener("resize", () => chartInstance?.resize());
|
|
||||||
// });
|
|
||||||
|
|
||||||
// onUnmounted(() => {
|
|
||||||
// window.removeEventListener("resize", () => chartInstance?.resize());
|
|
||||||
// });
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<div ref="chartContainer" style="width: 100%; height: 100%" />
|
|
||||||
</template>
|
|
@ -1,49 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="flex items-center justify-center w-full h-full position-relative">
|
|
||||||
<video ref="videoRef" :controls="false" muted :src="videoUrl" width="100%" height="144"
|
|
||||||
style="object-fit: cover;" @error="handleVideoError" v-if="!isVideoError"></video>
|
|
||||||
<div class="bg_error_img" v-if="isVideoError">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div :class="{ 'bg_icon': true, 'playing': isPlaying }" v-if="!isVideoError">
|
|
||||||
<!-- {{ isPlaying }} -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
videoUrl: string;
|
|
||||||
isPlaying: boolean;
|
|
||||||
}>();
|
|
||||||
const videoRef = ref<HTMLVideoElement | null>(null);
|
|
||||||
const isVideoError = ref<boolean>(false);
|
|
||||||
|
|
||||||
const handleVideoError = () => {
|
|
||||||
console.log('handleVideoError')
|
|
||||||
isVideoError.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.bg_error_img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: url("@/assets/common/load_file_error.png") no-repeat center center;
|
|
||||||
background-size: 50%;
|
|
||||||
border: 1px dashed red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg_icon {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: url("@/assets/common/player_icon_1.png") no-repeat center center;
|
|
||||||
background-size: 40px;
|
|
||||||
|
|
||||||
&.playing {
|
|
||||||
background: url("@/assets/common/player_icon_2.png") no-repeat center center;
|
|
||||||
background-size: 40px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -0,0 +1,13 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: donghao donghao@supervision.ltd
|
||||||
|
* @Date: 2025-06-12 10:26:59
|
||||||
|
* @LastEditors: donghao donghao@supervision.ltd
|
||||||
|
* @LastEditTime: 2025-06-12 10:38:19
|
||||||
|
* @FilePath: \Web-Traffic-Police\src\views\dataView\components\Type1ObjectDetect.vue
|
||||||
|
* @Description: 目标检测
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
1
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -0,0 +1,13 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: donghao donghao@supervision.ltd
|
||||||
|
* @Date: 2025-06-12 10:27:06
|
||||||
|
* @LastEditors: donghao donghao@supervision.ltd
|
||||||
|
* @LastEditTime: 2025-06-12 10:38:27
|
||||||
|
* @FilePath: \Web-Traffic-Police\src\views\dataView\components\Type2LicensePlateRecog.vue
|
||||||
|
* @Description: 车牌识别
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -0,0 +1,13 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: donghao donghao@supervision.ltd
|
||||||
|
* @Date: 2025-06-12 10:37:10
|
||||||
|
* @LastEditors: donghao donghao@supervision.ltd
|
||||||
|
* @LastEditTime: 2025-06-12 10:38:40
|
||||||
|
* @FilePath: \Web-Traffic-Police\src\views\dataView\components\Type4AudioDetection.vue
|
||||||
|
* @Description: 递烟
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -0,0 +1,13 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: donghao donghao@supervision.ltd
|
||||||
|
* @Date: 2025-06-12 10:37:10
|
||||||
|
* @LastEditors: donghao donghao@supervision.ltd
|
||||||
|
* @LastEditTime: 2025-06-12 10:38:40
|
||||||
|
* @FilePath: \Web-Traffic-Police\src\views\dataView\components\Type4AudioDetection.vue
|
||||||
|
* @Description: 音频检测
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -1,21 +0,0 @@
|
|||||||
self.onmessage = function (e) {
|
|
||||||
console.log('Received message:', e.data);
|
|
||||||
const { positions, gridSize, grid } = e.data;
|
|
||||||
const numPoints = positions.length / 3;
|
|
||||||
console.log('Number of points:', numPoints);
|
|
||||||
|
|
||||||
// 计算每个点的密度
|
|
||||||
const densities = [];
|
|
||||||
for (let i = 0; i < numPoints; i++) {
|
|
||||||
const x = positions[i * 3];
|
|
||||||
const y = positions[i * 3 + 1];
|
|
||||||
const z = positions[i * 3 + 2];
|
|
||||||
const gridX = Math.floor(x / gridSize);
|
|
||||||
const gridY = Math.floor(y / gridSize);
|
|
||||||
const gridZ = Math.floor(z / gridSize);
|
|
||||||
const key = `${gridX},${gridY},${gridZ}`;
|
|
||||||
densities.push(grid[key] || 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.postMessage(densities);
|
|
||||||
};
|
|
@ -0,0 +1,104 @@
|
|||||||
|
{
|
||||||
|
"titles": ["\u76ee\u6807\u68c0\u6d4b"],
|
||||||
|
"video_url": "http://110.40.131.100:8106/media/test_video/217.mp4",
|
||||||
|
"\u4eba\u673a\u5206\u79bb": false,
|
||||||
|
"\u4eba\u673a\u5206\u79bb\u65f6\u95f4": [],
|
||||||
|
"\u4eba\u8138\u56fe\u7247": [],
|
||||||
|
"\u544a\u77e5\u5904\u7f5a\u5185\u5bb9": false,
|
||||||
|
"\u544a\u77e5\u590d\u8bae\u8bc9\u8bbc\u7b49\u6551\u6d4e\u9014\u5f84": false,
|
||||||
|
"\u544a\u77e5\u6267\u6cd5\u4f9d\u636e": false,
|
||||||
|
"\u544a\u77e5\u6267\u6cd5\u5168\u7a0b\u88ab\u8bb0\u5f55": false,
|
||||||
|
"\u544a\u77e5\u6c11\u8b66\u8eab\u4efd": false,
|
||||||
|
"\u544a\u77e5\u7533\u8fa9\u6743\u529b": false,
|
||||||
|
"\u544a\u77e5\u8fdd\u6cd5\u4e8b\u5b9e": false,
|
||||||
|
"\u591a\u6b21\u5439\u6c14": false,
|
||||||
|
"\u591a\u6b21\u5439\u6c14\u65f6\u95f4": [],
|
||||||
|
"\u6838\u67e5\u5f53\u4e8b\u4eba\u8eab\u4efd\u4fe1\u606f": false,
|
||||||
|
"\u76ee\u6807\u68c0\u6d4b": {
|
||||||
|
"\u4eba": [
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/17.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/5.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/18.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/27.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/29.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/11.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/22.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/30.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/23.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/14.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/31.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/4.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/28.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/26.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/9.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/7.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/24.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/20.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/2.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/25.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/6.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/19.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/12.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/13.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/10.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/1.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/16.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/3.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/8.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/21.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4eba/15.jpg"
|
||||||
|
],
|
||||||
|
"\u4fe1\u53f7\u706f": [
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u4fe1\u53f7\u706f/1.jpg"
|
||||||
|
],
|
||||||
|
"\u8f66": [
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/17.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/5.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/18.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/27.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/11.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/22.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/23.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/14.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/4.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/28.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/26.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/9.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/7.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/24.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/20.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/2.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/25.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/6.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/19.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/12.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/13.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/10.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/1.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/16.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/3.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/8.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/21.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u76ee\u6807\u68c0\u6d4b/object_det/\u8f66/15.jpg"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"\u89c6\u9891\u635f\u574f": false,
|
||||||
|
"\u8bed\u901f": 0,
|
||||||
|
"\u8bed\u97f3\u89d2\u8272": {},
|
||||||
|
"\u8f66\u724c\u53f7": [],
|
||||||
|
"\u8f66\u724c\u56fe\u7247": [],
|
||||||
|
"\u8f66\u724c\u989c\u8272": [],
|
||||||
|
"\u8fc7\u6fc0\u884c\u4e3a": false,
|
||||||
|
"\u8fc7\u6fc0\u884c\u4e3a\u65f6\u95f4": [],
|
||||||
|
"\u9003\u907f\u9152\u7cbe\u68c0\u6d4b": false,
|
||||||
|
"\u9003\u907f\u9152\u7cbe\u68c0\u6d4b\u65f6\u95f4": [],
|
||||||
|
"\u9012\u70df": false,
|
||||||
|
"\u9012\u70df\u65f6\u95f4": [],
|
||||||
|
"\u9012\u94b1": false,
|
||||||
|
"\u9012\u94b1\u65f6\u95f4": [],
|
||||||
|
"\u906e\u6321": false,
|
||||||
|
"\u906e\u6321\u65f6\u95f4": [],
|
||||||
|
"\u906e\u6321\u8f66\u724c": false,
|
||||||
|
"\u906e\u6321\u8f66\u724c\u65f6\u95f4": [],
|
||||||
|
"\u9152\u7cbe\u5ea6\u6570": 0
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
{
|
||||||
|
"titles": ["\u8f66\u724c\u8bc6\u522b"],
|
||||||
|
"video_url": "http://110.40.131.100:8106/media/test_video/213.mp4",
|
||||||
|
"\u4eba\u673a\u5206\u79bb": false,
|
||||||
|
"\u4eba\u673a\u5206\u79bb\u65f6\u95f4": [],
|
||||||
|
"\u4eba\u8138\u56fe\u7247": [],
|
||||||
|
"\u544a\u77e5\u5904\u7f5a\u5185\u5bb9": false,
|
||||||
|
"\u544a\u77e5\u590d\u8bae\u8bc9\u8bbc\u7b49\u6551\u6d4e\u9014\u5f84": false,
|
||||||
|
"\u544a\u77e5\u6267\u6cd5\u4f9d\u636e": false,
|
||||||
|
"\u544a\u77e5\u6267\u6cd5\u5168\u7a0b\u88ab\u8bb0\u5f55": false,
|
||||||
|
"\u544a\u77e5\u6c11\u8b66\u8eab\u4efd": false,
|
||||||
|
"\u544a\u77e5\u7533\u8fa9\u6743\u529b": false,
|
||||||
|
"\u544a\u77e5\u8fdd\u6cd5\u4e8b\u5b9e": false,
|
||||||
|
"\u591a\u6b21\u5439\u6c14": false,
|
||||||
|
"\u591a\u6b21\u5439\u6c14\u65f6\u95f4": [],
|
||||||
|
"\u6838\u67e5\u5f53\u4e8b\u4eba\u8eab\u4efd\u4fe1\u606f": false,
|
||||||
|
"\u76ee\u6807\u68c0\u6d4b": {},
|
||||||
|
"\u89c6\u9891\u635f\u574f": false,
|
||||||
|
"\u8bed\u901f": 0,
|
||||||
|
"\u8bed\u97f3\u89d2\u8272": {},
|
||||||
|
"\u8f66\u724c\u53f7": [
|
||||||
|
"\u9655E\u00b7J3333",
|
||||||
|
"\u9655U\u00b7666B6",
|
||||||
|
"\u9655E\u00b7N2222",
|
||||||
|
"\u9655U\u00b7CR032",
|
||||||
|
"\u9655U\u00b7D9999",
|
||||||
|
"\u9655A\u00b700026",
|
||||||
|
"\u9655A\u00b788D88",
|
||||||
|
"\u9655E\u00b7Y7777",
|
||||||
|
"\u9655A\u00b7S0325",
|
||||||
|
"\u9655E\u00b739999",
|
||||||
|
"\u9655K\u00b744444",
|
||||||
|
"\u9655E\u00b7K1111",
|
||||||
|
"\u7518M\u00b733333"
|
||||||
|
],
|
||||||
|
"\u8f66\u724c\u56fe\u7247": [
|
||||||
|
"http://110.40.131.100:8106/images/\u8f66\u724c_2/license_plate/\u9655E\u00b7J3333.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u8f66\u724c_2/license_plate/\u9655U\u00b7666B6.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u8f66\u724c_2/license_plate/\u9655E\u00b7N2222.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u8f66\u724c_2/license_plate/\u9655U\u00b7CR032.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u8f66\u724c_2/license_plate/\u9655U\u00b7D9999.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u8f66\u724c_2/license_plate/\u9655A\u00b700026.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u8f66\u724c_2/license_plate/\u9655A\u00b788D88.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u8f66\u724c_2/license_plate/\u9655E\u00b7Y7777.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u8f66\u724c_2/license_plate/\u9655A\u00b7S0325.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u8f66\u724c_2/license_plate/\u9655E\u00b739999.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u8f66\u724c_2/license_plate/\u9655K\u00b744444.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u8f66\u724c_2/license_plate/\u9655E\u00b7K1111.jpg",
|
||||||
|
"http://110.40.131.100:8106/images/\u8f66\u724c_2/license_plate/\u7518M\u00b733333.jpg"
|
||||||
|
],
|
||||||
|
"\u8f66\u724c\u989c\u8272": [
|
||||||
|
"\u9ec4",
|
||||||
|
"\u9ec4",
|
||||||
|
"\u9ec4",
|
||||||
|
"\u9ec4",
|
||||||
|
"\u9ec4",
|
||||||
|
"\u9ec4",
|
||||||
|
"\u9ec4",
|
||||||
|
"\u9ec4",
|
||||||
|
"\u9ec4",
|
||||||
|
"\u9ec4",
|
||||||
|
"\u9ec4",
|
||||||
|
"\u9ec4",
|
||||||
|
"\u9ec4"
|
||||||
|
],
|
||||||
|
"\u8fc7\u6fc0\u884c\u4e3a": false,
|
||||||
|
"\u8fc7\u6fc0\u884c\u4e3a\u65f6\u95f4": [],
|
||||||
|
"\u9003\u907f\u9152\u7cbe\u68c0\u6d4b": false,
|
||||||
|
"\u9003\u907f\u9152\u7cbe\u68c0\u6d4b\u65f6\u95f4": [],
|
||||||
|
"\u9012\u70df": false,
|
||||||
|
"\u9012\u70df\u65f6\u95f4": [],
|
||||||
|
"\u9012\u94b1": false,
|
||||||
|
"\u9012\u94b1\u65f6\u95f4": [],
|
||||||
|
"\u906e\u6321": false,
|
||||||
|
"\u906e\u6321\u65f6\u95f4": [],
|
||||||
|
"\u906e\u6321\u8f66\u724c": false,
|
||||||
|
"\u906e\u6321\u8f66\u724c\u65f6\u95f4": [],
|
||||||
|
"\u9152\u7cbe\u5ea6\u6570": 0
|
||||||
|
}
|