Files
rtsp-video-analysis-system/rtsp-vue/src/views/video/alarm/index.vue
2025-09-30 13:24:53 +08:00

369 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="任务名称" prop="taskName">
<el-input
v-model="queryParams.taskName"
placeholder="请输入任务名称"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="设备名称" prop="deviceName">
<el-input
v-model="queryParams.deviceName"
placeholder="请输入设备名称"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="报警类型" prop="alarmType">
<el-input
v-model="queryParams.alarmType"
placeholder="请输入报警类型"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="处理状态" prop="handleStatus">
<el-select v-model="queryParams.handleStatus" placeholder="请选择处理状态" clearable>
<el-option label="未处理" value="0" />
<el-option label="已处理" value="1" />
<el-option label="已忽略" value="2" />
</el-select>
</el-form-item>
<el-form-item label="报警时间">
<el-date-picker
v-model="daterangeAlarmTime"
style="width: 240px"
value-format="YYYY-MM-DD"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Check"
:disabled="multiple"
@click="handleBatchProcess('1')"
v-hasPermi="['video:alarm:handle']"
>批量处理</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="Close"
:disabled="multiple"
@click="handleBatchProcess('2')"
v-hasPermi="['video:alarm:handle']"
>批量忽略</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['video:alarm:export']"
>导出</el-button>
</el-col>
<right-toolbar v-model="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="alarmList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="报警ID" align="center" prop="alarmId" />
<el-table-column label="任务名称" align="center" prop="taskName" />
<el-table-column label="设备名称" align="center" prop="deviceName" />
<el-table-column label="报警类型" align="center" prop="alarmType" />
<el-table-column label="报警级别" align="center" prop="alarmLevel">
<template #default="scope">
<el-tag v-if="scope.row.alarmLevel === '1'" type="info"></el-tag>
<el-tag v-else-if="scope.row.alarmLevel === '2'" type="warning"></el-tag>
<el-tag v-else-if="scope.row.alarmLevel === '3'" type="danger"></el-tag>
</template>
</el-table-column>
<el-table-column label="报警描述" align="center" prop="alarmDesc" />
<el-table-column label="置信度" align="center" prop="confidence">
<template #default="scope">
{{ (scope.row.confidence * 100).toFixed(1) }}%
</template>
</el-table-column>
<el-table-column label="报警图片" align="center" prop="imagePath">
<template #default="scope">
<el-image
v-if="scope.row.imagePath"
style="width: 60px; height: 40px"
:src="scope.row.imagePath"
:preview-src-list="[scope.row.imagePath]"
fit="cover"
/>
</template>
</el-table-column>
<el-table-column label="报警视频" align="center" prop="videoPath">
<template #default="scope">
<el-button
v-if="scope.row.videoPath"
link
type="primary"
icon="VideoPlay"
@click="handleView(scope.row)"
>播放</el-button>
</template>
</el-table-column>
<el-table-column label="报警时间" align="center" prop="alarmTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.alarmTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="处理状态" align="center" prop="handleStatus">
<template #default="scope">
<el-tag v-if="scope.row.handleStatus === '0'" type="danger">未处理</el-tag>
<el-tag v-else-if="scope.row.handleStatus === '1'" type="success">已处理</el-tag>
<el-tag v-else-if="scope.row.handleStatus === '2'" type="info">已忽略</el-tag>
</template>
</el-table-column>
<el-table-column label="处理人" align="center" prop="handleBy" />
<el-table-column label="处理时间" align="center" prop="handleTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.handleTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button
v-if="scope.row.handleStatus === '0'"
link
type="primary"
icon="Check"
@click="handleProcess(scope.row, '1')"
v-hasPermi="['video:alarm:handle']"
>处理</el-button>
<el-button
v-if="scope.row.handleStatus === '0'"
link
type="info"
icon="Close"
@click="handleProcess(scope.row, '2')"
v-hasPermi="['video:alarm:handle']"
>忽略</el-button>
<el-button
link
type="primary"
icon="View"
@click="handleView(scope.row)"
>查看</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page="queryParams.pageNum"
:limit="queryParams.pageSize"
@pagination="getList"
/>
<!-- 处理报警对话框 -->
<el-dialog :title="processTitle" v-model="processOpen" width="500px" append-to-body>
<el-form ref="processRef" :model="processForm" label-width="80px">
<el-form-item label="处理备注" prop="handleRemark">
<el-input
v-model="processForm.handleRemark"
type="textarea"
placeholder="请输入处理备注"
:rows="4"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitProcess"> </el-button>
<el-button @click="processOpen = false"> </el-button>
</div>
</template>
</el-dialog>
<!-- 查看详情对话框 -->
<el-dialog title="报警详情" v-model="viewOpen" width="800px" append-to-body>
<el-descriptions :column="2" border>
<el-descriptions-item label="报警ID">{{ viewForm.alarmId }}</el-descriptions-item>
<el-descriptions-item label="任务名称">{{ viewForm.taskName }}</el-descriptions-item>
<el-descriptions-item label="设备名称">{{ viewForm.deviceName }}</el-descriptions-item>
<el-descriptions-item label="报警类型">{{ viewForm.alarmType }}</el-descriptions-item>
<el-descriptions-item label="报警级别">
<el-tag v-if="viewForm.alarmLevel === '1'" type="info"></el-tag>
<el-tag v-else-if="viewForm.alarmLevel === '2'" type="warning"></el-tag>
<el-tag v-else-if="viewForm.alarmLevel === '3'" type="danger"></el-tag>
</el-descriptions-item>
<el-descriptions-item label="置信度">{{ (viewForm.confidence * 100).toFixed(1) }}%</el-descriptions-item>
<el-descriptions-item label="报警时间" :span="2">
{{ parseTime(viewForm.alarmTime, '{y}-{m}-{d} {h}:{i}:{s}') }}
</el-descriptions-item>
<el-descriptions-item label="报警描述" :span="2">{{ viewForm.alarmDesc }}</el-descriptions-item>
<el-descriptions-item label="处理状态">
<el-tag v-if="viewForm.handleStatus === '0'" type="danger">未处理</el-tag>
<el-tag v-else-if="viewForm.handleStatus === '1'" type="success">已处理</el-tag>
<el-tag v-else-if="viewForm.handleStatus === '2'" type="info">已忽略</el-tag>
</el-descriptions-item>
<el-descriptions-item label="处理人">{{ viewForm.handleBy || '-' }}</el-descriptions-item>
<el-descriptions-item label="处理时间" :span="2">
{{ viewForm.handleTime ? parseTime(viewForm.handleTime, '{y}-{m}-{d} {h}:{i}:{s}') : '-' }}
</el-descriptions-item>
<el-descriptions-item label="处理备注" :span="2">{{ viewForm.handleRemark || '-' }}</el-descriptions-item>
</el-descriptions>
<div v-if="viewForm.imagePath" style="margin-top: 20px;">
<h4>报警图片</h4>
<el-image
style="width: 100%; max-height: 400px"
:src="viewForm.imagePath"
:preview-src-list="[viewForm.imagePath]"
fit="contain"
/>
</div>
<div v-if="viewForm.videoPath" style="margin-top: 20px;">
<h4>报警视频</h4>
<video
:src="viewForm.videoPath"
style="width: 100%; max-height: 420px; background: #000"
controls
preload="metadata"
/>
</div>
</el-dialog>
</div>
</template>
<script setup name="Alarm">
import { listAlarm, handleAlarm, batchHandleAlarm } from "@/api/video/alarm";
const { proxy } = getCurrentInstance();
const alarmList = ref([]);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const multiple = ref(true);
const total = ref(0);
const daterangeAlarmTime = ref([]);
const processOpen = ref(false);
const processTitle = ref("");
const processForm = ref({});
const viewOpen = ref(false);
const viewForm = ref({});
const data = reactive({
queryParams: {
pageNum: 1,
pageSize: 20,
taskName: null,
deviceName: null,
alarmType: null,
handleStatus: null,
beginAlarmTime: null,
endAlarmTime: null
}
});
const { queryParams } = toRefs(data);
/** 查询报警记录列表 */
function getList() {
loading.value = true;
queryParams.value.beginAlarmTime = daterangeAlarmTime.value ? daterangeAlarmTime.value[0] : null;
queryParams.value.endAlarmTime = daterangeAlarmTime.value ? daterangeAlarmTime.value[1] : null;
listAlarm(queryParams.value).then(response => {
alarmList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
function resetQuery() {
daterangeAlarmTime.value = [];
proxy.resetForm("queryRef");
handleQuery();
}
// 多选框选中数据
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.alarmId);
multiple.value = !selection.length;
}
/** 处理报警 */
function handleProcess(row, status) {
processForm.value = {
alarmId: row.alarmId,
handleStatus: status,
handleRemark: ''
};
processTitle.value = status === '1' ? '处理报警' : '忽略报警';
processOpen.value = true;
}
/** 提交处理 */
function submitProcess() {
handleAlarm(processForm.value).then(response => {
proxy.$modal.msgSuccess("操作成功");
processOpen.value = false;
getList();
});
}
/** 批量处理 */
function handleBatchProcess(status) {
const alarmIds = ids.value;
const statusText = status === '1' ? '处理' : '忽略';
proxy.$modal.confirm('是否确认批量' + statusText + '选中的报警记录?').then(function() {
return batchHandleAlarm({
alarmIds: alarmIds,
handleStatus: status,
handleRemark: '批量' + statusText
});
}).then(() => {
getList();
proxy.$modal.msgSuccess("操作成功");
}).catch(() => {});
}
/** 查看详情 */
function handleView(row) {
viewForm.value = { ...row };
viewOpen.value = true;
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('video/alarm/export', {
...queryParams.value
}, `alarm_${new Date().getTime()}.xlsx`)
}
onMounted(() => {
getList();
});
</script>