|
<template>
<div class="ai_alarm">
<!-- 顶部的查询组件 -->
<!-- <div class="alarm_header">
<div>
<span class="title">报警类型 : </span>
<t-select v-model="searchdata.alarmTypeCode" style="width:200px;height:32px">
<t-option v-for="item in alarmtypelist" :key="item.code" :value="item.code">{{ item.value }}</t-option>
</t-select>
</div>
<div>
<span class="title">开始时间 : </span>
<t-date-picker :confirm="false" v-model="searchdata.beginTime" placeholder="请选择开始时间" style="width:200px;height:32px"></t-date-picker>
</div>
<div>
<span class="title">结束时间 : </span>
<t-date-picker :confirm="false" v-model="searchdata.endTime" placeholder="请选择结束时间" style="width:200px;height:32px"></t-date-picker>
<t-button color="primary" @click="btnsearch">查询</t-button>
<t-button @click="reset">重置</t-button>
</div>
<t-button icon="upload" style="width:128px;height:32px" class="upload">导出至Excel</t-button>
</div> -->
<div class="track-container">
<div class="search-container">
<div class="search-ctn">
<div>
<div style="display: flex;">
<t-select v-model="searchdata.alarmTypeCode" style="width:200px;height:32px" placeholder="请选择报警类型">
<t-option v-for="item in alarmtypelist" :key="item.code" :value="item.code">{{ item.value }}</t-option>
</t-select>
<template>
<t-button style="margin-left:10px" color="primary" icon="search-outline" @click="btnsearch">查询</t-button>
</template>
<t-button icon="filter-outline" style="margin: 0 10px;" @click="slideVisible = !slideVisible"></t-button>
</div>
</div>
<div class="btns">
<t-button icon="upload" style="width:128px;height:32px" class="upload">导出至Excel</t-button>
<t-dropdown :visibled="customVisibled" trigger-mode="custom">
<t-button slot="trigger" color="secondary" icon="tile-four-outline" class="trigger-button" @click="onTriggerClick"></t-button>
<div slot="popper">
<div style="border-radius: 5px;padding: 20px 20px 20px 20px;background-color: white;">
<t-checkbox-group v-model="social" vertical @change="checkAllGroupChange">
<t-checkbox v-for="(item) in columns" :key="item.label" :value="item.label" :label="item.label">
<span>{{ item.label }}</span>
</t-checkbox>
</t-checkbox-group>
<div style="padding-bottom: 10px">
<t-checkbox :indeterminate="indeterminate" :checked.sync="checkAll" @click.prevent.native="handleCheckAll">全选
</t-checkbox>
</div>
<t-button color="primary" size="sm" @click="onCloseClick">确认</t-button>
</div>
</div>
</t-dropdown>
</div>
</div>
<div class="animate-demo-wrapper">
<transition name="slide-up">
<div v-show="slideVisible" class="transition-box allCondition">
<div class="input-rule">
<span>开始时间:</span>
<t-date-picker :confirm="false" v-model="searchdata.beginTime" placeholder="请选择开始时间" style="width:320px;height:32px"></t-date-picker>
</div>
<div class="input-rule">
<span>结束时间:</span>
<t-date-picker :confirm="false" v-model="searchdata.endTime" placeholder="请选择结束时间" style="width:320px;height:32px"></t-date-picker>
</div>
<a style="float:right;color:#0089d4;" @click="reset" href="javascript:;">重置</a>
</div>
</transition>
</div>
</div>
</div>
<!-- 表格 -->
<t-table :data="data" line @selection-change="handleSelectionChange">
<t-table-column type="selection" width="50"></t-table-column>
<t-table-column v-if="columns[0].show" label="状态" width="100">
<template slot-scope="scope">
<t-tag v-if="scope.row.status=== 'RUN'" state="info">处理中</t-tag>
<t-tag v-if="scope.row.status=== 'INI'" state="warning">未确认</t-tag>
<t-tag v-if="scope.row.status=== 'END'" state="success">已处理</t-tag>
<t-tag v-if="scope.row.status=== 'FAL'" state="danger">误报</t-tag>
</template>
</t-table-column>
<t-table-column v-if="columns[1].show" label="报警类型" prop="alarmTypeName">
</t-table-column>
<t-table-column v-if="columns[2].show" :formatter="date_formatter" label="报警描述" prop="alarmMemo" width="110">
</t-table-column>
<t-table-column v-if="columns[3].show" :formatter="date_formatter" label="设备名称" prop="resourceToolName" width="110">
</t-table-column>
<t-table-column v-if="columns[4].show" :formatter="date_formatter" label="设备编号" prop="resourceToolCode" width="90">
</t-table-column>
<t-table-column v-if="columns[5].show" :formatter="date_formatter" label="设备位置" prop="monitorSceneName" width="120">
</t-table-column>
<t-table-column v-if="columns[6].show" :formatter="date_formatter" label="报警时间" prop="aiIdenTime" width="160px">
</t-table-column>
<t-table-column v-if="columns[7].show" :formatter="date_formatter" label="处理人" prop="workEmployeeRoleName" width="70">
</t-table-column>
<t-table-column v-if="columns[8].show" :formatter="date_formatter" label="处理时间" prop="processTime" width="160px">
</t-table-column>
<t-table-column label="操作" width="140" fixed="right">
<template slot-scope="scope">
<a href="javascript:void(0)" size="sm" style="color:#0089D4" @click="handleClick(scope,0)">详情</a>
<div class="caozuo">
<a v-if="scope.row.status=='RUN'||scope.row.status=='FAL'" style="color:#0089D4" @click="handleClick(scope,1)">关闭</a>
<a v-if="scope.row.status=='INI'" style="color:#0089D4" @click="handleClick(scope,1)">处理</a>
</div>
</template>
</t-table-column>
</t-table>
<!-- 分页 -->
<t-pager :total="total" :current="page" :page-size="limit" show-elevator class="pager" @on-change="onChange"></t-pager>
<!-- 模态框-->
<t-modal :visibled.sync="details_modal" :title="clickdetail==0?'报警详情':'报警处理'" width="732px">
<div style="text-align:center">
<div class="details_item1">
<div class="detail">
<label class="detail_title">状态:</label>
<div class="detail_content">
<t-tag v-if="alarmDetailData.statusZh==='未确认'" state="warning">未确认</t-tag>
<t-tag v-if="alarmDetailData.statusZh==='已处理'" state="success">已处理</t-tag>
<t-tag v-if="alarmDetailData.statusZh==='处理中'" state="info">处理中</t-tag>
<t-tag v-if="alarmDetailData.statusZh==='误报'" state="danger">误报</t-tag>
</div>
</div>
<div class="detail">
<label class="detail_title">报警类型:</label>
<div class="detail_content">{{ alarmDetailData.alarmTypeCodeZh || '' }}</div>
</div>
<div class="detail">
<label class="detail_title">报警描述:</label>
<div class="detail_content">{{ alarmDetailData.alarmMemo }}</div>
</div>
<div class="detail">
<label class="detail_title">报警时间:</label>
<div class="detail_content">{{ alarmDetailData.aiIdenTime|formatDateTime }}</div>
</div>
<div class="detail">
<label class="detail_title">设备编号:</label>
<div class="detail_content">{{ alarmDetailData.resourceToolCode ||'暂无编号' }}</div>
</div>
<div class="detail">
<label class="detail_title">设备位置:</label>
<div class="detail_content">{{ alarmDetailData.monitorSceneName }}</div>
</div>
<div class="detail">
<label class="detail_title">处理人:</label>
<div class="detail_content">{{ alarmDetailData.workEmployeeRoleName|| '--' }}</div>
</div>
<div class="detail">
<label class="detail_title">处理时间:</label>
<div>{{ alarmDetailData.disposeDate || '--' }}</div>
</div>
</div>
<div class="details_item2">
<div>
<div>识别图片</div>
<div><img :src="pictureDetailData.fileUrl" alt="" srcset="" style="width:100%;height:100%"></div>
</div>
<div>
<div>识别视频</div>
<div class="video">
<!-- <video :src="videoDetailData.videoFileUrl" class="video" controls></video> -->
<video-player ref="videoPlayer" :playsinline="true" :options="playerOptions" class="video-player vjs-custom-skin"></video-player>
</div>
</div>
</div>
<div v-if="clickdetail==1">
<div v-if="alarmDetailData.status!='END'" class="radio">
<div>报警处理 : </div>
<div v-if="alarmDetailData.status=='INI'">
<t-radio-group v-model="status">
<t-radio label="RUN">
<span>确认</span>
</t-radio>
<t-radio label="FAL">
<span>误判</span>
</t-radio>
</t-radio-group>
</div>
<div v-if="alarmDetailData.status=='RUN'||alarmDetailData.status=='FAL'">
<t-radio-group v-model="status">
<t-radio label="END">关闭</t-radio>
</t-radio-group>
</div>
</div>
</div>
</div>
<div slot="footer">
<div v-if="clickdetail==1">
<div>
<t-button @click="details_modal=false">取消</t-button>
<t-button :loading="loading" color="primary" @click="confimclick">确认</t-button>
</div>
</div>
<div v-else>
<t-button type="danger" long @click="details_modal=false">关闭</t-button>
</div>
</div>
</t-modal>
</div>
</template>
<script>
import aialarmapi from '@/api/aialarm'
import formatDateTime from '@/utils/formatDateTime.js'
export default {
filters: {
formatDateTime
},
data () {
return {
slideVisible: false,
indeterminate: true,
checkAll: true,
social: ['状态', '报警类型', '报警描述', '设备名称', '设备编号', '设备位置', '报警时间', '处理人', '处理时间'],
columns: [
{
label: '状态',
show: true
}, {
label: '报警类型',
show: true
}, {
label: '报警描述',
show: true
}, {
label: '设备名称',
show: true
}, {
label: '设备编号',
show: true
}, {
label: '设备位置',
show: true
}, {
label: '报警时间',
show: true
}, {
label: '处理人',
show: true
}, {
label: '处理时间',
show: true
}
],
customVisibled: false,
searchdata: {
alarmTypeCode: '', // 报警类型
beginTime: '', // 开始时间
endTime: '' // 结束时间
},
// 报警类型
alarmtypelist: [],
// 报警人
aialarmhandlerlist: [],
// 模态框中的单选按钮
status: '',
// 模态框
details_modal: false,
// 当前行的数据
currentdata: {
index: '',
data: {}
},
// 报警详情数据
alarmDetailData: {},
// 图片详情数据
pictureDetailData: {},
// 视频详情数据
videoDetailData: {},
// 选择的数据
selectdata: [],
// 判断是详情还是处理
clickdetail: 0,
// 一页的数据
data: [],
// 页数
page: 1,
limit: 10,
total: 0,
loading: false,
playerOptions: {
playbackRates: [0.7, 1.0, 1.5, 2.0], // 播放速度
autoplay: true, // 如果true,浏览器准备好时开始回放。
muted: true, // 默认情况下将会消除任何音频。
loop: false, // 导致视频一结束就重新开始。
preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
language: 'zh-CN',
aspectRatio: '13:10', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
// fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
// 是否流体自适应容器宽高
fluid: true,
// // 设置视频播放器的显示宽度(以像素为单位)
// width: '100px',
// // 设置视频播放器的显示高度(以像素为单位)
// height: '300px',
sources: [{
type: 'application/x-mpegURL', // 这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目
src: '' // url地址
}],
notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
controlBar: {
timeDivider: true,
// durationDisplay: true,
remainingTimeDisplay: false,
fullscreenToggle: true, // 全屏按钮,
pictureInPictureToggle: false
}
}
}
},
mounted () {
this.gettype()
this.search()
},
methods: {
checkAllGroupChange () {
if (this.social.length === 9) {
this.indeterminate = false
this.checkAll = true
} else if (this.social.length > 0) {
this.indeterminate = true
this.checkAll = false
} else {
this.indeterminate = false
this.checkAll = false
}
},
handleCheckAll () {
if (this.indeterminate) {
this.checkAll = false
} else {
this.checkAll = !this.checkAll
}
this.indeterminate = false
if (this.checkAll) {
this.social = ['状态', '报警类型', '报警描述', '设备名称', '设备编号', '设备位置', '报警时间', '处理人', '处理时间']
} else {
this.social = []
}
},
onTriggerClick () {
this.customVisibled = true
},
onCloseClick () {
this.columns.forEach(e => {
e.show = this.social.indexOf(e.label) >= 0
})
this.customVisibled = false
},
// 选择行
handleSelectionChange (val) {
// console.log(val)
this.selectdata = val
},
// 点击详情
async handleClick (scope, val) {
this.clickdetail = val
// 去除模态框中的单选项
let res = await aialarmapi.getAlarmDetail({ params: { 'workTaskId': scope.row.workTaskId } })
if (res.status === 200) {
console.log(res.data.data)
this.alarmDetailData = res.data.data.alarmInfo
this.pictureDetailData = res.data.data.pictureInfo
this.playerOptions.sources[0].src = res.data.data.videoInfo || ''
// console.log(this.playerOptions.sources[0].src)
} else { this.$Message.danger('处理失败') }
this.status = ''
this.details_modal = true // 打开模态框
// this.currentdata.data = scope.row // 获取当前行的数据
this.currentdata.index = scope.$index // 获取当前行的索引
},
// 未确认状态的模态框的确认按钮 || 处理中状态的模态框的确认按钮
confimclick () {
this.loading = true
// 获取单选框中的值
// console.log(this.msg)
// 判断是否选择了单选框
if (this.status) {
// 向后端发送数据
this.alarmdispose(this.alarmDetailData.workTaskId, this.status)
// console.log(this.status)
} else {
this.$Message.warning('请选择按钮')
this.loading = false
}
},
async alarmdispose (id, status, processMemo) {
const dict = { 'END': '已解决', 'RUN': '处理中', 'FAL': '误报' }
// console.log(id, status, dict[status])
var res = await aialarmapi.dispose({ 'workTaskId': id, 'status': status, 'processMemo': dict.status })
if (res.status === 200) {
this.$Message.success('操作成功')
this.search()
this.loading = false
// 关闭模态框
this.details_modal = false
this.$store.commit('alarm/add', 1)
// this.data[this.currentdata.index].status = res.data.data.status
// if (res.data.data.status === 'END') {
// this.data[this.currentdata.index].processTime = res.data.data.doneDate
// }
} else {
this.$Message.danger('处理失败')
}
},
onChange (val) {
// console.log(val)
this.page = val
this.search()
},
// 点击查询按钮
btnsearch () {
if (this.page === 1) {
this.search()
} else {
this.page = 1
}
},
// 获取报警类型
async gettype () {
var res = await aialarmapi.getAiAlarmType()
// console.log(res)
if (res.status === 200) {
// this.alarmtypelist = res.data.data
// console.log(this.alarmtypelist)
// console.log(res.data)
this.alarmtypelist = res.data
}
},
// 查询数据时
async search () {
var flag = this.startreend(this.searchdata.beginTime, this.searchdata.endTime)
// console.log(flag)
if (flag) {
// 查询
var params = this.searchdata
params.pageNumber = this.page
params.pageSize = this.limit
var res = await aialarmapi.getAiAlarmList({
params: params
})
// console.log(res)
if (res.status === 200) {
this.data = res.data.data.data
this.data = this.data.map((item) => { item.aiIdenTime = formatDateTime(item.aiIdenTime); return item })
console.log(this.data)
console.log('数据是', res)
// this.total = Math.ceil(res.data.data.total / res.data.data.size) * 5
this.total = res.data.data.total
} else {
this.$Message.danger('数据获取失败')
}
} else {
this.$Message.danger('开始时间不能在结束时间的后面')
}
},
// 重置
reset () {
for (var index in this.searchdata) {
this.searchdata[index] = ''
}
// console.log(this.searchdata)
this.page = 1
this.$Message.success('数据重置成功')
},
// 字符串更改为时间类型
stringtodate (date) {
date = date.substring(0, 19)
date = date.replace(/-/g, '/')
var timestamp = new Date(date).getTime()
return timestamp
},
// 验证开始时间·和结束时间
startreend (startdate, enddate) {
startdate = this.stringtodate(startdate)
enddate = this.stringtodate(enddate)
if (startdate > enddate) {
return false
} else {
return true
}
},
date_formatter (row, column, cellValue, index) {
if (cellValue === '' || cellValue === null) {
return '-'
} else {
return cellValue
}
}
}
}
</script>
<style lang='scss' >
.ai_alarm {
font-size: 14px;
padding: 6px 24px;
.upload {
font-size: 14px;
line-height: 22px;
}
.caozuo {
display: inline;
}
.table th,
.table td {
padding: 0 0 0 21px;
}
.track-container {
width: 100%;
margin: 24px 0;
// padding: 20px;
box-sizing: border-box;
.search-container {
width: 100%;
.search-ctn {
width: 100%;
overflow: hidden;
margin: 0;
padding: 0;
display: flex;
position: relative;
> div {
// margin: 0 20px 16px 0;
line-height: 2;
}
.btns {
margin-left: auto;
display: block;
button {
margin: 0 2px;
}
}
}
}
.table-pager {
margin: 20px auto;
}
.allCondition {
display: flex;
justify-content: space-between;
border: 1px solid rgba(0, 0, 0, 0.09);
background-color: #f8f9fa;
flex-wrap: nowrap;
align-items: center;
padding: 20px;
margin: 5px auto;
.input-rule {
flex: 1;
padding: 10px 0 10px 20px;
}
}
}
}
.pager {
float: right;
margin-top: 26px;
}
.details_item1 {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
height: 192px;
align-items: center;
border-radius: 4px;
background-color: rgba(245, 245, 245, 1);
padding: 0 16px;
color: rgba(0, 0, 0, 0.45);
font-size: 14px;
.detail {
width: 49%;
display: flex;
.detail_title {
display: block;
width: 70px;
height: 22px;
text-align: right;
}
.detail_content {
flex: 1;
text-align: left;
}
}
}
.details_item2 {
display: flex;
justify-content: space-between;
margin-top: 24px;
> div {
width: 49%;
> div:nth-child(1) {
text-align: left;
font-size: 14px;
color: rgba(0, 0, 0, 0.65);
margin-bottom: 8px;
}
> div:nth-child(2) {
height: 250px;
// border: 1px solid black;
border-radius: 5px;
overflow: hidden;
}
}
}
.radio {
margin-top: 19px;
float: left;
display: flex;
align-items: center;
> div:nth-child(1) {
margin-right: 5px;
}
}
.video {
width: 100%;
height: 100%;
margin: 0 auto;
}
</style>
|