Commit d07a5680f3f25a9898a1d465d785f6c595a21005
1 parent
e0028a87
为推流列表增加批量移除功能
Showing
11 changed files
with
143 additions
and
20 deletions
src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java
| ... | ... | @@ -43,4 +43,5 @@ public interface IGbStreamService { |
| 43 | 43 | DeviceChannel getDeviceChannelListByStream(GbStream gbStream, String catalogId, String deviceGBId); |
| 44 | 44 | |
| 45 | 45 | void sendCatalogMsg(GbStream gbStream, String type); |
| 46 | + void sendCatalogMsgs(List<GbStream> gbStreams, String type); | |
| 46 | 47 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java
src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
| ... | ... | @@ -20,6 +20,7 @@ import org.springframework.jdbc.datasource.DataSourceTransactionManager; |
| 20 | 20 | import org.springframework.stereotype.Service; |
| 21 | 21 | import org.springframework.transaction.TransactionDefinition; |
| 22 | 22 | import org.springframework.transaction.TransactionStatus; |
| 23 | +import org.springframework.util.StringUtils; | |
| 23 | 24 | |
| 24 | 25 | import java.util.ArrayList; |
| 25 | 26 | import java.util.List; |
| ... | ... | @@ -144,8 +145,16 @@ public class GbStreamServiceImpl implements IGbStreamService { |
| 144 | 145 | gbStreams.add(streamProxyItem); |
| 145 | 146 | } |
| 146 | 147 | } |
| 148 | + sendCatalogMsgs(gbStreams, type); | |
| 149 | + } | |
| 150 | + | |
| 151 | + @Override | |
| 152 | + public void sendCatalogMsgs(List<GbStream> gbStreams, String type) { | |
| 147 | 153 | if (gbStreams.size() > 0) { |
| 148 | 154 | for (GbStream gs : gbStreams) { |
| 155 | + if (StringUtils.isEmpty(gs.getGbId())){ | |
| 156 | + continue; | |
| 157 | + } | |
| 149 | 158 | List<ParentPlatform> parentPlatforms = platformGbStreamMapper.selectByAppAndStream(gs.getApp(), gs.getStream()); |
| 150 | 159 | if (parentPlatforms.size() > 0) { |
| 151 | 160 | for (ParentPlatform parentPlatform : parentPlatforms) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
| ... | ... | @@ -355,8 +355,26 @@ public class StreamPushServiceImpl implements IStreamPushService { |
| 355 | 355 | } |
| 356 | 356 | } |
| 357 | 357 | } |
| 358 | + } | |
| 359 | + } | |
| 360 | + | |
| 361 | + @Override | |
| 362 | + public boolean batchStop(List<GbStream> gbStreams) { | |
| 363 | + if (gbStreams == null || gbStreams.size() == 0) { | |
| 364 | + return false; | |
| 365 | + } | |
| 366 | + gbStreamService.sendCatalogMsgs(gbStreams, CatalogEvent.DEL); | |
| 358 | 367 | |
| 368 | + int delStream = streamPushMapper.delAllForGbStream(gbStreams); | |
| 369 | + gbStreamMapper.batchDelForGbStream(gbStreams); | |
| 370 | + platformGbStreamMapper.delByGbStreams(gbStreams); | |
| 371 | + if (delStream > 0) { | |
| 372 | + for (GbStream gbStream : gbStreams) { | |
| 373 | + MediaServerItem mediaServerItem = mediaServerService.getOne(gbStream.getMediaServerId()); | |
| 374 | + zlmresTfulUtils.closeStreams(mediaServerItem, gbStream.getApp(), gbStream.getStream()); | |
| 375 | + } | |
| 359 | 376 | |
| 360 | 377 | } |
| 378 | + return true; | |
| 361 | 379 | } |
| 362 | 380 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
| ... | ... | @@ -84,6 +84,14 @@ public interface GbStreamMapper { |
| 84 | 84 | "</script>") |
| 85 | 85 | void batchDel(List<StreamProxyItem> streamProxyItemList); |
| 86 | 86 | |
| 87 | + @Delete("<script> "+ | |
| 88 | + "DELETE FROM gb_stream where " + | |
| 89 | + "<foreach collection='gbStreams' item='item' separator='or'>" + | |
| 90 | + "(app=#{item.app} and stream=#{item.stream}) " + | |
| 91 | + "</foreach>" + | |
| 92 | + "</script>") | |
| 93 | + void batchDelForGbStream(List<GbStream> gbStreams); | |
| 94 | + | |
| 87 | 95 | @Insert("<script> " + |
| 88 | 96 | "REPLACE into gb_stream " + |
| 89 | 97 | "(app, stream, gbId, name, " + | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformGbStreamMapper.java
| ... | ... | @@ -74,4 +74,12 @@ public interface PlatformGbStreamMapper { |
| 74 | 74 | |
| 75 | 75 | @Delete("DELETE FROM platform_gb_stream WHERE app=#{app} AND stream=#{stream} AND platformId=#{platformId}") |
| 76 | 76 | int delByAppAndStreamAndPlatform(String app, String stream, String platformId); |
| 77 | + | |
| 78 | + @Delete("<script> "+ | |
| 79 | + "DELETE FROM platform_gb_stream where " + | |
| 80 | + "<foreach collection='gbStreams' item='item' separator='or'>" + | |
| 81 | + "(app=#{item.app} and stream=#{item.stream}) " + | |
| 82 | + "</foreach>" + | |
| 83 | + "</script>") | |
| 84 | + void delByGbStreams(List<GbStream> gbStreams); | |
| 77 | 85 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java
| 1 | 1 | package com.genersoft.iot.vmp.storager.dao; |
| 2 | 2 | |
| 3 | +import com.genersoft.iot.vmp.gb28181.bean.GbStream; | |
| 3 | 4 | import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; |
| 4 | 5 | import org.apache.ibatis.annotations.*; |
| 5 | 6 | import org.springframework.stereotype.Repository; |
| ... | ... | @@ -48,7 +49,13 @@ public interface StreamPushMapper { |
| 48 | 49 | "</script>") |
| 49 | 50 | int delAll(List<StreamPushItem> streamPushItems); |
| 50 | 51 | |
| 51 | - | |
| 52 | + @Delete("<script> "+ | |
| 53 | + "DELETE FROM stream_push where " + | |
| 54 | + "<foreach collection='gbStreams' item='item' separator='or'>" + | |
| 55 | + "(app=#{item.app} and stream=#{item.stream}) " + | |
| 56 | + "</foreach>" + | |
| 57 | + "</script>") | |
| 58 | + int delAllForGbStream(List<GbStream> gbStreams); | |
| 52 | 59 | |
| 53 | 60 | |
| 54 | 61 | @Select(value = {" <script>" + | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/bean/BatchGBStreamParam.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.vmanager.bean; | |
| 2 | + | |
| 3 | +import com.genersoft.iot.vmp.gb28181.bean.GbStream; | |
| 4 | + | |
| 5 | +import java.util.List; | |
| 6 | + | |
| 7 | +public class BatchGBStreamParam { | |
| 8 | + private List<GbStream> gbStreams; | |
| 9 | + | |
| 10 | + public List<GbStream> getGbStreams() { | |
| 11 | + return gbStreams; | |
| 12 | + } | |
| 13 | + | |
| 14 | + public void setGbStreams(List<GbStream> gbStreams) { | |
| 15 | + this.gbStreams = gbStreams; | |
| 16 | + } | |
| 17 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java
| ... | ... | @@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; |
| 10 | 10 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 11 | 11 | import com.genersoft.iot.vmp.service.IStreamPushService; |
| 12 | 12 | import com.genersoft.iot.vmp.service.impl.StreamPushUploadFileHandler; |
| 13 | +import com.genersoft.iot.vmp.vmanager.bean.BatchGBStreamParam; | |
| 13 | 14 | import com.genersoft.iot.vmp.vmanager.bean.StreamPushExcelDto; |
| 14 | 15 | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; |
| 15 | 16 | import com.github.pagehelper.PageInfo; |
| ... | ... | @@ -116,13 +117,32 @@ public class StreamPushController { |
| 116 | 117 | }) |
| 117 | 118 | @PostMapping(value = "/stop") |
| 118 | 119 | @ResponseBody |
| 119 | - public Object removeFormGB(@RequestParam(required = true)String app, @RequestParam(required = true)String streamId){ | |
| 120 | + public Object stop(String app, String streamId){ | |
| 120 | 121 | if (streamPushService.stop(app, streamId)){ |
| 121 | 122 | return "success"; |
| 122 | 123 | }else { |
| 123 | 124 | return "fail"; |
| 124 | 125 | } |
| 125 | 126 | } |
| 127 | + | |
| 128 | + @ApiOperation("中止多个推流") | |
| 129 | + @ApiImplicitParams({ | |
| 130 | + @ApiImplicitParam(name = "app", value = "应用名", required = true, dataTypeClass = String.class), | |
| 131 | + @ApiImplicitParam(name = "streamId", value = "流ID", required = true, dataTypeClass = String.class), | |
| 132 | + }) | |
| 133 | + @DeleteMapping(value = "/batchStop") | |
| 134 | + @ResponseBody | |
| 135 | + public Object batchStop(@RequestBody BatchGBStreamParam batchGBStreamParam){ | |
| 136 | + if (batchGBStreamParam.getGbStreams().size() == 0) { | |
| 137 | + return "fail"; | |
| 138 | + } | |
| 139 | + if (streamPushService.batchStop(batchGBStreamParam.getGbStreams())){ | |
| 140 | + return "success"; | |
| 141 | + }else { | |
| 142 | + return "fail"; | |
| 143 | + } | |
| 144 | + } | |
| 145 | + | |
| 126 | 146 | @PostMapping(value = "upload") |
| 127 | 147 | @ResponseBody |
| 128 | 148 | public DeferredResult<ResponseEntity<WVPResult<Object>>> uploadChannelFile(@RequestParam(value = "file") MultipartFile file){ | ... | ... |
web_src/src/components/PushVideoList.vue
| ... | ... | @@ -30,10 +30,17 @@ |
| 30 | 30 | <el-button icon="el-icon-download" size="mini" style="margin-right: 1rem;" type="primary" > |
| 31 | 31 | <a style="color: #FFFFFF; text-align: center; text-decoration: none" href="/static/file/推流通道导入.zip" download='推流通道导入.zip' >下载模板</a> |
| 32 | 32 | </el-button> |
| 33 | + <el-button icon="el-icon-delete" size="mini" style="margin-right: 1rem;" :disabled="multipleSelection.length === 0" type="danger" @click="batchDel">批量移除</el-button> | |
| 33 | 34 | </div> |
| 34 | 35 | <devicePlayer ref="devicePlayer"></devicePlayer> |
| 35 | 36 | <addStreamTOGB ref="addStreamTOGB"></addStreamTOGB> |
| 36 | - <el-table :data="pushList" border style="width: 100%" :height="winHeight"> | |
| 37 | + <el-table ref="pushListTable" :data="pushList" border style="width: 100%" :height="winHeight" @selection-change="handleSelectionChange" :row-key="(row)=> row.app + row.stream"> | |
| 38 | + <el-table-column | |
| 39 | + align="center" | |
| 40 | + type="selection" | |
| 41 | + :reserve-selection="true" | |
| 42 | + width="55"> | |
| 43 | + </el-table-column> | |
| 37 | 44 | <el-table-column prop="name" label="名称" width="180" align="center"> |
| 38 | 45 | </el-table-column> |
| 39 | 46 | <el-table-column prop="app" label="APP" width="180" align="center"> |
| ... | ... | @@ -60,8 +67,8 @@ |
| 60 | 67 | <el-table-column label="操作" width="360" align="center" fixed="right"> |
| 61 | 68 | <template slot-scope="scope"> |
| 62 | 69 | <el-button-group> |
| 63 | - <el-button size="mini" icon="el-icon-video-play" v-if="(scope.row.status == false && scope.row.gbId == null) || scope.row.status" @click="playPuhsh(scope.row)">播放</el-button> | |
| 64 | - <el-button size="mini" icon="el-icon-switch-button" type="danger" @click="stopPuhsh(scope.row)">移除</el-button> | |
| 70 | + <el-button size="mini" icon="el-icon-video-play" v-if="(scope.row.status == false && scope.row.gbId == null) || scope.row.status" @click="playPush(scope.row)">播放</el-button> | |
| 71 | + <el-button size="mini" icon="el-icon-delete" type="danger" @click="stopPush(scope.row)">移除</el-button> | |
| 65 | 72 | <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!!scope.row.gbId" @click="addToGB(scope.row)">加入国标</el-button> |
| 66 | 73 | <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!scope.row.gbId" @click="removeFromGB(scope.row)">移出国标</el-button> |
| 67 | 74 | </el-button-group> |
| ... | ... | @@ -107,7 +114,7 @@ |
| 107 | 114 | currentPusher: {}, //当前操作设备对象 |
| 108 | 115 | updateLooper: 0, //数据刷新轮训标志 |
| 109 | 116 | currentDeviceChannelsLenth:0, |
| 110 | - winHeight: window.innerHeight - 200, | |
| 117 | + winHeight: window.innerHeight - 250, | |
| 111 | 118 | mediaServerObj : new MediaServer(), |
| 112 | 119 | currentPage:1, |
| 113 | 120 | count:15, |
| ... | ... | @@ -116,6 +123,7 @@ |
| 116 | 123 | pushing: "", |
| 117 | 124 | mediaServerId: "", |
| 118 | 125 | mediaServerList: [], |
| 126 | + multipleSelection: [], | |
| 119 | 127 | getDeviceListLoading: false |
| 120 | 128 | }; |
| 121 | 129 | }, |
| ... | ... | @@ -123,7 +131,7 @@ |
| 123 | 131 | }, |
| 124 | 132 | mounted() { |
| 125 | 133 | this.initData(); |
| 126 | - this.updateLooper = setInterval(this.initData, 2000); | |
| 134 | + this.updateLooper = setInterval(this.getPushList, 2000); | |
| 127 | 135 | }, |
| 128 | 136 | destroyed() { |
| 129 | 137 | clearTimeout(this.updateLooper); |
| ... | ... | @@ -131,7 +139,6 @@ |
| 131 | 139 | methods: { |
| 132 | 140 | initData: function() { |
| 133 | 141 | this.mediaServerObj.getOnlineMediaServerList((data)=>{ |
| 134 | - console.log(data) | |
| 135 | 142 | this.mediaServerList = data.data; |
| 136 | 143 | }) |
| 137 | 144 | this.getPushList(); |
| ... | ... | @@ -162,12 +169,12 @@ |
| 162 | 169 | that.pushList = res.data.list; |
| 163 | 170 | that.getDeviceListLoading = false; |
| 164 | 171 | }).catch(function (error) { |
| 165 | - console.log(error); | |
| 172 | + console.error(error); | |
| 166 | 173 | that.getDeviceListLoading = false; |
| 167 | 174 | }); |
| 168 | 175 | }, |
| 169 | 176 | |
| 170 | - playPuhsh: function(row){ | |
| 177 | + playPush: function(row){ | |
| 171 | 178 | let that = this; |
| 172 | 179 | this.getListLoading = true; |
| 173 | 180 | this.$axios({ |
| ... | ... | @@ -185,12 +192,12 @@ |
| 185 | 192 | hasAudio: true |
| 186 | 193 | }); |
| 187 | 194 | }).catch(function (error) { |
| 188 | - console.log(error); | |
| 195 | + console.error(error); | |
| 189 | 196 | that.getListLoading = false; |
| 190 | 197 | }); |
| 191 | 198 | }, |
| 192 | - stopPuhsh: function(row){ | |
| 193 | - var that = this; | |
| 199 | + stopPush: function(row){ | |
| 200 | + let that = this; | |
| 194 | 201 | that.$axios({ |
| 195 | 202 | method:"post", |
| 196 | 203 | url:"/api/push/stop", |
| ... | ... | @@ -203,14 +210,14 @@ |
| 203 | 210 | that.initData() |
| 204 | 211 | } |
| 205 | 212 | }).catch(function (error) { |
| 206 | - console.log(error); | |
| 213 | + console.error(error); | |
| 207 | 214 | }); |
| 208 | 215 | }, |
| 209 | 216 | addToGB: function(row){ |
| 210 | 217 | this.$refs.addStreamTOGB.openDialog({app: row.app, stream: row.stream, mediaServerId: row.mediaServerId}, this.initData); |
| 211 | 218 | }, |
| 212 | 219 | removeFromGB: function(row){ |
| 213 | - var that = this; | |
| 220 | + let that = this; | |
| 214 | 221 | that.$axios({ |
| 215 | 222 | method:"delete", |
| 216 | 223 | url:"/api/push/remove_form_gb", |
| ... | ... | @@ -220,12 +227,12 @@ |
| 220 | 227 | that.initData() |
| 221 | 228 | } |
| 222 | 229 | }).catch(function (error) { |
| 223 | - console.log(error); | |
| 230 | + console.error(error); | |
| 224 | 231 | }); |
| 225 | 232 | }, |
| 226 | 233 | dateFormat: function(/** timestamp=0 **/) { |
| 227 | - var ts = arguments[0] || 0; | |
| 228 | - var t,y,m,d,h,i,s; | |
| 234 | + let ts = arguments[0] || 0; | |
| 235 | + let t,y,m,d,h,i,s; | |
| 229 | 236 | t = ts ? new Date(ts*1000) : new Date(); |
| 230 | 237 | y = t.getFullYear(); |
| 231 | 238 | m = t.getMonth()+1; |
| ... | ... | @@ -241,6 +248,32 @@ |
| 241 | 248 | |
| 242 | 249 | }) |
| 243 | 250 | }, |
| 251 | + batchDel: function () { | |
| 252 | + this.$confirm(`确定删除选中的${this.multipleSelection.length}个通道?`, '提示', { | |
| 253 | + confirmButtonText: '确定', | |
| 254 | + cancelButtonText: '取消', | |
| 255 | + type: 'warning' | |
| 256 | + }).then(() => { | |
| 257 | + let that = this; | |
| 258 | + that.$axios({ | |
| 259 | + method:"delete", | |
| 260 | + url:"/api/push/batchStop", | |
| 261 | + data: { | |
| 262 | + gbStreams: this.multipleSelection | |
| 263 | + } | |
| 264 | + }).then((res)=>{ | |
| 265 | + this.initData(); | |
| 266 | + this.$refs.pushListTable.clearSelection(); | |
| 267 | + }).catch(function (error) { | |
| 268 | + console.error(error); | |
| 269 | + }); | |
| 270 | + }).catch(() => { | |
| 271 | + | |
| 272 | + }); | |
| 273 | + }, | |
| 274 | + handleSelectionChange: function (val) { | |
| 275 | + this.multipleSelection = val; | |
| 276 | + }, | |
| 244 | 277 | } |
| 245 | 278 | }; |
| 246 | 279 | </script> | ... | ... |
web_src/src/components/dialog/importChannel.vue
| ... | ... | @@ -45,8 +45,8 @@ export default { |
| 45 | 45 | showDialog: false, |
| 46 | 46 | isLoging: false, |
| 47 | 47 | isEdit: false, |
| 48 | - errorStreams: null, | |
| 49 | - errorGBIds: null, | |
| 48 | + errorStreams: [], | |
| 49 | + errorGBIds: [], | |
| 50 | 50 | uploadUrl: process.env.NODE_ENV === 'development'?`debug/api/push/upload`:`api/push/upload`, |
| 51 | 51 | }; |
| 52 | 52 | }, | ... | ... |