feat: 目标检测分页筛选完成

master
donghao 24 hours ago
parent c115e0221b
commit 01b43061d9

Binary file not shown.

After

Width:  |  Height:  |  Size: 734 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 664 B

@ -20,3 +20,13 @@
.bg_basic_content{
// background: linear-gradient( 180deg, rgba(7,16,19,0) 0%, #081417 100%);;
}
.text_des_1{
color:#1D2129
}
.text_color_3 {
color: #333;
}
.text_color_6 {
color: #666;
}

@ -3,7 +3,7 @@
import { config } from '@/config';
import Type1ObjectDetect from "./components/Type1ObjectDetect.vue";
import Type2LicensePlateRecog from "./components/Type2LicensePlateRecog.vue";
import Type3CigaretteOffer from "./components/Type3CigaretteOffer.vue";
import Type3TargetRecog from "./components/Type3TargetRecog.vue";
import Type4AudioDetection from "./components/Type4AudioDetection.vue";
import { useAllData } from './hooks/useAllData';
//
@ -77,7 +77,7 @@ const tabDetails = (title: string) => {
detailInfo.value = filterDetailsByData(toRaw(dataList.value), title);
currentType.value = fetchTypeByTitle(title);
isHomePage.value = false;
console.log(currentType.value, detailInfo.value, 'tabDetails', toRaw(dataList.value));
console.log(currentType.value, detailInfo.value, 'tabDetails');
}
//
@ -108,7 +108,7 @@ onUnmounted(() => {
<ul class="content-list-box">
<li class="content-detail-box">
<Type2LicensePlateRecog typeKey="2" :info="detailInfo" :title="currentTilte" v-if="currentType === '2'" />
<Type3CigaretteOffer typeKey="3" :info="detailInfo" :title="currentTilte" v-else-if="currentType === '3'" />
<Type3TargetRecog typeKey="3" :info="detailInfo" :title="currentTilte" v-else-if="currentType === '3'" />
<Type4AudioDetection typeKey="4" :info="detailInfo" :title="currentTilte" v-else-if="currentType === '4'" />
<Type1ObjectDetect typeKey="1" :info="detailInfo" :title="currentTilte" v-else />
</li>

@ -2,98 +2,125 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2025-06-12 10:26:59
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-06-12 10:38:19
* @LastEditTime: 2025-06-13 10:39:45
* @FilePath: \Web-Traffic-Police\src\views\dataView\components\Type1ObjectDetect.vue
* @Description: 目标检测
-->
<template>
<div class="type-first">
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4 type-first-mid">
<div class="type-first-mid-box" v-for="(item, index) in info" :key="index">
<div class="type-first-mid-box-video">
<video
class="w-[100%] h-[100%]"
:src="item.video_url"
controls
></video>
</div>
<div class="type-first-mid-box-text" v-if="title === '酒精度数'">
<span>酒精度数:</span> <span style="font-weight: normal;">{{ item['酒精度数'] }}</span>
</div>
<div class="type-first-mid-box-text" v-else-if="title === ''">
<span>语音角色:</span> <span style="font-weight: normal;">{{ item['语音角色'] }}</span>
</div>
<div class="type-first-mid-box-text" v-else>
<span>关键帧:</span> <span v-for="item1 in item[`${title}时间`]" style="font-weight: normal;">{{ item1 }}</span>
</div>
</div>
<div class="type-first">
<div
class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4 type-first-mid"
>
<div
class="type-first-mid-box"
v-for="(item, index) in info.slice(
(pagination.page - 1) * pagination.pageSize,
pagination.page * pagination.pageSize
)"
:key="index"
>
<div class="type-first-mid-box-video">
<video
class="w-[100%] h-[100%]"
:src="item.video_url"
controls
></video>
</div>
<div class="type-first-bottom"></div>
<div class="type-first-mid-box-text" v-if="title === '酒精度数'">
<span>酒精度数:</span>
<span style="font-weight: normal">{{ item["酒精度数"] }}</span>
</div>
<div class="type-first-mid-box-text" v-else-if="title === ''">
<span>语音角色:</span>
<span style="font-weight: normal">{{ item["语音角色"] }}</span>
</div>
<div class="type-first-mid-box-text" v-else>
<span>关键帧:</span>
<span
v-for="item1 in item[`${title}时间`]"
style="font-weight: normal"
>{{ item1 }}</span
>
</div>
</div>
</div>
<div class="type-first-bottom mt-[87px]" v-if="info?.length">
<BasePagination
class="bg-transparent"
:showTable="false"
:total="info?.length"
:pageSize="pagination.pageSize"
:dataSource="info"
:isFixedPagination="true"
:page="pagination.page"
@change="changePage"
>
</BasePagination>
</div>
</div>
</template>
<script lang="ts" setup>
import { BasePagination } from "@/components/CustomTable";
defineOptions({
name: "Type1ObjectDetectWarp"
name: "Type1ObjectDetectWarp",
});
interface Props {
typeKey: String;
info: Record<string, any>;
title: String;
typeKey: String;
info: Record<string, any>;
title: String;
}
const props = withDefaults(defineProps < Props > (), {
typeKey: "1",
info: {},
title: String
const props = withDefaults(defineProps<Props>(), {
typeKey: "1",
info: {},
title: String,
});
const pagination = ref({ page: 1, pageSize: 8 });
//
function changePage({ page, pageSize }) {
pagination.value = { page, pageSize };
}
</script>
<style lang="scss" scoped>
.type-first {
.type-first-top {
cursor: pointer;
margin-bottom: 16px;
.type-first-top {
cursor: pointer;
margin-bottom: 16px;
font-family: PingFang SC, PingFang SC;
font-weight: bold;
font-size: 20px;
color: #1d2129;
}
.type-first-mid {
min-height: 744px;
max-height: 744px;
overflow-y: auto;
.type-first-mid-box {
box-sizing: border-box;
width: 348px;
height: 360px;
background: #fff;
border-radius: 4px;
.type-first-mid-box-video {
box-sizing: border-box;
width: 100%;
height: 198px;
img {
border-radius: 4px 4px 0 0;
}
}
.type-first-mid-box-text {
box-sizing: border-box;
width: 100%;
height: 162px;
padding: 16px;
font-family: PingFang SC, PingFang SC;
font-weight: bold;
font-size: 20px;
color: #1D2129;
}
.type-first-mid {
// display: flex;
// justify-self: start;
// justify-content: space-between;
// align-content: space-between;
// flex-direction: row;
// flex-wrap: wrap;
height: 744px;
overflow-y: auto;
.type-first-mid-box {
box-sizing: border-box;
width: 348px;
height: 360px;
background: #fff;
border-radius: 4px;
.type-first-mid-box-video {
box-sizing: border-box;
width: 100%;
height: 198px;
img {
border-radius: 4px 4px 0 0;
}
}
.type-first-mid-box-text {
box-sizing: border-box;
width: 100%;
height: 162px;
padding: 16px;
font-family: PingFang SC, PingFang SC;
font-weight: bold;
font-size: 14px;
color: #1D2129;
}
}
font-size: 14px;
color: #1d2129;
}
}
}
}
</style>
</style>

@ -2,49 +2,68 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2025-06-12 10:27:06
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-06-12 17:37:33
* @LastEditTime: 2025-06-13 13:06:33
* @FilePath: \Web-Traffic-Police\src\views\dataView\components\Type2LicensePlateRecog.vue
* @Description: 车牌识别
* @Description: 车牌识别 人脸检测
-->
<template>
<div class="type-second">
<div class="type-second-mid">
<div class="type-second-mid-video">
<!-- //TODO -->
<div class="arrow-icon left-arrow" @click="toPrev()" v-if="info?.length > 1"></div>
<video
class="w-[100%] h-[100%]"
:src="info[0].video_url"
:src="currentInfo?.video_url"
controls
></video>
<!-- <img src="https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg" class="w-[100%] h-[100%]"/> -->
<div class="arrow-icon right-arrow" @click="toNext()" v-if="info?.length > 1"></div>
</div>
<div
<ul
class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4 type-second-mid-box"
>
<div
class="type-second-mid-crad"
v-for="(item, index) in currentInfoList.slice(
(pagination.page - 1) * pagination.pageSize,
pagination.page * pagination.pageSize
)"
:key="index"
>
<div class="type-second-mid-crad-image">
<img :src="item['车牌图片']" class="w-[100%] h-[100%]" />
</div>
<div class="type-second-mid-crad-text">
<!-- 车辆识别 -->
<p>
<span>牌照颜色</span><span>{{ item["车牌颜色"] }}</span>
</p>
<p>
<span>车牌号</span><span>{{ item["车牌号"] }}</span>
</p>
</div>
</div>
</div>
<template v-if="title === '车牌识别'">
<li
class="type-second-mid-crad"
v-for="(item, index) in currentInfoList.slice(
(pagination.page - 1) * pagination.pageSize,
pagination.page * pagination.pageSize
)"
:key="index"
>
<div class="type-second-mid-crad-image">
<img :src="item['车牌图片']" class="w-[100%] h-[100%]" />
</div>
<div class="type-second-mid-crad-text text_color_6">
<!-- //TODO -->
<p>
<span>牌照颜色</span
><span>{{
item["车牌颜色"] ? item["车牌颜色"] + "色" : "未知"
}}</span>
</p>
<p>
<span>牌照号码</span><span class="text_des_1">{{ item["车牌号"] }}</span>
</p>
</div>
</li>
</template>
<template v-else>
<li
class="type-second-mid-crad face-Recog-box"
v-for="(item, index) in currentInfoList.slice(
(pagination.page - 1) * pagination.pageSize,
pagination.page * pagination.pageSize
)"
:key="index"
>
<div class="type-second-mid-crad-image type-second-mid-crad-image-face-Recog flex justify-center items-center">
<img :src="item['人脸图片']" class="h-[100%]" />
</div>
</li>
</template>
</ul>
</div>
<div class="type-second-bottom mt-[87px]">
<div class="type-second-bottom mt-[87px]" v-if="currentInfoList?.length">
<BasePagination
class="bg-transparent"
:showTable="false"
@ -70,7 +89,6 @@ interface Props {
info: Record<string, any>;
title: String;
}
const props = withDefaults(defineProps<Props>(), {
typeKey: "4",
info: {},
@ -92,12 +110,42 @@ function convertLPRArrToObjects() {
}
return result;
}
//
function convertFRArrToObjects() {
const result = [];
for (let i = 0; i < currentInfo.value?.["人脸图片"].length; i++) {
result.push({
["人脸图片"]: currentInfo.value?.["人脸图片"][i],
});
}
return result;
}
//
function changePage({ page, pageSize }) {
pagination.value = { page, pageSize };
}
//
function changeCurrentVideo(index: number) {
pagination.value = {...toRaw(pagination.value), page: 1 };
currentIndex.value = index;
currentInfo.value = props.info[index];
}
function toPrev() {
if (currentIndex.value > 0) {
changeCurrentVideo(toRaw(currentIndex.value) - 1);
} else {
changeCurrentVideo(props.info.length - 1);
}
}
function toNext() {
if (currentIndex.value < props.info.length - 1) {
changeCurrentVideo(toRaw(currentIndex.value) + 1);
} else {
changeCurrentVideo(0);
}
}
watch(
props.info,
() => {
@ -110,13 +158,15 @@ watch(
);
watch(
currentInfo.value,
() => [currentIndex.value],
() => {
console.log(currentInfo.value, props.title);
console.log(currentInfo.value, props.title, "watch-车牌识别-currentInfo.value");
switch (props.title) {
case "车牌识别":
currentInfoList.value = convertLPRArrToObjects();
break;
default:
currentInfoList.value = convertFRArrToObjects();
break;
}
},
@ -136,7 +186,6 @@ watch(
font-family: PingFang SC, PingFang SC;
font-weight: bold;
font-size: 20px;
color: #1d2129;
}
.type-second-mid {
.type-second-mid-video {
@ -148,6 +197,20 @@ watch(
width: 100%;
height: 324px;
border-radius: 4px;
.arrow-icon {
width: 40px;
height: 40px;
margin: 0 32px;
cursor: pointer;
background-image: url("@/assets/images/left_arrow.png");
background-size: 100%;
background-position: center;
background-repeat: no-repeat;
}
.right-arrow{
background-image: url("@/assets/images/right_arrow.png");
}
video {
width: 720px;
height: 100%;
@ -178,6 +241,9 @@ watch(
border-radius: 4px 4px 0 0;
}
}
.type-second-mid-crad-image-face-Recog{
height: 232px;
}
.type-second-mid-crad-text {
box-sizing: border-box;
width: 100%;
@ -186,7 +252,6 @@ watch(
font-family: PingFang SC, PingFang SC;
font-weight: bold;
font-size: 14px;
color: #1d2129;
}
}
}

@ -1,125 +0,0 @@
<!--
* @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 class="type-fourth">
<!-- <div class="type-fourth-top">
<span></span> <span>车牌识别</span>
</div> -->
<div class="type-fourth-mid">
<div class="type-fourth-mid-video">
<video
class="w-[720px] h-[100%]"
:src="info[0].video_url"
controls
></video>
</div>
<div class="type-fourth-mid-tab">
<el-button type="primary" class="w-[76px] h-[32px!important]">全部</el-button>
<el-button class="w-[76px] h-[32px!important]">人员</el-button>
<el-button class="w-[76px] h-[32px!important]">车辆</el-button>
<el-button class="w-[76px] h-[32px!important]">路灯</el-button>
</div>
<div class="type-fourth-mid-box">
<div class="type-fourth-mid-crad" v-for="(item, index) in 8">
<div class="type-fourth-mid-crad-image">
<img src="https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg" class="w-[100%] h-[100%]"/>
</div>
<div class="type-fourth-mid-crad-text">
<span style="color: #666;">检测类型:</span> 123123
</div>
</div>
</div>
</div>
<div class="type-fourth-bottom"></div>
</div>
</template>
<script lang="ts" setup>
defineOptions({
name: "Type3CigaretteOfferWarp"
});
interface Props {
typeKey: String;
info: Record<string, any>;
title: String;
}
const props = withDefaults(defineProps<Props>(), {
typeKey: "3",
info: {},
title: String,
});
</script>
<style lang="scss" scoped>
.type-fourth {
.type-fourth-top {
cursor: pointer;
margin-bottom: 16px;
font-family: PingFang SC, PingFang SC;
font-weight: bold;
font-size: 20px;
color: #1D2129;
}
.type-fourth-mid {
.type-fourth-mid-video {
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 324px;
border-radius: 4px;
img {
width: 720px;
height: 100%;
border-radius: 4px;
}
}
.type-fourth-mid-tab {
box-sizing: border-box;
margin-top: 24px;
margin-bottom: 16px;
width: 100%;
height: 32px;
}
.type-fourth-mid-box {
display: flex;
justify-content: space-between;
align-content: space-between;
flex-direction: row;
flex-wrap: wrap;
height: 420px;
.type-fourth-mid-crad {
box-sizing: border-box;
width: 348px;
height: 202px;
background: #fff;
border-radius: 4px;
.type-fourth-mid-crad-image {
box-sizing: border-box;
width: 100%;
height: 148px;
img {
border-radius: 4px 4px 0 0;
}
}
.type-fourth-mid-crad-text {
box-sizing: border-box;
width: 100%;
height: 54px;
padding: 16px;
font-family: PingFang SC, PingFang SC;
font-weight: bold;
font-size: 14px;
color: #1D2129;
}
}
}
}
}
</style>

@ -0,0 +1,275 @@
<!--
* @Author: donghao donghao@supervision.ltd
* @Date: 2025-06-12 10:37:10
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-06-13 13:13:42
* @FilePath: \Web-Traffic-Police\src\views\dataView\components\Type4AudioDetection.vue
* @Description: 递烟
-->
<template>
<div class="type-fourth">
<!-- <div class="type-fourth-top">
<span></span> <span>车牌识别</span>
</div> -->
<div class="type-fourth-mid">
<div class="type-fourth-mid-video">
<div
class="arrow-icon left-arrow"
@click="toPrev()"
v-if="info?.length > 1"
></div>
<video
class="w-[720px] h-[100%]"
:src="currentInfo?.video_url"
controls
></video>
<div
class="arrow-icon right-arrow"
@click="toNext()"
v-if="info?.length > 1"
></div>
</div>
<div class="type-fourth-mid-tab">
<el-button
v-for="v in regTypeMap"
:type="currentRegType === v.key ? 'primary' : ''"
class="w-[76px] h-[32px!important]"
:key="v.key"
@click="changeRegType(v)"
>{{ v.title }}</el-button
>
</div>
<div
class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4 type-fourth-mid-box"
>
<div
class="type-fourth-mid-crad"
v-for="(item, index) in currentInfoList.slice(
(pagination.page - 1) * pagination.pageSize,
pagination.page * pagination.pageSize
)"
:key="index"
>
<div class="type-fourth-mid-crad-image">
<img :src="item['图片']" class="w-[100%] h-[100%]" />
</div>
<div class="type-fourth-mid-crad-text">
<span style="color: #666">检测类型:</span> {{ item["检测类型"] }}
</div>
</div>
</div>
</div>
<div class="type-fourth-bottom mt-[100px]" v-if="currentInfoList?.length">
<BasePagination
class="bg-transparent"
:showTable="false"
:total="currentInfoList?.length"
:pageSize="pagination.pageSize"
:dataSource="currentInfoList"
:isFixedPagination="true"
:page="pagination.page"
@change="changePage"
>
</BasePagination>
</div>
</div>
</template>
<script lang="ts" setup>
import { BasePagination } from "@/components/CustomTable";
defineOptions({
name: "Type3TargetRecog",
});
interface Props {
typeKey: String;
info: Record<string, any>;
title: String;
}
const props = withDefaults(defineProps<Props>(), {
typeKey: "3",
info: {},
title: String,
});
//
const regTypeMap = [
{
key: "0",
title: "全部",
},
{
key: "人",
title: "人员",
},
{
key: "车",
title: "车辆",
},
{
key: "信号灯",
title: "路灯",
},
];
const currentRegType = ref<string>("0");
const pagination = ref({ page: 1, pageSize: 8 });
const currentIndex = ref<number>(0); //
const currentInfo = ref<Record<string, any> | null>(null);
const currentInfoList = ref<Record<string, any>[]>([]);
//
function convertObjects(key) {
const targetArr = currentInfo.value?.["目标检测"]?.[key];
const result = [];
for (let i = 0; i < targetArr.length; i++) {
result.push({
["图片"]: targetArr[i],
["检测类型"]: key,
});
}
return result;
}
//
function changePage({ page, pageSize }) {
pagination.value = { page, pageSize };
}
//
function changeCurrentVideo(index: number) {
currentIndex.value = index;
currentInfo.value = props.info[index];
}
function toPrev() {
if (currentIndex.value > 0) {
changeCurrentVideo(toRaw(currentIndex.value) - 1);
} else {
changeCurrentVideo(props.info.length - 1);
}
}
function toNext() {
if (currentIndex.value < props.info.length - 1) {
changeCurrentVideo(toRaw(currentIndex.value) + 1);
} else {
changeCurrentVideo(0);
}
}
//
function changeRegType(record) {
currentRegType.value = record.key;
console.log(record, "changeRegType");
}
watch(
props.info,
() => {
currentInfo.value = props.info[0];
},
{
immediate: true,
deep: true,
}
);
watch(
() => [currentIndex.value, currentRegType.value],
() => {
console.log(
currentInfo.value,
props.title,
"watch-目标检测-currentInfo.value"
);
pagination.value = { ...toRaw(pagination.value), page: 1 };
const currRegTypeKey = toRaw(currentRegType.value);
if (currRegTypeKey === "0") {
currentInfoList.value = [
...convertObjects("人"),
...convertObjects("车"),
...convertObjects("信号灯"),
];
} else {
currentInfoList.value = convertObjects(currRegTypeKey);
}
},
{
immediate: true,
deep: true,
}
);
</script>
<style lang="scss" scoped>
.type-fourth {
.type-fourth-top {
cursor: pointer;
margin-bottom: 16px;
font-family: PingFang SC, PingFang SC;
font-weight: bold;
font-size: 20px;
color: #1d2129;
}
.type-fourth-mid {
.type-fourth-mid-video {
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 324px;
border-radius: 4px;
.arrow-icon {
width: 40px;
height: 40px;
margin: 0 32px;
cursor: pointer;
background-image: url("@/assets/images/left_arrow.png");
background-size: 100%;
background-position: center;
background-repeat: no-repeat;
}
.right-arrow {
background-image: url("@/assets/images/right_arrow.png");
}
video {
width: 720px;
height: 100%;
border-radius: 4px;
}
}
.type-fourth-mid-tab {
box-sizing: border-box;
margin-top: 24px;
margin-bottom: 16px;
width: 100%;
height: 32px;
}
.type-fourth-mid-box {
min-height: 420px;
max-height: 420px;
overflow-y: auto;
.type-fourth-mid-crad {
box-sizing: border-box;
width: 348px;
height: 202px;
background: #fff;
border-radius: 4px;
.type-fourth-mid-crad-image {
box-sizing: border-box;
width: 100%;
height: 148px;
img {
border-radius: 4px 4px 0 0;
}
}
.type-fourth-mid-crad-text {
box-sizing: border-box;
width: 100%;
height: 54px;
padding: 16px;
font-family: PingFang SC, PingFang SC;
font-weight: bold;
font-size: 14px;
color: #1d2129;
}
}
}
}
}
</style>
Loading…
Cancel
Save