feat: 按业务要求微调模块

master
donghao 5 days ago
parent c740711751
commit 9d98404e71

@ -1,8 +1,16 @@
/*
* @Author: donghao donghao@supervision.ltd
* @Date: 2025-06-10 17:36:23
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-06-16 11:29:01
* @FilePath: \Web-Traffic-Police\src\config\index.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
const env = import.meta.env const env = import.meta.env
export const config = { export const config = {
apiHost: 'http://192.168.10.103:8888', // 接口地址 apiHost: 'http://192.168.10.103:8888', // 接口地址
apiMapTimeout: 600_000, // 接口轮询时间 apiMapTimeout: 60_000, // 接口轮询时间
env: env.VITE_APP_ENV, env: env.VITE_APP_ENV,
baseURL: env.VITE_APP_BASE_API, baseURL: env.VITE_APP_BASE_API,
timeout: 10000, timeout: 10000,

@ -0,0 +1,13 @@
/*
* @Author: donghao donghao@supervision.ltd
* @Date: 2025-06-16 15:41:45
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-06-16 15:43:58
* @FilePath: \Web-Traffic-Police\src\utils\forFiles.ts
* @Description:
*/
export function fetchFileNameByPath(path) {
const lastSlash = path.lastIndexOf("/");
if (lastSlash === -1) return path; // 如果没有斜杠,返回整个路径
return path.substring(lastSlash + 1);
}

@ -1,23 +1,24 @@
<!-- src/components/PollingComponent.vue --> <!-- src/components/PollingComponent.vue -->
<script setup lang="ts"> <script setup lang="ts">
import { config } from '@/config'; import { config } from "@/config";
import Type1ObjectDetect from "./components/Type1ObjectDetect.vue"; import Type1ObjectDetect from "./components/Type1ObjectDetect.vue";
import Type2LicensePlateRecog from "./components/Type2LicensePlateRecog.vue"; import Type2LicensePlateRecog from "./components/Type2LicensePlateRecog.vue";
import Type3TargetRecog from "./components/Type3TargetRecog.vue"; import Type3TargetRecog from "./components/Type3TargetRecog.vue";
import Type4AudioDetection from "./components/Type4AudioDetection.vue"; import Type4AudioDetection from "./components/Type4AudioDetection.vue";
import { useAllData } from './hooks/useAllData'; import { useAllData } from "./hooks/useAllData";
// //
interface ListItem { interface ListItem {
titles: string[]; titles: string[];
video_url: string; video_url: string;
} }
const { filterMenuByData, filterDetailsByData, fetchTypeByTitle } = useAllData() const { filterMenuByData, filterDetailsByData, fetchTypeByTitle } =
useAllData();
// //
const dataList = ref<ListItem[]>([]); const dataList = ref<ListItem[]>([]);
const menuList = ref<string[]>([]) const menuList = ref<string[]>([]);
const detailInfo = ref<ListItem | null>(); // const detailInfo = ref<ListItem | null>(); //
const isLoading = ref<boolean>(false); const isLoading = ref<boolean>(false);
const isHomePage = ref<boolean>(true) const isHomePage = ref<boolean>(true);
const currentTilte = ref<string>(""); const currentTilte = ref<string>("");
const currentType = ref<string>("1"); const currentType = ref<string>("1");
let pollingTimer: number | null = null; let pollingTimer: number | null = null;
@ -30,11 +31,11 @@ const fetchList = async (): Promise<ListItem[]> => {
isLoading.value = true; isLoading.value = true;
// API // API
const response = await fetch(config.apiHost); const response = await fetch(config.apiHost);
if (!response.ok) throw new Error('请求失败'); if (!response.ok) throw new Error("请求失败");
const result = await response.json(); const result = await response.json();
// TypeScript // TypeScript
if (!Array.isArray(result)) { if (!Array.isArray(result)) {
throw new Error('返回数据格式错误'); throw new Error("返回数据格式错误");
} }
return result as ListItem[]; return result as ListItem[];
} catch (err) { } catch (err) {
@ -44,11 +45,31 @@ const fetchList = async (): Promise<ListItem[]> => {
} }
}; };
//
const fetchMenuByData = async () => {
try {
isLoading.value = true;
// API
const response = await fetch(config.apiHost + "/titles");
if (!response.ok) throw new Error("请求失败");
const result = await response.json();
// TypeScript
if (!Array.isArray(result)) {
throw new Error("返回数据格式错误");
}
menuList.value = result;
} catch (err) {
// return []; //
} finally {
isLoading.value = false;
}
};
// //
const fetchInfoList = (result: ListItem[]) => { const fetchInfoList = (result: ListItem[]) => {
dataList.value = result; dataList.value = result;
menuList.value = filterMenuByData(result); // menuList.value = filterMenuByData(result);
} };
// //
const startPolling = () => { const startPolling = () => {
@ -69,7 +90,6 @@ const stopPolling = () => {
abortController?.abort(); abortController?.abort();
}; };
/**跳转页面 */ /**跳转页面 */
const tabDetails = (title: string) => { const tabDetails = (title: string) => {
currentTilte.value = title; currentTilte.value = title;
@ -77,17 +97,18 @@ const tabDetails = (title: string) => {
detailInfo.value = filterDetailsByData(toRaw(dataList.value), title); detailInfo.value = filterDetailsByData(toRaw(dataList.value), title);
currentType.value = fetchTypeByTitle(title); currentType.value = fetchTypeByTitle(title);
isHomePage.value = false; isHomePage.value = false;
console.log(currentType.value, detailInfo.value, 'tabDetails'); console.log(currentType.value, detailInfo.value, "tabDetails");
} };
// //
onMounted(() => { onMounted(() => {
startPolling() fetchMenuByData();
startPolling();
}); });
// //
onUnmounted(() => { onUnmounted(() => {
stopPolling() stopPolling();
}); });
</script> </script>
@ -95,28 +116,55 @@ onUnmounted(() => {
<div class="flex items-center justify-center data-overview-wrap"> <div class="flex items-center justify-center data-overview-wrap">
<div class="menu-wrap" v-if="isHomePage"> <div class="menu-wrap" v-if="isHomePage">
<!-- 递钱 递烟 --> <!-- 递钱 递烟 -->
<div class="flex items-center justify-center menu-item" v-for="title in menuList" :key="title" <div
@click="tabDetails(title)"> class="flex items-center justify-center menu-item"
v-for="title in menuList"
:key="title"
@click="tabDetails(title)"
>
<span>{{ title }}</span> <span>{{ title }}</span>
</div> </div>
</div> </div>
<div class="w-full content-box" v-else> <div class="w-full content-box" v-else>
<!-- 标题栏 --> <!-- 标题栏 -->
<div class="tilte-bar type-first-top" @click="() => isHomePage = true"> <div class="tilte-bar type-first-top" @click="() => (isHomePage = true)">
<span></span> <span>{{ currentTilte }}</span> <span></span> <span>{{ currentTilte }}</span>
</div> </div>
<ul class="content-list-box"> <ul class="content-list-box" v-if="detailInfo?.length">
<li class="content-detail-box"> <li class="content-detail-box">
<Type2LicensePlateRecog typeKey="2" :info="detailInfo" :title="currentTilte" v-if="currentType === '2'" /> <Type2LicensePlateRecog
<Type3TargetRecog typeKey="3" :info="detailInfo" :title="currentTilte" v-else-if="currentType === '3'" /> typeKey="2"
<Type4AudioDetection typeKey="4" :info="detailInfo" :title="currentTilte" v-else-if="currentType === '4'" /> :info="detailInfo"
<Type1ObjectDetect typeKey="1" :info="detailInfo" :title="currentTilte" v-else /> :title="currentTilte"
v-if="currentType === '2'"
/>
<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> </li>
</ul> </ul>
<el-empty v-else>
<el-button type="primary" @click="() => (isHomePage = true)">返回</el-button>
</el-empty>
</div> </div>
</div> </div>
</template> </template>
<style lang="scss"> <style lang="scss">
@import url('./DataOverview.scss'); @import url("./DataOverview.scss");
</style> </style>

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2025-06-12 10:26:59 * @Date: 2025-06-12 10:26:59
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-06-13 14:17:19 * @LastEditTime: 2025-06-18 11:01:59
* @FilePath: \Web-Traffic-Police\src\views\dataView\components\Type1ObjectDetect.vue * @FilePath: \Web-Traffic-Police\src\views\dataView\components\Type1ObjectDetect.vue
* @Description: 目标检测 * @Description: 目标检测
--> -->
@ -13,7 +13,7 @@
> >
<div <div
class="type-first-mid-box" class="type-first-mid-box"
v-for="(item, index) in info.slice( v-for="(item, index) in currentInfo.slice(
(pagination.page - 1) * pagination.pageSize, (pagination.page - 1) * pagination.pageSize,
pagination.page * pagination.pageSize pagination.page * pagination.pageSize
)" )"
@ -26,27 +26,40 @@
controls controls
></video> ></video>
</div> </div>
<div <div class="type-first-mid-box-text max-h-[140px] overflow-auto">
class="type-first-mid-box-text max-h-[140px] overflow-auto" <div>
v-if="title === '酒精度数'" <span>视频名称</span>
> <span style="font-weight: normal">{{
fetchFileNameByPath(item?.video_url)
}}</span>
</div>
<template v-if="title === '酒精度数'">
<div>
<span>酒精度数</span> <span>酒精度数</span>
<span style="font-weight: normal" <span style="font-weight: normal"
>{{ item["酒精度数"] }}mg/100ml</span >{{ item["酒精度数"] }}mg/100ml</span
> >
</div> </div>
<div class="type-first-mid-box-text" v-else-if="title === ''"> <div>
<span>酒精检测时间</span>
<span style="font-weight: normal"
>{{ item["酒精检测时间"] }}</span
>
</div>
</template>
<div v-else-if="title === ''">
<span>语音角色</span> <span>语音角色</span>
<div class="max-h-[120px] overflow-auto"> <div class="max-h-[75px] overflow-auto">
<p v-for="(v, k) in item['语音角色']" :key="k"> <div v-for="(v, k) in item['语音角色']" :key="k">
<span>角色{{ Number(k) + 1 }}</span> <span>角色{{ Number(k) + 1 }}</span>
<span style="font-weight: normal">{{ <span style="font-weight: normal">{{
transformKeyframes(v) transformKeyframes(v)
}}</span> }}</span>
</p>
</div> </div>
</div> </div>
<div class="type-first-mid-box-text max-h-[140px] overflow-auto" v-else> </div>
<div v-else>
<span>关键帧</span> <span>关键帧</span>
<span style="font-weight: normal">{{ <span style="font-weight: normal">{{
transformKeyframes(item[`${title}时间`]) transformKeyframes(item[`${title}时间`])
@ -54,13 +67,14 @@
</div> </div>
</div> </div>
</div> </div>
<div class="type-first-bottom mt-[87px]" v-if="info?.length"> </div>
<div class="type-first-bottom mt-[87px]" v-if="currentInfo?.length">
<BasePagination <BasePagination
class="bg-transparent" class="bg-transparent"
:showTable="false" :showTable="false"
:total="info?.length" :total="currentInfo?.length"
:pageSize="pagination.pageSize" :pageSize="pagination.pageSize"
:dataSource="info" :dataSource="currentInfo"
:isFixedPagination="true" :isFixedPagination="true"
:page="pagination.page" :page="pagination.page"
@change="changePage" @change="changePage"
@ -72,6 +86,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { BasePagination } from "@/components/CustomTable"; import { BasePagination } from "@/components/CustomTable";
import { fetchFileNameByPath } from "@/utils/forFiles";
defineOptions({ defineOptions({
name: "Type1ObjectDetectWarp", name: "Type1ObjectDetectWarp",
@ -87,11 +102,16 @@ const props = withDefaults(defineProps<Props>(), {
title: String, title: String,
}); });
const pagination = ref({ page: 1, pageSize: 8 }); const pagination = ref({ page: 1, pageSize: 8 });
const currentInfo = ref<Record<string, any> | null>(null);
// //
function changePage({ page, pageSize }) { function changePage({ page, pageSize }) {
pagination.value = { page, pageSize }; pagination.value = { page, pageSize };
} }
function transformKeyframes(data) { function transformKeyframes(data) {
if (!Array.isArray(data)) {
return "";
}
// //
const result = data.map((item) => { const result = data.map((item) => {
// item [, ] // item [, ]
@ -104,6 +124,22 @@ function transformKeyframes(data) {
// //
return `["${result.filter(Boolean).join('", "')}"]`; return `["${result.filter(Boolean).join('", "')}"]`;
} }
watch(
props.info,
() => {
if (["遮挡", "人机分离"].includes(props.title)) {
currentInfo.value = props.info.filter((item) => item?.[props.title]);
} else {
currentInfo.value = props.info;
}
},
{
immediate: true,
deep: true,
}
);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.type-first { .type-first {
@ -137,7 +173,7 @@ function transformKeyframes(data) {
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
height: 162px; height: 162px;
padding: 16px; padding: 16px 16px 0;
font-family: PingFang SC, PingFang SC; font-family: PingFang SC, PingFang SC;
font-weight: bold; font-weight: bold;
font-size: 14px; font-size: 14px;

@ -2,21 +2,31 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2025-06-12 10:27:06 * @Date: 2025-06-12 10:27:06
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-06-13 14:07:24 * @LastEditTime: 2025-06-18 10:54:50
* @FilePath: \Web-Traffic-Police\src\views\dataView\components\Type2LicensePlateRecog.vue * @FilePath: \Web-Traffic-Police\src\views\dataView\components\Type2LicensePlateRecog.vue
* @Description: 车牌识别 人脸检测 * @Description: 车牌识别 人脸检测
--> -->
<template> <template>
<div class="type-second"> <div class="type-second">
<div class="type-second-mid"> <div class="type-second-mid">
<div class="type-second-mid-video"> <div class="type-second-mid-video" v-if="info?.length > 0">
<div class="arrow-icon left-arrow" @click="toPrev()" v-if="info?.length > 1"></div> <div
class="arrow-icon left-arrow"
@click="toPrev()"
v-if="info?.length > 1"
></div>
<div class=" h-[100%] flex flex-col justify-center items-center">
<video <video
class="w-[100%] h-[100%]"
:src="currentInfo?.video_url" :src="currentInfo?.video_url"
controls controls
></video> ></video>
<div class="arrow-icon right-arrow" @click="toNext()" v-if="info?.length > 1"></div> <p>{{ fetchFileNameByPath(currentInfo?.video_url) }}</p>
</div>
<div
class="arrow-icon right-arrow"
@click="toNext()"
v-if="info?.length > 1"
></div>
</div> </div>
<ul <ul
class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4 type-second-mid-box" class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4 type-second-mid-box"
@ -30,8 +40,10 @@
)" )"
:key="index" :key="index"
> >
<div class="type-second-mid-crad-image max-w-[100%] overflow-hidden"> <div
<img :src="item['车牌图片']" class="h-[100%]" /> class="flex items-center justify-center overflow-hidden bg-black type-second-mid-crad-image"
>
<img :src="item['车牌图片']" class="max-h-[100%] max-w-[100%] scale-[1.5]" />
</div> </div>
<div class="type-second-mid-crad-text text_color_6"> <div class="type-second-mid-crad-text text_color_6">
<p> <p>
@ -41,7 +53,8 @@
}}</span> }}</span>
</p> </p>
<p> <p>
<span>牌照号码</span><span class="text_des_1">{{ item["车牌号"] }}</span> <span>牌照号码</span
><span class="text_des_1">{{ item["车牌号"] }}</span>
</p> </p>
</div> </div>
</li> </li>
@ -55,7 +68,9 @@
)" )"
:key="index" :key="index"
> >
<div class="flex items-center justify-center type-second-mid-crad-image max-w-[100%] overflow-hidden"> <div
class="flex items-center justify-center type-second-mid-crad-image max-w-[100%] overflow-hidden"
>
<img :src="item['人脸图片']" class="h-[100%]" /> <img :src="item['人脸图片']" class="h-[100%]" />
</div> </div>
<div class="type-second-mid-crad-text text_color_6"> <div class="type-second-mid-crad-text text_color_6">
@ -84,7 +99,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { BasePagination } from "@/components/CustomTable"; import { BasePagination } from "@/components/CustomTable";
import { fetchFileNameByPath } from "@/utils/forFiles";
defineOptions({ defineOptions({
name: "Type2LicensePlateRecogWarp", name: "Type2LicensePlateRecogWarp",
}); });
@ -100,11 +115,11 @@ const props = withDefaults(defineProps<Props>(), {
}); });
// //
const objectRegTypeMap = { const objectRegTypeMap = {
'黄': "#E3A108", ["黄"]: "#E3A108",
"蓝": "#3B64AC", ["蓝"]: "#3B64AC",
"绿": "#2BC284", ["绿"]: "#2BC284",
"白": "#1d2129", ["白"]: "#1d2129",
} };
const pagination = ref({ page: 1, pageSize: 8 }); const pagination = ref({ page: 1, pageSize: 8 });
const currentIndex = ref<number>(0); // const currentIndex = ref<number>(0); //
const currentInfo = ref<Record<string, any> | null>(null); const currentInfo = ref<Record<string, any> | null>(null);
@ -172,7 +187,11 @@ watch(
watch( watch(
() => [currentIndex.value], () => [currentIndex.value],
() => { () => {
console.log(currentInfo.value, props.title, "watch-车牌识别-currentInfo.value"); console.log(
currentInfo.value,
props.title,
"watch-车牌识别-currentInfo.value"
);
switch (props.title) { switch (props.title) {
case "车牌识别": case "车牌识别":
currentInfoList.value = convertLPRArrToObjects(); currentInfoList.value = convertLPRArrToObjects();
@ -221,7 +240,6 @@ watch(
} }
.right-arrow { .right-arrow {
background-image: url("@/assets/images/right_arrow.png"); background-image: url("@/assets/images/right_arrow.png");
} }
video { video {
width: 720px; width: 720px;

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2025-06-12 10:37:10 * @Date: 2025-06-12 10:37:10
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-06-13 14:13:16 * @LastEditTime: 2025-06-16 16:16:04
* @FilePath: \Web-Traffic-Police\src\views\dataView\components\Type4AudioDetection.vue * @FilePath: \Web-Traffic-Police\src\views\dataView\components\Type4AudioDetection.vue
* @Description: 递烟 * @Description: 递烟
--> -->
@ -18,11 +18,10 @@
@click="toPrev()" @click="toPrev()"
v-if="info?.length > 1" v-if="info?.length > 1"
></div> ></div>
<video <div class="h-[100%] flex flex-col justify-center items-center">
class="w-[720px] h-[100%]" <video :src="currentInfo?.video_url" controls></video>
:src="currentInfo?.video_url" <p>{{ fetchFileNameByPath(currentInfo?.video_url) }}</p>
controls </div>
></video>
<div <div
class="arrow-icon right-arrow" class="arrow-icon right-arrow"
@click="toNext()" @click="toNext()"
@ -32,11 +31,11 @@
<div class="type-fourth-mid-tab"> <div class="type-fourth-mid-tab">
<el-button <el-button
v-for="v in regTypeMap" v-for="v in regTypeMap"
:type="currentRegType === v.key ? 'primary' : ''" :type="currentRegType === v ? 'primary' : ''"
class="w-[76px] h-[32px!important]" class="w-[76px] h-[32px!important]"
:key="v.key" :key="v"
@click="changeRegType(v)" @click="changeRegType(v)"
>{{ v.title }}</el-button >{{ v }}</el-button
> >
</div> </div>
<div <div
@ -50,7 +49,9 @@
)" )"
:key="index" :key="index"
> >
<div class="flex items-center justify-center type-fourth-mid-crad-image max-w-[100%] overflow-hidden"> <div
class="flex items-center justify-center type-fourth-mid-crad-image max-w-[100%] overflow-hidden"
>
<img :src="item['图片']" class="h-[100%]" /> <img :src="item['图片']" class="h-[100%]" />
</div> </div>
<div class="type-fourth-mid-crad-text"> <div class="type-fourth-mid-crad-text">
@ -76,6 +77,8 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { BasePagination } from "@/components/CustomTable"; import { BasePagination } from "@/components/CustomTable";
import { fetchFileNameByPath } from "@/utils/forFiles";
defineOptions({ defineOptions({
name: "Type3TargetRecog", name: "Type3TargetRecog",
}); });
@ -91,25 +94,8 @@ const props = withDefaults(defineProps<Props>(), {
title: String, title: String,
}); });
// //
const regTypeMap = [ const regTypeMap = ref<string[]>([]);
{ const currentRegType = ref<string>("全部");
key: "0",
title: "全部",
},
{
key: "人",
title: "人员",
},
{
key: "车",
title: "车辆",
},
{
key: "信号灯",
title: "路灯",
},
];
const currentRegType = ref<string>("0");
const pagination = ref({ page: 1, pageSize: 8 }); const pagination = ref({ page: 1, pageSize: 8 });
const currentIndex = ref<number>(0); // const currentIndex = ref<number>(0); //
const currentInfo = ref<Record<string, any> | null>(null); const currentInfo = ref<Record<string, any> | null>(null);
@ -154,7 +140,7 @@ function toNext() {
// //
function changeRegType(record) { function changeRegType(record) {
currentRegType.value = record.key; currentRegType.value = record;
console.log(record, "changeRegType"); console.log(record, "changeRegType");
} }
@ -162,6 +148,7 @@ watch(
props.info, props.info,
() => { () => {
currentInfo.value = props.info[0]; currentInfo.value = props.info[0];
regTypeMap.value = ['全部', ...Object.keys(currentInfo.value?.["目标检测"])];
}, },
{ {
immediate: true, immediate: true,
@ -179,12 +166,12 @@ watch(
); );
pagination.value = { ...toRaw(pagination.value), page: 1 }; pagination.value = { ...toRaw(pagination.value), page: 1 };
const currRegTypeKey = toRaw(currentRegType.value); const currRegTypeKey = toRaw(currentRegType.value);
if (currRegTypeKey === "0") { if (currRegTypeKey === "全部") {
currentInfoList.value = [ let targerArr = []
...convertObjects("人"), Object.keys(currentInfo.value?.["目标检测"]).forEach((key) => {
...convertObjects("车"), targerArr = targerArr.concat([...convertObjects(key)])
...convertObjects("信号灯"), })
]; currentInfoList.value = targerArr
} else { } else {
currentInfoList.value = convertObjects(currRegTypeKey); currentInfoList.value = convertObjects(currRegTypeKey);
} }

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2025-06-12 10:37:10 * @Date: 2025-06-12 10:37:10
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2025-06-13 09:22:29 * @LastEditTime: 2025-06-18 10:50:56
* @FilePath: \Web-Traffic-Police\src\views\dataView\components\Type4AudioDetection.vue * @FilePath: \Web-Traffic-Police\src\views\dataView\components\Type4AudioDetection.vue
* @Description: 音频检测 * @Description: 音频检测
--> -->
@ -43,6 +43,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { BaseTable, BasePagination } from "@/components/CustomTable"; import { BaseTable, BasePagination } from "@/components/CustomTable";
import onLineIcon from "@/assets/common/online_icon.png"; import onLineIcon from "@/assets/common/online_icon.png";
import { fetchFileNameByPath } from "@/utils/forFiles";
defineOptions({ defineOptions({
name: "Type4AudioDetectionWarp", name: "Type4AudioDetectionWarp",
@ -66,18 +67,28 @@ const columns = [
{ {
label: "视频", label: "视频",
property: "video_url", property: "video_url",
width: 240, width: 200,
formatter: (row) => { formatter: (row) => {
return h("video", { return h("video", {
src: row.video_url, src: row.video_url,
controls: "controls", controls: "controls",
style: { style: {
width: "180px", width: "160px",
height: "100px", height: "100px",
}, },
}); });
}, },
}, },
{
label: "文件名称",
property: "video_url",
formatter: (row, column, value) => {
if (value) {
return fetchFileNameByPath(value);
}
return "-";
},
},
{ {
label: "告知执法依据", label: "告知执法依据",
property: "告知执法依据", property: "告知执法依据",
@ -110,6 +121,23 @@ const columns = [
} }
}, },
}, },
//
{
label: "告知处罚内容",
property: "告知处罚内容",
formatter: (row, column, value) => {
if (value) {
return h("img", {
src: onLineIcon,
style: {
width: "20px",
height: "20px",
marginRight: "10px",
},
});
}
},
},
{ {
label: "告知申辩权利", label: "告知申辩权利",
property: "告知申辩权利", property: "告知申辩权利",
@ -129,7 +157,7 @@ const columns = [
{ {
label: "告知复议诉讼等救济途径", label: "告知复议诉讼等救济途径",
property: "告知复议诉讼等救济途径", property: "告知复议诉讼等救济途径",
width: 190, width: 120,
formatter: (row, column, value) => { formatter: (row, column, value) => {
if (value) { if (value) {
return h("img", { return h("img", {
@ -146,7 +174,7 @@ const columns = [
{ {
label: "告知执法全程被记录", label: "告知执法全程被记录",
property: "告知执法全程被记录", property: "告知执法全程被记录",
width: 160, width: 120,
formatter: (row, column, value) => { formatter: (row, column, value) => {
if (value) { if (value) {
return h("img", { return h("img", {
@ -194,7 +222,7 @@ const columns = [
}, },
}, },
{ {
label: "语速(字/分钟)", label: "语速",
property: "语速", property: "语速",
}, },
]; ];

@ -29,6 +29,7 @@ export const useAllData = () => {
"过激行为", "过激行为",
"语音角色", "语音角色",
"多次吹气", "多次吹气",
"视频质量检测",
], ],
"3": ["目标检测"], "3": ["目标检测"],
"2": ["车牌识别", "人脸检测"], "2": ["车牌识别", "人脸检测"],

Loading…
Cancel
Save