ebc

index.vue 22KB

    <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>