| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- <template>
- <div class="app-container">
- <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="80px">
- <el-form-item label="告警类型" prop="alarmType">
- <el-select v-model="queryParams.alarmType" placeholder="请选择告警类型" clearable class="search-select">
- <el-option
- v-for="dict in alarm_type"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="告警级别" prop="alarmLevel">
- <el-select v-model="queryParams.alarmLevel" placeholder="请选择告警级别" clearable class="search-select">
- <el-option
- v-for="dict in alarm_level"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="处理状态" prop="handleStatus">
- <el-select v-model="queryParams.handleStatus" placeholder="请选择处理状态" clearable class="search-select">
- <el-option
- v-for="dict in alarm_handle_status"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="告警时间">
- <el-date-picker
- v-model="daterangeAlarmTime"
- value-format="YYYY-MM-DD"
- type="daterange"
- range-separator="-"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- class="search-date"
- />
- </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="warning"
- plain
- icon="Download"
- @click="handleExport"
- v-hasPermi="['base:alarmLog:export']"
- >导出</el-button>
- </el-col>
- <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
- </el-row>
- <el-table v-loading="loading" :data="alarmLogList">
- <el-table-column label="告警时间" align="center" prop="alarmTime" width="170">
- <template #default="scope">
- <span>{{ parseTime(scope.row.alarmTime) }}</span>
- </template>
- </el-table-column>
- <el-table-column label="告警类型" align="center" prop="alarmType" width="110">
- <template #default="scope">
- <dict-tag :options="alarm_type" :value="scope.row.alarmType"/>
- </template>
- </el-table-column>
- <el-table-column label="告警级别" align="center" prop="alarmLevel" width="100">
- <template #default="scope">
- <dict-tag :options="alarm_level" :value="scope.row.alarmLevel"/>
- </template>
- </el-table-column>
- <el-table-column label="告警标题" align="left" prop="alarmTitle" min-width="220" show-overflow-tooltip>
- <template #default="scope">
- <span>{{ scope.row.alarmTitle || formatSummary(scope.row.description) }}</span>
- </template>
- </el-table-column>
- <el-table-column label="来源位置" align="center" prop="sourcePosition" width="160" show-overflow-tooltip />
- <el-table-column label="处理状态" align="center" prop="handleStatus" width="110">
- <template #default="scope">
- <dict-tag :options="alarm_handle_status" :value="scope.row.handleStatus"/>
- </template>
- </el-table-column>
- <el-table-column label="操作" align="center" fixed="right" width="220">
- <template #default="scope">
- <el-button link type="primary" icon="View" @click="handleDetail(scope.row)">详情</el-button>
- <el-button
- v-if="scope.row.handleStatus === '1'"
- link
- type="success"
- icon="CircleCheck"
- @click="openHandleDialog(scope.row, 'confirm')"
- >确认</el-button>
- <el-button
- v-if="scope.row.handleStatus === '1'"
- link
- type="warning"
- icon="CircleClose"
- @click="openHandleDialog(scope.row, 'ignore')"
- >忽略</el-button>
- </template>
- </el-table-column>
- </el-table>
- <pagination
- v-show="total>0"
- :total="total"
- v-model:page="queryParams.pageNum"
- v-model:limit="queryParams.pageSize"
- @pagination="getList"
- />
- <el-dialog title="安防告警详情" v-model="detailOpen" width="820px" append-to-body>
- <el-descriptions :column="2" border>
- <el-descriptions-item label="告警时间">{{ parseTime(detail.alarmTime) || '-' }}</el-descriptions-item>
- <el-descriptions-item label="告警类型">
- <dict-tag :options="alarm_type" :value="detail.alarmType"/>
- </el-descriptions-item>
- <el-descriptions-item label="告警级别">
- <dict-tag :options="alarm_level" :value="detail.alarmLevel"/>
- </el-descriptions-item>
- <el-descriptions-item label="告警来源">
- <dict-tag :options="alarm_source" :value="detail.alarmSource"/>
- </el-descriptions-item>
- <el-descriptions-item label="来源位置">{{ detail.sourcePosition || '-' }}</el-descriptions-item>
- <el-descriptions-item label="处理状态">
- <dict-tag :options="alarm_handle_status" :value="detail.handleStatus"/>
- </el-descriptions-item>
- <el-descriptions-item label="告警标题" :span="2">{{ detail.alarmTitle || '-' }}</el-descriptions-item>
- <el-descriptions-item label="告警描述" :span="2">{{ detail.description || '-' }}</el-descriptions-item>
- <el-descriptions-item label="处理人">{{ detail.handleBy || '-' }}</el-descriptions-item>
- <el-descriptions-item label="处理时间">{{ parseTime(detail.handleTime) || '-' }}</el-descriptions-item>
- <el-descriptions-item label="处理备注" :span="2">{{ detail.handleRemark || '-' }}</el-descriptions-item>
- <el-descriptions-item label="备注" :span="2">{{ detail.remark || '-' }}</el-descriptions-item>
- </el-descriptions>
- <div class="snapshot-block">
- <div class="snapshot-title">抓拍图</div>
- <el-image
- v-if="detail.snapshotUrl"
- class="snapshot-image"
- :src="detail.snapshotUrl"
- :preview-src-list="[detail.snapshotUrl]"
- fit="cover"
- preview-teleported
- />
- <div v-else class="snapshot-empty">暂无抓拍图</div>
- </div>
- <template #footer>
- <div class="dialog-footer">
- <el-button @click="detailOpen = false">关 闭</el-button>
- </div>
- </template>
- </el-dialog>
- <el-dialog :title="handleDialogTitle" v-model="handleOpen" width="520px" append-to-body>
- <el-form ref="handleRef" :model="handleForm" label-width="90px">
- <el-form-item label="告警标题">
- <span>{{ handleForm.alarmTitle || '-' }}</span>
- </el-form-item>
- <el-form-item label="处理备注" prop="handleRemark">
- <el-input
- v-model="handleForm.handleRemark"
- type="textarea"
- :rows="4"
- maxlength="500"
- show-word-limit
- placeholder="请输入处理备注"
- />
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitHandle">确 定</el-button>
- <el-button @click="handleOpen = false">取 消</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup name="AlarmLog">
- import { listAlarmLog, getAlarmLog, confirmAlarmLog, ignoreAlarmLog } from "@/api/base/alarmLog"
- const { proxy } = getCurrentInstance()
- const { alarm_type, alarm_level, alarm_source, alarm_handle_status } = useDict(
- 'alarm_type',
- 'alarm_level',
- 'alarm_source',
- 'alarm_handle_status'
- )
- const alarmLogList = ref([])
- const loading = ref(true)
- const showSearch = ref(true)
- const total = ref(0)
- const daterangeAlarmTime = ref([])
- const queryParams = ref({
- pageNum: 1,
- pageSize: 10,
- alarmType: undefined,
- alarmLevel: undefined,
- handleStatus: undefined
- })
- const detailOpen = ref(false)
- const detail = ref({})
- const handleOpen = ref(false)
- const handleType = ref("")
- const handleDialogTitle = ref("")
- const handleForm = reactive({
- id: null,
- alarmTitle: "",
- handleRemark: ""
- })
- /** 查询安防告警日志列表 */
- function getList() {
- loading.value = true
- const params = proxy.addDateRange(queryParams.value, daterangeAlarmTime.value, 'AlarmTime')
- listAlarmLog(params).then(response => {
- alarmLogList.value = response.rows || []
- total.value = response.total || 0
- }).finally(() => {
- loading.value = false
- })
- }
- /** 搜索按钮操作 */
- function handleQuery() {
- queryParams.value.pageNum = 1
- getList()
- }
- /** 重置按钮操作 */
- function resetQuery() {
- daterangeAlarmTime.value = []
- proxy.resetForm("queryRef")
- handleQuery()
- }
- /** 详情按钮操作 */
- function handleDetail(row) {
- getAlarmLog(row.id).then(response => {
- detail.value = response.data || row
- detailOpen.value = true
- })
- }
- /** 摘要兜底方法 */
- function formatSummary(content) {
- if (!content) return '-'
- return content.length > 60 ? content.substring(0, 60) + '...' : content
- }
- /** 打开确认/忽略弹窗 */
- function openHandleDialog(row, type) {
- handleType.value = type
- handleDialogTitle.value = type === 'confirm' ? '确认告警' : '忽略告警'
- handleForm.id = row.id
- handleForm.alarmTitle = row.alarmTitle || formatSummary(row.description)
- handleForm.handleRemark = ''
- handleOpen.value = true
- }
- /** 提交确认/忽略 */
- function submitHandle() {
- if (!handleForm.id) return
- const request = handleType.value === 'confirm' ? confirmAlarmLog : ignoreAlarmLog
- const successMsg = handleType.value === 'confirm' ? '告警已确认' : '告警已忽略'
- request(handleForm.id, {
- handleRemark: handleForm.handleRemark
- }).then(() => {
- proxy.$modal.msgSuccess(successMsg)
- handleOpen.value = false
- getList()
- })
- }
- /** 导出按钮操作 */
- function handleExport() {
- proxy.$modal.confirm('确认导出当前查询条件下的安防告警日志数据吗?').then(() => {
- const params = proxy.addDateRange(queryParams.value, daterangeAlarmTime.value, 'AlarmTime')
- proxy.download('base/alarmLog/export', {
- ...params
- }, `安防告警日志_${new Date().getTime()}.xlsx`)
- }).catch(() => {})
- }
- getList()
- </script>
- <style scoped>
- .search-select {
- width: 220px;
- }
- .search-date {
- width: 260px;
- }
- .snapshot-block {
- margin-top: 16px;
- }
- .snapshot-title {
- margin-bottom: 8px;
- font-weight: 600;
- color: #303133;
- }
- .snapshot-image {
- width: 220px;
- height: 140px;
- border-radius: 6px;
- border: 1px solid #ebeef5;
- background: #f8fafc;
- }
- .snapshot-empty {
- width: 220px;
- height: 140px;
- display: flex;
- align-items: center;
- justify-content: center;
- color: #909399;
- background: #f8fafc;
- border: 1px dashed #dcdfe6;
- border-radius: 6px;
- font-size: 13px;
- }
- </style>
|