1.重构全局页面结构,从之前每个页面独立绘制改为路由嵌套
2.全局页面样式优化,如滚动条、标题栏等
| | |
| | | <template> |
| | | <div id="app"> |
| | | <el-container> |
| | | <el-header> |
| | | <uiHeader></uiHeader> |
| | | </el-header> |
| | | <el-main> |
| | | <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;"> |
| | | <span v-if="!recordDetail" >云端录像</span> |
| | | <el-page-header v-if="recordDetail" @back="backToList" content="云端录像"> |
| | | </el-page-header> |
| | | <div style="position: absolute; right: 5rem; top: 0.3rem;"> |
| | | 节点选择: |
| | | <el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServerId" placeholder="请选择" :disabled="recordDetail"> |
| | | <el-option |
| | | v-for="item in mediaServerList" |
| | | :key="item.id" |
| | | :label="item.id" |
| | | :value="item.id"> |
| | | </el-option> |
| | | </el-select> |
| | | </div> |
| | | <div style="position: absolute; right: 1rem; top: 0.3rem;"> |
| | | <el-button v-if="!recordDetail" icon="el-icon-refresh-right" circle size="mini" :loading="loading" @click="getRecordList()"></el-button> |
| | | </div> |
| | | </div> |
| | | <div v-if="!recordDetail"> |
| | | <div id="app" style="width: 100%"> |
| | | <div class="page-header"> |
| | | <div class="page-title">云端录像</div> |
| | | <div class="page-header-btn"> |
| | | 节点选择: |
| | | <el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServerId" placeholder="请选择" :disabled="recordDetail"> |
| | | <el-option |
| | | v-for="item in mediaServerList" |
| | | :key="item.id" |
| | | :label="item.id" |
| | | :value="item.id"> |
| | | </el-option> |
| | | </el-select> |
| | | <el-button v-if="!recordDetail" icon="el-icon-refresh-right" circle size="mini" :loading="loading" @click="getRecordList()"></el-button> |
| | | </div> |
| | | </div> |
| | | <div v-if="!recordDetail"> |
| | | |
| | | <!--设备列表--> |
| | | <el-table :data="recordList" border style="width: 100%" :height="winHeight"> |
| | | <el-table-column prop="app" label="应用名" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="stream" label="流ID" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="time" label="时间" align="center"> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="360" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button-group> |
| | | <el-button size="mini" icon="el-icon-video-camera-solid" type="primary" @click="showRecordDetail(scope.row)">查看</el-button> |
| | | <!-- <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteRecord(scope.row)">删除</el-button>--> |
| | | </el-button-group> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination |
| | | style="float: right" |
| | | @size-change="handleSizeChange" |
| | | @current-change="currentChange" |
| | | :current-page="currentPage" |
| | | :page-size="count" |
| | | :page-sizes="[15, 25, 35, 50]" |
| | | layout="total, sizes, prev, pager, next" |
| | | :total="total"> |
| | | </el-pagination> |
| | | </div> |
| | | <cloud-record-detail ref="cloudRecordDetail" v-if="recordDetail" :recordFile="chooseRecord" :mediaServerId="mediaServerId" :mediaServerPath="mediaServerPath" ></cloud-record-detail> |
| | | </el-main> |
| | | </el-container> |
| | | </div> |
| | | <!--设备列表--> |
| | | <el-table :data="recordList" border style="width: 100%" :height="winHeight"> |
| | | <el-table-column prop="app" label="应用名" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="stream" label="流ID" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="time" label="时间" align="center"> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="360" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button-group> |
| | | <el-button size="mini" icon="el-icon-video-camera-solid" type="primary" @click="showRecordDetail(scope.row)">查看</el-button> |
| | | <!-- <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteRecord(scope.row)">删除</el-button>--> |
| | | </el-button-group> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination |
| | | style="float: right" |
| | | @size-change="handleSizeChange" |
| | | @current-change="currentChange" |
| | | :current-page="currentPage" |
| | | :page-size="count" |
| | | :page-sizes="[15, 25, 35, 50]" |
| | | layout="total, sizes, prev, pager, next" |
| | | :total="total"> |
| | | </el-pagination> |
| | | </div> |
| | | <cloud-record-detail ref="cloudRecordDetail" v-if="recordDetail" :recordFile="chooseRecord" :mediaServerId="mediaServerId" :mediaServerPath="mediaServerPath" ></cloud-record-detail> |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import uiHeader from './UiHeader.vue' |
| | | import uiHeader from '../layout/UiHeader.vue' |
| | | import cloudRecordDetail from './CloudRecordDetail.vue' |
| | | import MediaServer from './service/MediaServer' |
| | | export default { |
| | |
| | | |
| | | <script> |
| | | // TODO 根据查询的时间列表设置滑轨的最大值与最小值, |
| | | import uiHeader from './UiHeader.vue' |
| | | import uiHeader from '../layout/UiHeader.vue' |
| | | import player from './dialog/easyPlayer.vue' |
| | | import moment from 'moment' |
| | | export default { |
| | |
| | | <template> |
| | | <div id="app"> |
| | | <el-container> |
| | | <el-header> |
| | | <uiHeader></uiHeader> |
| | | </el-header> |
| | | <el-main> |
| | | <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;"> |
| | | <span style="font-size: 1rem; font-weight: bold;">设备列表</span> |
| | | <div style="position: absolute; right: 1rem; top: 0.3rem;"> |
| | | <el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading" @click="getDeviceList()"></el-button> |
| | | </div> |
| | | </div> |
| | | <!-- <devicePlayer ref="devicePlayer"></devicePlayer> --> |
| | | <!--设备列表--> |
| | | <el-table :data="deviceList" border style="width: 100%;font-size: 12px;" :height="winHeight"> |
| | | <el-table-column prop="name" label="名称" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceId" label="设备编号" width="180" align="center"> |
| | | </el-table-column> |
| | | <el-table-column label="地址" width="180" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium">{{ scope.row.hostAddress }}</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="manufacturer" label="厂家" align="center"> |
| | | </el-table-column> |
| | | <el-table-column label="流传输模式" align="center" width="120"> |
| | | <template slot-scope="scope"> |
| | | <el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择"> |
| | | <el-option key="UDP" label="UDP" value="UDP"></el-option> |
| | | <el-option key="TCP-ACTIVE" label="TCP主动模式" :disabled="true" value="TCP-ACTIVE"></el-option> |
| | | <el-option key="TCP-PASSIVE" label="TCP被动模式" value="TCP-PASSIVE"></el-option> |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="channelCount" label="通道数" align="center"> |
| | | </el-table-column> |
| | | <el-table-column label="状态" width="120" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.online == 1">在线</el-tag> |
| | | <el-tag size="medium" type="info" v-if="scope.row.online == 0">离线</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="keepaliveTime" label="最近心跳" align="center" width="140"> |
| | | </el-table-column> |
| | | <el-table-column prop="registerTime" label="最近注册" align="center" width="140"> |
| | | </el-table-column> |
| | | <el-table-column prop="updateTime" label="更新时间" align="center" width="140"> |
| | | </el-table-column> |
| | | <el-table-column prop="createTime" label="创建时间" align="center" width="140"> |
| | | </el-table-column> |
| | | <div id="app" style="width: 100%"> |
| | | <div class="page-header"> |
| | | <div class="page-title">设备列表</div> |
| | | <div class="page-header-btn"> |
| | | <el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading" |
| | | @click="getDeviceList()"></el-button> |
| | | </div> |
| | | </div> |
| | | <!-- <devicePlayer ref="devicePlayer"></devicePlayer> --> |
| | | <!--设备列表--> |
| | | <el-table :data="deviceList" border style="width: 100%;font-size: 12px;" :height="winHeight"> |
| | | <el-table-column prop="name" label="名称" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceId" label="设备编号" width="180" align="center"> |
| | | </el-table-column> |
| | | <el-table-column label="地址" width="180" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium">{{ scope.row.hostAddress }}</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="manufacturer" label="厂家" align="center"> |
| | | </el-table-column> |
| | | <el-table-column label="流传输模式" align="center" width="120"> |
| | | <template slot-scope="scope"> |
| | | <el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择"> |
| | | <el-option key="UDP" label="UDP" value="UDP"></el-option> |
| | | <el-option key="TCP-ACTIVE" label="TCP主动模式" :disabled="true" value="TCP-ACTIVE"></el-option> |
| | | <el-option key="TCP-PASSIVE" label="TCP被动模式" value="TCP-PASSIVE"></el-option> |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="channelCount" label="通道数" align="center"> |
| | | </el-table-column> |
| | | <el-table-column label="状态" width="120" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.online == 1">在线</el-tag> |
| | | <el-tag size="medium" type="info" v-if="scope.row.online == 0">离线</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="keepaliveTime" label="最近心跳" align="center" width="140"> |
| | | </el-table-column> |
| | | <el-table-column prop="registerTime" label="最近注册" align="center" width="140"> |
| | | </el-table-column> |
| | | <el-table-column prop="updateTime" label="更新时间" align="center" width="140"> |
| | | </el-table-column> |
| | | <el-table-column prop="createTime" label="创建时间" align="center" width="140"> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="操作" width="450" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="mini" v-if="scope.row.online!=0" icon="el-icon-refresh" @click="refDevice(scope.row)" @mouseover="getTooltipContent(scope.row.deviceId)">刷新</el-button> |
| | | <el-button-group> |
| | | <el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0" type="primary" @click="showChannelList(scope.row)">通道</el-button> |
| | | <el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary" @click="showDevicePosition(scope.row)">定位</el-button> |
| | | <el-button size="mini" icon="el-icon-edit" type="primary" @click="edit(scope.row)">编辑</el-button> |
| | | <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteDevice(scope.row)">删除</el-button> |
| | | </el-button-group> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination |
| | | style="float: right" |
| | | @size-change="handleSizeChange" |
| | | @current-change="currentChange" |
| | | :current-page="currentPage" |
| | | :page-size="count" |
| | | :page-sizes="[15, 25, 35, 50]" |
| | | layout="total, sizes, prev, pager, next" |
| | | :total="total"> |
| | | </el-pagination> |
| | | <deviceEdit ref="deviceEdit" ></deviceEdit> |
| | | <syncChannelProgress ref="syncChannelProgress" ></syncChannelProgress> |
| | | </el-main> |
| | | </el-container> |
| | | </div> |
| | | <el-table-column label="操作" width="450" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="mini" v-if="scope.row.online!=0" icon="el-icon-refresh" @click="refDevice(scope.row)" |
| | | @mouseover="getTooltipContent(scope.row.deviceId)">刷新 |
| | | </el-button> |
| | | <el-button-group> |
| | | <el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0" |
| | | type="primary" @click="showChannelList(scope.row)">通道 |
| | | </el-button> |
| | | <el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary" |
| | | @click="showDevicePosition(scope.row)">定位 |
| | | </el-button> |
| | | <el-button size="mini" icon="el-icon-edit" type="primary" @click="edit(scope.row)">编辑</el-button> |
| | | <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteDevice(scope.row)">删除</el-button> |
| | | </el-button-group> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination |
| | | style="float: right" |
| | | @size-change="handleSizeChange" |
| | | @current-change="currentChange" |
| | | :current-page="currentPage" |
| | | :page-size="count" |
| | | :page-sizes="[15, 25, 35, 50]" |
| | | layout="total, sizes, prev, pager, next" |
| | | :total="total"> |
| | | </el-pagination> |
| | | <deviceEdit ref="deviceEdit"></deviceEdit> |
| | | <syncChannelProgress ref="syncChannelProgress"></syncChannelProgress> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import uiHeader from './UiHeader.vue' |
| | | import deviceEdit from './dialog/deviceEdit.vue' |
| | | import syncChannelProgress from './dialog/SyncChannelProgress.vue' |
| | | export default { |
| | | name: 'app', |
| | | components: { |
| | | uiHeader, |
| | | deviceEdit, |
| | | syncChannelProgress, |
| | | }, |
| | | data() { |
| | | return { |
| | | deviceList: [], //设备列表 |
| | | currentDevice: {}, //当前操作设备对象 |
| | | import uiHeader from '../layout/UiHeader.vue' |
| | | import deviceEdit from './dialog/deviceEdit.vue' |
| | | import syncChannelProgress from './dialog/SyncChannelProgress.vue' |
| | | |
| | | videoComponentList: [], |
| | | updateLooper: 0, //数据刷新轮训标志 |
| | | currentDeviceChannelsLenth:0, |
| | | winHeight: window.innerHeight - 200, |
| | | currentPage:1, |
| | | count:15, |
| | | total:0, |
| | | getDeviceListLoading: false, |
| | | }; |
| | | }, |
| | | computed: { |
| | | getcurrentDeviceChannels: function() { |
| | | let data = this.currentDevice['channelMap']; |
| | | let channels = null; |
| | | if (data) { |
| | | channels = Object.keys(data).map(key => { |
| | | return data[key]; |
| | | }); |
| | | this.currentDeviceChannelsLenth = channels.length; |
| | | } |
| | | return channels; |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.initData(); |
| | | this.updateLooper = setInterval(this.initData, 10000); |
| | | }, |
| | | destroyed() { |
| | | this.$destroy('videojs'); |
| | | clearTimeout(this.updateLooper); |
| | | }, |
| | | methods: { |
| | | initData: function() { |
| | | this.getDeviceList(); |
| | | }, |
| | | currentChange: function(val){ |
| | | this.currentPage = val; |
| | | this.getDeviceList(); |
| | | }, |
| | | handleSizeChange: function(val){ |
| | | this.count = val; |
| | | this.getDeviceList(); |
| | | }, |
| | | getDeviceList: function() { |
| | | let that = this; |
| | | this.getDeviceListLoading = true; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url:`/api/device/query/devices`, |
| | | params: { |
| | | page: that.currentPage, |
| | | count: that.count |
| | | } |
| | | }).then(function (res) { |
| | | that.total = res.data.total; |
| | | that.deviceList = res.data.list; |
| | | that.getDeviceListLoading = false; |
| | | }).catch(function (error) { |
| | | console.error(error); |
| | | that.getDeviceListLoading = false; |
| | | }); |
| | | export default { |
| | | name: 'app', |
| | | components: { |
| | | uiHeader, |
| | | deviceEdit, |
| | | syncChannelProgress, |
| | | }, |
| | | data() { |
| | | return { |
| | | deviceList: [], //设备列表 |
| | | currentDevice: {}, //当前操作设备对象 |
| | | |
| | | }, |
| | | deleteDevice: function(row) { |
| | | let msg = "确定删除此设备?" |
| | | if (row.online !== 0) { |
| | | msg = "在线设备删除后仍可通过注册再次上线。<br/>如需彻底删除请先将设备离线。<br/><strong>确定删除此设备?</strong>" |
| | | } |
| | | this.$confirm(msg, '提示', { |
| | | dangerouslyUseHTMLString : true, |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | center: true, |
| | | type: 'warning' |
| | | }).then(() => { |
| | | this.$axios({ |
| | | method: 'delete', |
| | | url:`/api/device/query/devices/${row.deviceId}/delete` |
| | | }).then((res)=>{ |
| | | this.getDeviceList(); |
| | | }).catch((error) =>{ |
| | | console.error(error); |
| | | }); |
| | | }).catch(() => { |
| | | |
| | | videoComponentList: [], |
| | | updateLooper: 0, //数据刷新轮训标志 |
| | | currentDeviceChannelsLenth: 0, |
| | | winHeight: window.innerHeight - 200, |
| | | currentPage: 1, |
| | | count: 15, |
| | | total: 0, |
| | | getDeviceListLoading: false, |
| | | }; |
| | | }, |
| | | computed: { |
| | | getcurrentDeviceChannels: function () { |
| | | let data = this.currentDevice['channelMap']; |
| | | let channels = null; |
| | | if (data) { |
| | | channels = Object.keys(data).map(key => { |
| | | return data[key]; |
| | | }); |
| | | this.currentDeviceChannelsLenth = channels.length; |
| | | } |
| | | return channels; |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.initData(); |
| | | this.updateLooper = setInterval(this.initData, 10000); |
| | | }, |
| | | destroyed() { |
| | | this.$destroy('videojs'); |
| | | clearTimeout(this.updateLooper); |
| | | }, |
| | | methods: { |
| | | initData: function () { |
| | | this.getDeviceList(); |
| | | }, |
| | | currentChange: function (val) { |
| | | this.currentPage = val; |
| | | this.getDeviceList(); |
| | | }, |
| | | handleSizeChange: function (val) { |
| | | this.count = val; |
| | | this.getDeviceList(); |
| | | }, |
| | | getDeviceList: function () { |
| | | let that = this; |
| | | this.getDeviceListLoading = true; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: `/api/device/query/devices`, |
| | | params: { |
| | | page: that.currentPage, |
| | | count: that.count |
| | | } |
| | | }).then(function (res) { |
| | | that.total = res.data.total; |
| | | that.deviceList = res.data.list; |
| | | that.getDeviceListLoading = false; |
| | | }).catch(function (error) { |
| | | console.error(error); |
| | | that.getDeviceListLoading = false; |
| | | }); |
| | | |
| | | }, |
| | | deleteDevice: function (row) { |
| | | let msg = "确定删除此设备?" |
| | | if (row.online !== 0) { |
| | | msg = "在线设备删除后仍可通过注册再次上线。<br/>如需彻底删除请先将设备离线。<br/><strong>确定删除此设备?</strong>" |
| | | } |
| | | this.$confirm(msg, '提示', { |
| | | dangerouslyUseHTMLString: true, |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | center: true, |
| | | type: 'warning' |
| | | }).then(() => { |
| | | this.$axios({ |
| | | method: 'delete', |
| | | url: `/api/device/query/devices/${row.deviceId}/delete` |
| | | }).then((res) => { |
| | | this.getDeviceList(); |
| | | }).catch((error) => { |
| | | console.error(error); |
| | | }); |
| | | }).catch(() => { |
| | | |
| | | }); |
| | | |
| | | |
| | | }, |
| | | showChannelList: function(row) { |
| | | this.$router.push(`/channelList/${row.deviceId}/0/15/1`); |
| | | }, |
| | | showDevicePosition: function(row) { |
| | | this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`); |
| | | }, |
| | | }, |
| | | showChannelList: function (row) { |
| | | this.$router.push(`/channelList/${row.deviceId}/0/15/1`); |
| | | }, |
| | | showDevicePosition: function (row) { |
| | | this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`); |
| | | }, |
| | | |
| | | //gb28181平台对接 |
| | | //刷新设备信息 |
| | | refDevice: function(itemData) { |
| | | console.log("刷新对应设备:" + itemData.deviceId); |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'post', |
| | | url: '/api/device/query/devices/' + itemData.deviceId + '/sync' |
| | | }).then((res) => { |
| | | console.log("刷新设备结果:"+JSON.stringify(res)); |
| | | if (res.data.code !==0) { |
| | | that.$message({ |
| | | showClose: true, |
| | | message: res.data.msg, |
| | | type: 'error' |
| | | }); |
| | | }else{ |
| | | // that.$message({ |
| | | // showClose: true, |
| | | // message: res.data.msg, |
| | | // type: 'success' |
| | | // }); |
| | | this.$refs.syncChannelProgress.openDialog(itemData.deviceId) |
| | | } |
| | | that.initData() |
| | | }).catch((e) => { |
| | | console.error(e) |
| | | //gb28181平台对接 |
| | | //刷新设备信息 |
| | | refDevice: function (itemData) { |
| | | console.log("刷新对应设备:" + itemData.deviceId); |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'post', |
| | | url: '/api/device/query/devices/' + itemData.deviceId + '/sync' |
| | | }).then((res) => { |
| | | console.log("刷新设备结果:" + JSON.stringify(res)); |
| | | if (res.data.code !== 0) { |
| | | that.$message({ |
| | | showClose: true, |
| | | message: e, |
| | | message: res.data.msg, |
| | | type: 'error' |
| | | }); |
| | | }); |
| | | |
| | | }, |
| | | |
| | | getTooltipContent: async function (deviceId){ |
| | | let result = ""; |
| | | await this.$axios({ |
| | | method: 'get', |
| | | async: false, |
| | | url:`/api/device/query/${deviceId}/sync_status/`, |
| | | }).then((res) => { |
| | | if (res.data.code == 0) { |
| | | if (res.data.data.errorMsg !== null) { |
| | | result = res.data.data.errorMsg |
| | | } else if (res.data.msg !== null) { |
| | | result = res.data.msg |
| | | } else { |
| | | result = `同步中...[${res.data.data.current}/${res.data.data.total}]`; |
| | | } |
| | | } |
| | | }) |
| | | return result; |
| | | }, |
| | | //通知设备上传媒体流 |
| | | sendDevicePush: function(itemData) { |
| | | // let deviceId = this.currentDevice.deviceId; |
| | | // let channelId = itemData.channelId; |
| | | // console.log("通知设备推流1:" + deviceId + " : " + channelId); |
| | | // let that = this; |
| | | // this.$axios({ |
| | | // method: 'get', |
| | | // url: '/api/play/' + deviceId + '/' + channelId |
| | | // }).then(function(res) { |
| | | // let ssrc = res.data.ssrc; |
| | | // that.$refs.devicePlayer.play(ssrc,deviceId,channelId); |
| | | // }).catch(function(e) { |
| | | // }); |
| | | }, |
| | | transportChange: function (row) { |
| | | console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `); |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'post', |
| | | url: '/api/device/query/transport/' + row.deviceId + '/' + row.streamMode |
| | | }).then(function(res) { |
| | | |
| | | }).catch(function(e) { |
| | | } else { |
| | | // that.$message({ |
| | | // showClose: true, |
| | | // message: res.data.msg, |
| | | // type: 'success' |
| | | // }); |
| | | this.$refs.syncChannelProgress.openDialog(itemData.deviceId) |
| | | } |
| | | that.initData() |
| | | }).catch((e) => { |
| | | console.error(e) |
| | | that.$message({ |
| | | showClose: true, |
| | | message: e, |
| | | type: 'error' |
| | | }); |
| | | }, |
| | | edit: function (row) { |
| | | this.$refs.deviceEdit.openDialog(row, ()=>{ |
| | | this.$refs.deviceEdit.close(); |
| | | this.$message({ |
| | | showClose: true, |
| | | message: "设备修改成功,通道字符集将在下次更新生效", |
| | | type: "success", |
| | | }); |
| | | setTimeout(this.getDeviceList, 200) |
| | | }); |
| | | |
| | | }) |
| | | } |
| | | }, |
| | | |
| | | } |
| | | }; |
| | | getTooltipContent: async function (deviceId) { |
| | | let result = ""; |
| | | await this.$axios({ |
| | | method: 'get', |
| | | async: false, |
| | | url: `/api/device/query/${deviceId}/sync_status/`, |
| | | }).then((res) => { |
| | | if (res.data.code == 0) { |
| | | if (res.data.data.errorMsg !== null) { |
| | | result = res.data.data.errorMsg |
| | | } else if (res.data.msg !== null) { |
| | | result = res.data.msg |
| | | } else { |
| | | result = `同步中...[${res.data.data.current}/${res.data.data.total}]`; |
| | | } |
| | | } |
| | | }) |
| | | return result; |
| | | }, |
| | | //通知设备上传媒体流 |
| | | sendDevicePush: function (itemData) { |
| | | // let deviceId = this.currentDevice.deviceId; |
| | | // let channelId = itemData.channelId; |
| | | // console.log("通知设备推流1:" + deviceId + " : " + channelId); |
| | | // let that = this; |
| | | // this.$axios({ |
| | | // method: 'get', |
| | | // url: '/api/play/' + deviceId + '/' + channelId |
| | | // }).then(function(res) { |
| | | // let ssrc = res.data.ssrc; |
| | | // that.$refs.devicePlayer.play(ssrc,deviceId,channelId); |
| | | // }).catch(function(e) { |
| | | // }); |
| | | }, |
| | | transportChange: function (row) { |
| | | console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `); |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'post', |
| | | url: '/api/device/query/transport/' + row.deviceId + '/' + row.streamMode |
| | | }).then(function (res) { |
| | | |
| | | }).catch(function (e) { |
| | | }); |
| | | }, |
| | | edit: function (row) { |
| | | this.$refs.deviceEdit.openDialog(row, () => { |
| | | this.$refs.deviceEdit.close(); |
| | | this.$message({ |
| | | showClose: true, |
| | | message: "设备修改成功,通道字符集将在下次更新生效", |
| | | type: "success", |
| | | }); |
| | | setTimeout(this.getDeviceList, 200) |
| | | |
| | | }) |
| | | } |
| | | |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | .videoList { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-content: flex-start; |
| | | } |
| | | .videoList { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-content: flex-start; |
| | | } |
| | | |
| | | .video-item { |
| | | position: relative; |
| | | width: 15rem; |
| | | height: 10rem; |
| | | margin-right: 1rem; |
| | | background-color: #000000; |
| | | } |
| | | .video-item { |
| | | position: relative; |
| | | width: 15rem; |
| | | height: 10rem; |
| | | margin-right: 1rem; |
| | | background-color: #000000; |
| | | } |
| | | |
| | | .video-item-img { |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | .video-item-img { |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .video-item-img:after { |
| | | content: ""; |
| | | display: inline-block; |
| | | position: absolute; |
| | | z-index: 2; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 3rem; |
| | | height: 3rem; |
| | | background-image: url("../assets/loading.png"); |
| | | background-size: cover; |
| | | background-color: #000000; |
| | | } |
| | | .video-item-img:after { |
| | | content: ""; |
| | | display: inline-block; |
| | | position: absolute; |
| | | z-index: 2; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 3rem; |
| | | height: 3rem; |
| | | background-image: url("../assets/loading.png"); |
| | | background-size: cover; |
| | | background-color: #000000; |
| | | } |
| | | |
| | | .video-item-title { |
| | | position: absolute; |
| | | bottom: 0; |
| | | color: #000000; |
| | | background-color: #ffffff; |
| | | line-height: 1.5rem; |
| | | padding: 0.3rem; |
| | | width: 14.4rem; |
| | | } |
| | | .video-item-title { |
| | | position: absolute; |
| | | bottom: 0; |
| | | color: #000000; |
| | | background-color: #ffffff; |
| | | line-height: 1.5rem; |
| | | padding: 0.3rem; |
| | | width: 14.4rem; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div id="mediaServerManger"> |
| | | <el-container> |
| | | <el-header> |
| | | <uiHeader></uiHeader> |
| | | </el-header> |
| | | <el-main id="msMain"> |
| | | <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;"> |
| | | <span style="font-size: 1rem; font-weight: bold;">节点列表</span> |
| | | </div> |
| | | <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;"> |
| | | <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="add">添加节点</el-button> |
| | | </div> |
| | | <div id="mediaServerManger" style="width: 100%"> |
| | | <div class="page-header"> |
| | | <div class="page-title">节点列表</div> |
| | | <div class="page-header-btn"> |
| | | <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="add">添加节点</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-row :gutter="12"> |
| | | <el-col :span="num" v-for="item in mediaServerList" :key="item.id"> |
| | | <el-card shadow="hover" :body-style="{ padding: '0px'}" class="server-card"> |
| | | <div class="card-img-zlm"></div> |
| | | <div style="padding: 14px;text-align: left"> |
| | | <span style="font-size: 16px">{{item.id}}</span> |
| | | <el-button v-if="!item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">编辑</el-button> |
| | | <el-button v-if="item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">查看</el-button> |
| | | <el-button icon="el-icon-delete" style="margin-right: 10px;padding: 0;float: right;" type="text" @click="del(item)">移除</el-button> |
| | | <div style="margin-top: 13px; line-height: 12px; "> |
| | | <span style="font-size: 14px; color: #999; margin-top: 5px; ">{{item.ip}}</span> |
| | | <span style="font-size: 14px; color: #999; margin-top: 5px; float: right;">{{item.createTime}}</span> |
| | | </div> |
| | | </div> |
| | | <i v-if="item.status" class="iconfont icon-online server-card-status-online" title="在线"></i> |
| | | <i v-if="!item.status" class="iconfont icon-online server-card-status-offline" title="离线"></i> |
| | | <i v-if="item.defaultServer" class="server-card-default" >默认</i> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | <mediaServerEdit ref="mediaServerEdit" ></mediaServerEdit> |
| | | </el-main> |
| | | </el-container> |
| | | <el-row :gutter="12"> |
| | | <el-col :span="num" v-for="item in mediaServerList" :key="item.id"> |
| | | <el-card shadow="hover" :body-style="{ padding: '0px'}" class="server-card"> |
| | | <div class="card-img-zlm"></div> |
| | | <div style="padding: 14px;text-align: left"> |
| | | <span style="font-size: 16px">{{item.id}}</span> |
| | | <el-button v-if="!item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">编辑</el-button> |
| | | <el-button v-if="item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">查看</el-button> |
| | | <el-button icon="el-icon-delete" style="margin-right: 10px;padding: 0;float: right;" type="text" @click="del(item)">移除</el-button> |
| | | <div style="margin-top: 13px; line-height: 12px; "> |
| | | <span style="font-size: 14px; color: #999; margin-top: 5px; ">{{item.ip}}</span> |
| | | <span style="font-size: 14px; color: #999; margin-top: 5px; float: right;">{{item.createTime}}</span> |
| | | </div> |
| | | </div> |
| | | <i v-if="item.status" class="iconfont icon-online server-card-status-online" title="在线"></i> |
| | | <i v-if="!item.status" class="iconfont icon-online server-card-status-offline" title="离线"></i> |
| | | <i v-if="item.defaultServer" class="server-card-default" >默认</i> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | <mediaServerEdit ref="mediaServerEdit" ></mediaServerEdit> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import uiHeader from './UiHeader.vue' |
| | | import uiHeader from '../layout/UiHeader.vue' |
| | | import MediaServer from './service/MediaServer' |
| | | import mediaServerEdit from './dialog/MediaServerEdit' |
| | | export default { |
| | |
| | | <template> |
| | | <div id="app"> |
| | | <el-container> |
| | | <el-header> |
| | | <uiHeader></uiHeader> |
| | | </el-header> |
| | | <el-main> |
| | | <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;"> |
| | | <span style="font-size: 1rem; font-weight: bold;">上级平台列表</span> |
| | | </div> |
| | | <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;"> |
| | | <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addParentPlatform">添加</el-button> |
| | | </div> |
| | | <!--设备列表--> |
| | | <el-table :data="platformList" border style="width: 100%" :height="winHeight"> |
| | | <el-table-column prop="name" label="名称" align="center"></el-table-column> |
| | | <el-table-column prop="serverGBId" label="平台编号" width="180" align="center"></el-table-column> |
| | | <el-table-column label="是否启用" width="120" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.enable">已启用</el-tag> |
| | | <el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="状态" width="120" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.status">在线</el-tag> |
| | | <el-tag size="medium" type="info" v-if="!scope.row.status">离线</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="地址" width="180" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium">{{ scope.row.serverIP}}:{{scope.row.serverPort }}</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceGBId" label="设备国标编号" width="200" align="center"></el-table-column> |
| | | <el-table-column prop="transport" label="信令传输模式" width="120" align="center"></el-table-column> |
| | | <el-table-column prop="channelCount" label="通道数" width="120" align="center"></el-table-column> |
| | | <el-table-column label="订阅信息" width="240" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <i v-if="scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅" class="iconfont icon-gbaojings subscribe-on " ></i> |
| | | <i v-if="!scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅" class="iconfont icon-gbaojings subscribe-off " ></i> |
| | | <i v-if="scope.row.catalogSubscribe" title="目录订阅" class="iconfont icon-gjichus subscribe-on" ></i> |
| | | <i v-if="!scope.row.catalogSubscribe" title="目录订阅" class="iconfont icon-gjichus subscribe-off" ></i> |
| | | <i v-if="scope.row.mobilePositionSubscribe" title="位置订阅" class="iconfont icon-gxunjians subscribe-on" ></i> |
| | | <i v-if="!scope.row.mobilePositionSubscribe" title="位置订阅" class="iconfont icon-gxunjians subscribe-off" ></i> |
| | | </template> |
| | | </el-table-column> |
| | | <div id="app" style="width: 100%"> |
| | | <div class="page-header"> |
| | | <div class="page-title">上级平台列表</div> |
| | | <div class="page-header-btn"> |
| | | <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addParentPlatform">添加</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-table-column label="操作" width="300" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="mini" icon="el-icon-edit" @click="editPlatform(scope.row)">编辑</el-button> |
| | | <el-button size="mini" icon="el-icon-share" type="primary" @click="chooseChannel(scope.row)">选择通道</el-button> |
| | | <el-button size="mini" icon="el-icon-delete" type="danger" @click="deletePlatform(scope.row)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination |
| | | style="float: right" |
| | | @size-change="handleSizeChange" |
| | | @current-change="currentChange" |
| | | :current-page="currentPage" |
| | | :page-size="count" |
| | | :page-sizes="[15, 25, 35, 50]" |
| | | layout="total, sizes, prev, pager, next" |
| | | :total="total"> |
| | | </el-pagination> |
| | | <platformEdit ref="platformEdit" ></platformEdit> |
| | | <chooseChannelDialog ref="chooseChannelDialog" ></chooseChannelDialog> |
| | | </el-main> |
| | | </el-container> |
| | | <!--设备列表--> |
| | | <el-table :data="platformList" border style="width: 100%" :height="winHeight"> |
| | | <el-table-column prop="name" label="名称" align="center"></el-table-column> |
| | | <el-table-column prop="serverGBId" label="平台编号" align="center"></el-table-column> |
| | | <el-table-column label="是否启用" width="120" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.enable">已启用</el-tag> |
| | | <el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="状态" width="120" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.status">在线</el-tag> |
| | | <el-tag size="medium" type="info" v-if="!scope.row.status">离线</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="地址" width="180" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium">{{ scope.row.serverIP}}:{{scope.row.serverPort }}</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceGBId" label="设备国标编号" width="200" align="center"></el-table-column> |
| | | <el-table-column prop="transport" label="信令传输模式" width="120" align="center"></el-table-column> |
| | | <el-table-column prop="channelCount" label="通道数" width="120" align="center"></el-table-column> |
| | | <el-table-column label="订阅信息" width="240" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <i v-if="scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅" class="iconfont icon-gbaojings subscribe-on " ></i> |
| | | <i v-if="!scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅" class="iconfont icon-gbaojings subscribe-off " ></i> |
| | | <i v-if="scope.row.catalogSubscribe" title="目录订阅" class="iconfont icon-gjichus subscribe-on" ></i> |
| | | <i v-if="!scope.row.catalogSubscribe" title="目录订阅" class="iconfont icon-gjichus subscribe-off" ></i> |
| | | <i v-if="scope.row.mobilePositionSubscribe" title="位置订阅" class="iconfont icon-gxunjians subscribe-on" ></i> |
| | | <i v-if="!scope.row.mobilePositionSubscribe" title="位置订阅" class="iconfont icon-gxunjians subscribe-off" ></i> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="操作" width="300" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="mini" icon="el-icon-edit" @click="editPlatform(scope.row)">编辑</el-button> |
| | | <el-button size="mini" icon="el-icon-share" type="primary" @click="chooseChannel(scope.row)">选择通道</el-button> |
| | | <el-button size="mini" icon="el-icon-delete" type="danger" @click="deletePlatform(scope.row)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination |
| | | style="float: right" |
| | | @size-change="handleSizeChange" |
| | | @current-change="currentChange" |
| | | :current-page="currentPage" |
| | | :page-size="count" |
| | | :page-sizes="[15, 25, 35, 50]" |
| | | layout="total, sizes, prev, pager, next" |
| | | :total="total"> |
| | | </el-pagination> |
| | | <platformEdit ref="platformEdit" ></platformEdit> |
| | | <chooseChannelDialog ref="chooseChannelDialog" ></chooseChannelDialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import platformEdit from './dialog/platformEdit.vue' |
| | | import uiHeader from './UiHeader.vue' |
| | | import uiHeader from '../layout/UiHeader.vue' |
| | | import chooseChannelDialog from './dialog/chooseChannel.vue' |
| | | export default { |
| | | name: 'app', |
| | |
| | | <template> |
| | | <div id="pushVideoList"> |
| | | <el-container> |
| | | <el-header> |
| | | <uiHeader></uiHeader> |
| | | </el-header> |
| | | <el-main> |
| | | <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;"> |
| | | <span style="font-size: 1rem; font-weight: bold;">推流列表</span> |
| | | </div> |
| | | <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;"> |
| | | |
| | | 搜索: <el-input @input="getPushList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字" prefix-icon="el-icon-search" v-model="searchSrt" clearable> </el-input> |
| | | |
| | | 流媒体: <el-select size="mini" @change="getPushList" style="margin-right: 1rem;" v-model="mediaServerId" placeholder="请选择" default-first-option> |
| | | <div id="pushVideoList" style="width: 100%"> |
| | | <div class="page-header"> |
| | | <div class="page-title">推流列表</div> |
| | | <div class="page-header-btn"> |
| | | 搜索: |
| | | <el-input @input="getPushList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字" |
| | | prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input> |
| | | 流媒体: |
| | | <el-select size="mini" @change="getPushList" style="margin-right: 1rem;" v-model="mediaServerId" |
| | | placeholder="请选择" default-first-option> |
| | | <el-option label="全部" value=""></el-option> |
| | | <el-option |
| | | v-for="item in mediaServerList" |
| | |
| | | :value="item.id"> |
| | | </el-option> |
| | | </el-select> |
| | | 推流状态: <el-select size="mini" style="margin-right: 1rem;" @change="getPushList" v-model="pushing" placeholder="请选择" default-first-option> |
| | | 推流状态: |
| | | <el-select size="mini" style="margin-right: 1rem;" @change="getPushList" v-model="pushing" placeholder="请选择" |
| | | default-first-option> |
| | | <el-option label="全部" value=""></el-option> |
| | | <el-option label="推流进行中" value="true"></el-option> |
| | | <el-option label="推流未进行" value="false"></el-option> |
| | | </el-select> |
| | | <el-button icon="el-icon-upload2" size="mini" style="margin-right: 1rem;" type="primary" @click="importChannel">通道导入</el-button> |
| | | <el-button icon="el-icon-download" size="mini" style="margin-right: 1rem;" type="primary" > |
| | | <a style="color: #FFFFFF; text-align: center; text-decoration: none" href="/static/file/推流通道导入.zip" download='推流通道导入.zip' >下载模板</a> |
| | | </el-button> |
| | | <el-button icon="el-icon-delete" size="mini" style="margin-right: 1rem;" :disabled="multipleSelection.length === 0" type="danger" @click="batchDel">批量移除</el-button> |
| | | </div> |
| | | <devicePlayer ref="devicePlayer"></devicePlayer> |
| | | <addStreamTOGB ref="addStreamTOGB"></addStreamTOGB> |
| | | <el-table ref="pushListTable" :data="pushList" border style="width: 100%" :height="winHeight" @selection-change="handleSelectionChange" :row-key="(row)=> row.app + row.stream"> |
| | | <el-table-column align="center" type="selection" :reserve-selection="true" width="55"> |
| | | </el-table-column> |
| | | <el-table-column prop="name" label="名称" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="app" label="APP" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="stream" label="流ID" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="gbId" label="国标编码" width="200" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="mediaServerId" label="流媒体" width="200" align="center"> |
| | | </el-table-column> |
| | | <el-table-column label="开始时间" align="center" width="200"> |
| | | <template slot-scope="scope"> |
| | | <el-button-group> |
| | | {{dateFormat(parseInt(scope.row.createStamp))}} |
| | | </el-button-group> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="正在推流" align="center" width="100"> |
| | | <template slot-scope="scope"> |
| | | {{(scope.row.status == false && scope.row.gbId == null) || scope.row.status ?'是':'否'}} |
| | | </template> |
| | | </el-table-column> |
| | | <el-button icon="el-icon-upload2" size="mini" style="margin-right: 1rem;" type="primary" @click="importChannel"> |
| | | 通道导入 |
| | | </el-button> |
| | | <el-button icon="el-icon-download" size="mini" style="margin-right: 1rem;" type="primary"> |
| | | <a style="color: #FFFFFF; text-align: center; text-decoration: none" href="/static/file/推流通道导入.zip" |
| | | download='推流通道导入.zip'>下载模板</a> |
| | | </el-button> |
| | | <el-button icon="el-icon-delete" size="mini" style="margin-right: 1rem;" |
| | | :disabled="multipleSelection.length === 0" type="danger" @click="batchDel">批量移除 |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <devicePlayer ref="devicePlayer"></devicePlayer> |
| | | <addStreamTOGB ref="addStreamTOGB"></addStreamTOGB> |
| | | <el-table ref="pushListTable" :data="pushList" border style="width: 100%" :height="winHeight" |
| | | @selection-change="handleSelectionChange" :row-key="(row)=> row.app + row.stream"> |
| | | <el-table-column align="center" type="selection" :reserve-selection="true" width="55"> |
| | | </el-table-column> |
| | | <el-table-column prop="name" label="名称" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="app" label="APP" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="stream" label="流ID" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="gbId" label="国标编码" width="200" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="mediaServerId" label="流媒体" width="200" align="center"> |
| | | </el-table-column> |
| | | <el-table-column label="开始时间" align="center" width="200"> |
| | | <template slot-scope="scope"> |
| | | <el-button-group> |
| | | {{ dateFormat(parseInt(scope.row.createStamp)) }} |
| | | </el-button-group> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="正在推流" align="center" width="100"> |
| | | <template slot-scope="scope"> |
| | | {{ (scope.row.status == false && scope.row.gbId == null) || scope.row.status ? '是' : '否' }} |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="操作" width="360" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button-group> |
| | | <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> |
| | | <el-button size="mini" icon="el-icon-delete" type="danger" @click="stopPush(scope.row)">移除</el-button> |
| | | <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!!scope.row.gbId" @click="addToGB(scope.row)">加入国标</el-button> |
| | | <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!scope.row.gbId" @click="removeFromGB(scope.row)">移出国标</el-button> |
| | | </el-button-group> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination |
| | | style="float: right" |
| | | @size-change="handleSizeChange" |
| | | @current-change="currentChange" |
| | | :current-page="currentPage" |
| | | :page-size="count" |
| | | :page-sizes="[15, 25, 35, 50]" |
| | | layout="total, sizes, prev, pager, next" |
| | | :total="total"> |
| | | </el-pagination> |
| | | <streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit> |
| | | <importChannel ref="importChannel" ></importChannel> |
| | | </el-main> |
| | | </el-container> |
| | | </div> |
| | | <el-table-column label="操作" width="360" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button-group> |
| | | <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> |
| | | <el-button size="mini" icon="el-icon-delete" type="danger" @click="stopPush(scope.row)">移除</el-button> |
| | | <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!!scope.row.gbId" |
| | | @click="addToGB(scope.row)">加入国标 |
| | | </el-button> |
| | | <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!scope.row.gbId" |
| | | @click="removeFromGB(scope.row)">移出国标 |
| | | </el-button> |
| | | </el-button-group> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination |
| | | style="float: right" |
| | | @size-change="handleSizeChange" |
| | | @current-change="currentChange" |
| | | :current-page="currentPage" |
| | | :page-size="count" |
| | | :page-sizes="[15, 25, 35, 50]" |
| | | layout="total, sizes, prev, pager, next" |
| | | :total="total"> |
| | | </el-pagination> |
| | | <streamProxyEdit ref="streamProxyEdit"></streamProxyEdit> |
| | | <importChannel ref="importChannel"></importChannel> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import streamProxyEdit from './dialog/StreamProxyEdit.vue' |
| | | import devicePlayer from './dialog/devicePlayer.vue' |
| | | import addStreamTOGB from './dialog/addStreamTOGB.vue' |
| | | import uiHeader from './UiHeader.vue' |
| | | import importChannel from './dialog/importChannel.vue' |
| | | import MediaServer from './service/MediaServer' |
| | | export default { |
| | | name: 'pushVideoList', |
| | | components: { |
| | | devicePlayer, |
| | | addStreamTOGB, |
| | | streamProxyEdit, |
| | | uiHeader, |
| | | importChannel, |
| | | }, |
| | | data() { |
| | | return { |
| | | pushList: [], //设备列表 |
| | | currentPusher: {}, //当前操作设备对象 |
| | | updateLooper: 0, //数据刷新轮训标志 |
| | | currentDeviceChannelsLenth:0, |
| | | winHeight: window.innerHeight - 250, |
| | | mediaServerObj : new MediaServer(), |
| | | currentPage:1, |
| | | count:15, |
| | | total:0, |
| | | searchSrt: "", |
| | | pushing: "", |
| | | mediaServerId: "", |
| | | mediaServerList: [], |
| | | multipleSelection: [], |
| | | getDeviceListLoading: false |
| | | }; |
| | | }, |
| | | computed: { |
| | | }, |
| | | mounted() { |
| | | this.initData(); |
| | | this.updateLooper = setInterval(this.getPushList, 2000); |
| | | }, |
| | | destroyed() { |
| | | clearTimeout(this.updateLooper); |
| | | }, |
| | | methods: { |
| | | initData: function() { |
| | | this.mediaServerObj.getOnlineMediaServerList((data)=>{ |
| | | this.mediaServerList = data.data; |
| | | }) |
| | | this.getPushList(); |
| | | }, |
| | | currentChange: function(val){ |
| | | this.currentPage = val; |
| | | this.getPushList(); |
| | | }, |
| | | handleSizeChange: function(val){ |
| | | this.count = val; |
| | | this.getPushList(); |
| | | }, |
| | | getPushList: function() { |
| | | let that = this; |
| | | this.getDeviceListLoading = true; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url:`/api/push/list`, |
| | | params: { |
| | | page: that.currentPage, |
| | | count: that.count, |
| | | query: that.searchSrt, |
| | | pushing: that.pushing, |
| | | mediaServerId: that.mediaServerId, |
| | | } |
| | | }).then(function (res) { |
| | | that.total = res.data.total; |
| | | that.pushList = res.data.list; |
| | | that.getDeviceListLoading = false; |
| | | }).catch(function (error) { |
| | | console.error(error); |
| | | that.getDeviceListLoading = false; |
| | | }); |
| | | }, |
| | | import streamProxyEdit from './dialog/StreamProxyEdit.vue' |
| | | import devicePlayer from './dialog/devicePlayer.vue' |
| | | import addStreamTOGB from './dialog/addStreamTOGB.vue' |
| | | import uiHeader from '../layout/UiHeader.vue' |
| | | import importChannel from './dialog/importChannel.vue' |
| | | import MediaServer from './service/MediaServer' |
| | | |
| | | playPush: function(row){ |
| | | let that = this; |
| | | this.getListLoading = true; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/media/stream_info_by_app_and_stream', |
| | | params: { |
| | | app: row.app, |
| | | stream: row.stream, |
| | | mediaServerId: row.mediaServerId |
| | | } |
| | | }).then(function (res) { |
| | | that.getListLoading = false; |
| | | that.$refs.devicePlayer.openDialog("streamPlay", null, null, { |
| | | streamInfo: res.data.data, |
| | | hasAudio: true |
| | | }); |
| | | }).catch(function (error) { |
| | | console.error(error); |
| | | that.getListLoading = false; |
| | | }); |
| | | }, |
| | | stopPush: function(row){ |
| | | export default { |
| | | name: 'pushVideoList', |
| | | components: { |
| | | devicePlayer, |
| | | addStreamTOGB, |
| | | streamProxyEdit, |
| | | uiHeader, |
| | | importChannel, |
| | | }, |
| | | data() { |
| | | return { |
| | | pushList: [], //设备列表 |
| | | currentPusher: {}, //当前操作设备对象 |
| | | updateLooper: 0, //数据刷新轮训标志 |
| | | currentDeviceChannelsLenth: 0, |
| | | winHeight: window.innerHeight - 250, |
| | | mediaServerObj: new MediaServer(), |
| | | currentPage: 1, |
| | | count: 15, |
| | | total: 0, |
| | | searchSrt: "", |
| | | pushing: "", |
| | | mediaServerId: "", |
| | | mediaServerList: [], |
| | | multipleSelection: [], |
| | | getDeviceListLoading: false |
| | | }; |
| | | }, |
| | | computed: {}, |
| | | mounted() { |
| | | this.initData(); |
| | | this.updateLooper = setInterval(this.getPushList, 2000); |
| | | }, |
| | | destroyed() { |
| | | clearTimeout(this.updateLooper); |
| | | }, |
| | | methods: { |
| | | initData: function () { |
| | | this.mediaServerObj.getOnlineMediaServerList((data) => { |
| | | this.mediaServerList = data.data; |
| | | }) |
| | | this.getPushList(); |
| | | }, |
| | | currentChange: function (val) { |
| | | this.currentPage = val; |
| | | this.getPushList(); |
| | | }, |
| | | handleSizeChange: function (val) { |
| | | this.count = val; |
| | | this.getPushList(); |
| | | }, |
| | | getPushList: function () { |
| | | let that = this; |
| | | this.getDeviceListLoading = true; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: `/api/push/list`, |
| | | params: { |
| | | page: that.currentPage, |
| | | count: that.count, |
| | | query: that.searchSrt, |
| | | pushing: that.pushing, |
| | | mediaServerId: that.mediaServerId, |
| | | } |
| | | }).then(function (res) { |
| | | that.total = res.data.total; |
| | | that.pushList = res.data.list; |
| | | that.getDeviceListLoading = false; |
| | | }).catch(function (error) { |
| | | console.error(error); |
| | | that.getDeviceListLoading = false; |
| | | }); |
| | | }, |
| | | |
| | | playPush: function (row) { |
| | | let that = this; |
| | | this.getListLoading = true; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/media/stream_info_by_app_and_stream', |
| | | params: { |
| | | app: row.app, |
| | | stream: row.stream, |
| | | mediaServerId: row.mediaServerId |
| | | } |
| | | }).then(function (res) { |
| | | that.getListLoading = false; |
| | | that.$refs.devicePlayer.openDialog("streamPlay", null, null, { |
| | | streamInfo: res.data.data, |
| | | hasAudio: true |
| | | }); |
| | | }).catch(function (error) { |
| | | console.error(error); |
| | | that.getListLoading = false; |
| | | }); |
| | | }, |
| | | stopPush: function (row) { |
| | | let that = this; |
| | | that.$axios({ |
| | | method: "post", |
| | | url: "/api/push/stop", |
| | | params: { |
| | | app: row.app, |
| | | streamId: row.stream |
| | | } |
| | | }).then((res) => { |
| | | if (res.data == "success") { |
| | | that.initData() |
| | | } |
| | | }).catch(function (error) { |
| | | console.error(error); |
| | | }); |
| | | }, |
| | | addToGB: function (row) { |
| | | this.$refs.addStreamTOGB.openDialog({ |
| | | app: row.app, |
| | | stream: row.stream, |
| | | mediaServerId: row.mediaServerId |
| | | }, this.initData); |
| | | }, |
| | | removeFromGB: function (row) { |
| | | let that = this; |
| | | that.$axios({ |
| | | method: "delete", |
| | | url: "/api/push/remove_form_gb", |
| | | data: row |
| | | }).then((res) => { |
| | | if (res.data == "success") { |
| | | that.initData() |
| | | } |
| | | }).catch(function (error) { |
| | | console.error(error); |
| | | }); |
| | | }, |
| | | dateFormat: function (/** timestamp=0 **/) { |
| | | let ts = arguments[0] || 0; |
| | | let t, y, m, d, h, i, s; |
| | | t = ts ? new Date(ts) : new Date(); |
| | | y = t.getFullYear(); |
| | | m = t.getMonth() + 1; |
| | | d = t.getDate(); |
| | | h = t.getHours(); |
| | | i = t.getMinutes(); |
| | | s = t.getSeconds(); |
| | | // 可根据需要在这里定义时间格式 |
| | | return y + '-' + (m < 10 ? '0' + m : m) + '-' + (d < 10 ? '0' + d : d) + ' ' + (h < 10 ? '0' + h : h) + ':' + (i < 10 ? '0' + i : i) + ':' + (s < 10 ? '0' + s : s); |
| | | }, |
| | | importChannel: function () { |
| | | this.$refs.importChannel.openDialog(() => { |
| | | |
| | | }) |
| | | }, |
| | | batchDel: function () { |
| | | this.$confirm(`确定删除选中的${this.multipleSelection.length}个通道?`, '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | let that = this; |
| | | that.$axios({ |
| | | method:"post", |
| | | url:"/api/push/stop", |
| | | params: { |
| | | app: row.app, |
| | | streamId: row.stream |
| | | method: "delete", |
| | | url: "/api/push/batchStop", |
| | | data: { |
| | | gbStreams: this.multipleSelection |
| | | } |
| | | }).then((res)=>{ |
| | | if (res.data == "success") { |
| | | that.initData() |
| | | } |
| | | }).then((res) => { |
| | | this.initData(); |
| | | this.$refs.pushListTable.clearSelection(); |
| | | }).catch(function (error) { |
| | | console.error(error); |
| | | }); |
| | | }, |
| | | addToGB: function(row){ |
| | | this.$refs.addStreamTOGB.openDialog({app: row.app, stream: row.stream, mediaServerId: row.mediaServerId}, this.initData); |
| | | }, |
| | | removeFromGB: function(row){ |
| | | let that = this; |
| | | that.$axios({ |
| | | method:"delete", |
| | | url:"/api/push/remove_form_gb", |
| | | data:row |
| | | }).then((res)=>{ |
| | | if (res.data == "success") { |
| | | that.initData() |
| | | } |
| | | }).catch(function (error) { |
| | | console.error(error); |
| | | }); |
| | | }, |
| | | dateFormat: function(/** timestamp=0 **/) { |
| | | let ts = arguments[0] || 0; |
| | | let t,y,m,d,h,i,s; |
| | | t = ts ? new Date(ts) : new Date(); |
| | | y = t.getFullYear(); |
| | | m = t.getMonth()+1; |
| | | d = t.getDate(); |
| | | h = t.getHours(); |
| | | i = t.getMinutes(); |
| | | s = t.getSeconds(); |
| | | // 可根据需要在这里定义时间格式 |
| | | return y+'-'+(m<10?'0'+m:m)+'-'+(d<10?'0'+d:d)+' '+(h<10?'0'+h:h)+':'+(i<10?'0'+i:i)+':'+(s<10?'0'+s:s); |
| | | }, |
| | | importChannel: function () { |
| | | this.$refs.importChannel.openDialog(()=>{ |
| | | }).catch(() => { |
| | | |
| | | }) |
| | | }, |
| | | batchDel: function () { |
| | | this.$confirm(`确定删除选中的${this.multipleSelection.length}个通道?`, '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | let that = this; |
| | | that.$axios({ |
| | | method:"delete", |
| | | url:"/api/push/batchStop", |
| | | data: { |
| | | gbStreams: this.multipleSelection |
| | | } |
| | | }).then((res)=>{ |
| | | this.initData(); |
| | | this.$refs.pushListTable.clearSelection(); |
| | | }).catch(function (error) { |
| | | console.error(error); |
| | | }); |
| | | }).catch(() => { |
| | | |
| | | }); |
| | | }, |
| | | handleSelectionChange: function (val) { |
| | | this.multipleSelection = val; |
| | | }, |
| | | } |
| | | }; |
| | | }); |
| | | }, |
| | | handleSelectionChange: function (val) { |
| | | this.multipleSelection = val; |
| | | }, |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | .videoList { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-content: flex-start; |
| | | } |
| | | .videoList { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-content: flex-start; |
| | | } |
| | | |
| | | .video-item { |
| | | position: relative; |
| | | width: 15rem; |
| | | height: 10rem; |
| | | margin-right: 1rem; |
| | | background-color: #000000; |
| | | } |
| | | .video-item { |
| | | position: relative; |
| | | width: 15rem; |
| | | height: 10rem; |
| | | margin-right: 1rem; |
| | | background-color: #000000; |
| | | } |
| | | |
| | | .video-item-img { |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | .video-item-img { |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .video-item-img:after { |
| | | content: ""; |
| | | display: inline-block; |
| | | position: absolute; |
| | | z-index: 2; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 3rem; |
| | | height: 3rem; |
| | | background-image: url("../assets/loading.png"); |
| | | background-size: cover; |
| | | background-color: #000000; |
| | | } |
| | | .video-item-img:after { |
| | | content: ""; |
| | | display: inline-block; |
| | | position: absolute; |
| | | z-index: 2; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 3rem; |
| | | height: 3rem; |
| | | background-image: url("../assets/loading.png"); |
| | | background-size: cover; |
| | | background-color: #000000; |
| | | } |
| | | |
| | | .video-item-title { |
| | | position: absolute; |
| | | bottom: 0; |
| | | color: #000000; |
| | | background-color: #ffffff; |
| | | line-height: 1.5rem; |
| | | padding: 0.3rem; |
| | | width: 14.4rem; |
| | | } |
| | | .video-item-title { |
| | | position: absolute; |
| | | bottom: 0; |
| | | color: #000000; |
| | | background-color: #ffffff; |
| | | line-height: 1.5rem; |
| | | padding: 0.3rem; |
| | | width: 14.4rem; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div id="streamProxyList"> |
| | | <el-container> |
| | | <el-header> |
| | | <uiHeader></uiHeader> |
| | | </el-header> |
| | | <el-main> |
| | | <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;"> |
| | | <span style="font-size: 1rem; font-weight: bold;">拉流代理列表</span> |
| | | </div> |
| | | <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;"> |
| | | <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">添加代理</el-button> |
| | | <el-button v-if="false" icon="el-icon-search" size="mini" style="margin-right: 1rem;" type="primary" @click="addOnvif">搜索ONVIF</el-button> |
| | | </div> |
| | | <devicePlayer ref="devicePlayer"></devicePlayer> |
| | | <el-table :data="streamProxyList" border style="width: 100%" :height="winHeight"> |
| | | <el-table-column prop="name" label="名称" align="center" show-overflow-tooltip/> |
| | | <el-table-column prop="app" label="流应用名" align="center" show-overflow-tooltip/> |
| | | <el-table-column prop="stream" label="流ID" align="center" show-overflow-tooltip/> |
| | | <el-table-column label="流地址" width="400" align="center" show-overflow-tooltip > |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <div id="streamProxyList" style="width: 100%"> |
| | | <div class="page-header"> |
| | | <div class="page-title">拉流代理列表</div> |
| | | <div class="page-header-btn"> |
| | | <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">添加代理</el-button> |
| | | <el-button v-if="false" icon="el-icon-search" size="mini" style="margin-right: 1rem;" type="primary" @click="addOnvif">搜索ONVIF</el-button> |
| | | </div> |
| | | </div> |
| | | <devicePlayer ref="devicePlayer"></devicePlayer> |
| | | <el-table :data="streamProxyList" border style="width: 100%" :height="winHeight"> |
| | | <el-table-column prop="name" label="名称" align="center" show-overflow-tooltip/> |
| | | <el-table-column prop="app" label="流应用名" align="center" show-overflow-tooltip/> |
| | | <el-table-column prop="stream" label="流ID" align="center" show-overflow-tooltip/> |
| | | <el-table-column label="流地址" width="400" align="center" show-overflow-tooltip > |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | |
| | | <el-tag size="medium" v-if="scope.row.type == 'default'"> |
| | | <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i> |
| | | {{scope.row.url}} |
| | | </el-tag> |
| | | <el-tag size="medium" v-if="scope.row.type != 'default'"> |
| | | <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.src_url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i> |
| | | {{scope.row.src_url}} |
| | | </el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="mediaServerId" label="流媒体" width="150" align="center"></el-table-column> |
| | | <el-table-column label="类型" width="100" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium">{{scope.row.type}}</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-tag size="medium" v-if="scope.row.type == 'default'"> |
| | | <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i> |
| | | {{scope.row.url}} |
| | | </el-tag> |
| | | <el-tag size="medium" v-if="scope.row.type != 'default'"> |
| | | <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.src_url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i> |
| | | {{scope.row.src_url}} |
| | | </el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="mediaServerId" label="流媒体" width="150" align="center"></el-table-column> |
| | | <el-table-column label="类型" width="100" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium">{{scope.row.type}}</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="gbId" label="国标编码" width="180" align="center" show-overflow-tooltip/> |
| | | <el-table-column label="状态" width="120" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.status">在线</el-tag> |
| | | <el-tag size="medium" type="info" v-if="!scope.row.status">离线</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="启用" width="120" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.enable">已启用</el-tag> |
| | | <el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="createTime" label="创建时间" align="center" width="150" show-overflow-tooltip/> |
| | | <el-table-column label="转HLS" width="120" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.enable_hls">已启用</el-tag> |
| | | <el-tag size="medium" type="info" v-if="!scope.row.enable_hls">未启用</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="MP4录制" width="120" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.enable_mp4">已启用</el-tag> |
| | | <el-tag size="medium" type="info" v-if="!scope.row.enable_mp4">未启用</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="无人观看自动删除" width="160" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.enable_remove_none_reader">已启用</el-tag> |
| | | <el-tag size="medium" type="info" v-if="!scope.row.enable_remove_none_reader">未启用</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="gbId" label="国标编码" width="180" align="center" show-overflow-tooltip/> |
| | | <el-table-column label="状态" width="120" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.status">在线</el-tag> |
| | | <el-tag size="medium" type="info" v-if="!scope.row.status">离线</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="启用" width="120" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.enable">已启用</el-tag> |
| | | <el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="createTime" label="创建时间" align="center" width="150" show-overflow-tooltip/> |
| | | <el-table-column label="转HLS" width="120" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.enable_hls">已启用</el-tag> |
| | | <el-tag size="medium" type="info" v-if="!scope.row.enable_hls">未启用</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="MP4录制" width="120" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.enable_mp4">已启用</el-tag> |
| | | <el-tag size="medium" type="info" v-if="!scope.row.enable_mp4">未启用</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="无人观看自动删除" width="160" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.enable_remove_none_reader">已启用</el-tag> |
| | | <el-tag size="medium" type="info" v-if="!scope.row.enable_remove_none_reader">未启用</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | |
| | | <el-table-column label="操作" width="360" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button-group> |
| | | <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.enable" @click="play(scope.row)">播放</el-button> |
| | | <el-button size="mini" icon="el-icon-close" type="success" v-if="scope.row.enable" @click="stop(scope.row)">停用</el-button> |
| | | <el-button size="mini" icon="el-icon-check" type="primary" :loading="startBtnLaoding" v-if="!scope.row.enable" @click="start(scope.row)">启用</el-button> |
| | | <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteStreamProxy(scope.row)">删除</el-button> |
| | | </el-button-group> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination |
| | | style="float: right" |
| | | @size-change="handleSizeChange" |
| | | @current-change="currentChange" |
| | | :current-page="currentPage" |
| | | :page-size="count" |
| | | :page-sizes="[15, 25, 35, 50]" |
| | | layout="total, sizes, prev, pager, next" |
| | | :total="total"> |
| | | </el-pagination> |
| | | <streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit> |
| | | <onvifEdit ref="onvifEdit" ></onvifEdit> |
| | | </el-main> |
| | | </el-container> |
| | | <el-table-column label="操作" width="360" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button-group> |
| | | <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.enable" @click="play(scope.row)">播放</el-button> |
| | | <el-button size="mini" icon="el-icon-close" type="success" v-if="scope.row.enable" @click="stop(scope.row)">停用</el-button> |
| | | <el-button size="mini" icon="el-icon-check" type="primary" :loading="startBtnLaoding" v-if="!scope.row.enable" @click="start(scope.row)">启用</el-button> |
| | | <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteStreamProxy(scope.row)">删除</el-button> |
| | | </el-button-group> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination |
| | | style="float: right" |
| | | @size-change="handleSizeChange" |
| | | @current-change="currentChange" |
| | | :current-page="currentPage" |
| | | :page-size="count" |
| | | :page-sizes="[15, 25, 35, 50]" |
| | | layout="total, sizes, prev, pager, next" |
| | | :total="total"> |
| | | </el-pagination> |
| | | <streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit> |
| | | <onvifEdit ref="onvifEdit" ></onvifEdit> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import streamProxyEdit from './dialog/StreamProxyEdit.vue' |
| | | import onvifEdit from './dialog/onvifEdit.vue' |
| | | import devicePlayer from './dialog/devicePlayer.vue' |
| | | import uiHeader from './UiHeader.vue' |
| | | import uiHeader from '../layout/UiHeader.vue' |
| | | export default { |
| | | name: 'streamProxyList', |
| | | components: { |
| | |
| | | <template> |
| | | <div id="channelList"> |
| | | <el-container> |
| | | <el-header> |
| | | <uiHeader></uiHeader> |
| | | </el-header> |
| | | <el-main> |
| | | <div style="background-color: #FFFFFF; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center;"> |
| | | <span style="font-size: 1rem; font-weight: 500; ">通道列表({{parentChannelId ==0 ? deviceId:parentChannelId}})</span> |
| | | <div id="channelList"> |
| | | <div style="background-color: #FFFFFF; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center;"> |
| | | <span |
| | | style="font-size: 1rem; font-weight: 500; ">通道列表({{ parentChannelId == 0 ? deviceId : parentChannelId }})</span> |
| | | |
| | | </div> |
| | | <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;"> |
| | | <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem;" type="primary" @click="showDevice">返回</el-button> |
| | | 搜索: <el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字" prefix-icon="el-icon-search" v-model="searchSrt" clearable> </el-input> |
| | | </div> |
| | | <div |
| | | style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;"> |
| | | <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem;" type="primary" @click="showDevice"> |
| | | 返回 |
| | | </el-button> |
| | | 搜索: |
| | | <el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字" |
| | | prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input> |
| | | |
| | | 通道类型: <el-select size="mini" @change="search" style="margin-right: 1rem;" v-model="channelType" placeholder="请选择" default-first-option> |
| | | <el-option label="全部" value=""></el-option> |
| | | <el-option label="设备" value="false"></el-option> |
| | | <el-option label="子目录" value="true"></el-option> |
| | | </el-select> |
| | | 在线状态: <el-select size="mini" style="margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择" default-first-option> |
| | | <el-option label="全部" value=""></el-option> |
| | | <el-option label="在线" value="true"></el-option> |
| | | <el-option label="离线" value="false"></el-option> |
| | | </el-select> |
| | | <el-checkbox size="mini" style="margin-right: 1rem; float: right;" v-model="autoList" @change="autoListChange">自动刷新</el-checkbox> |
| | | </div> |
| | | <devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer> |
| | | <!--设备列表--> |
| | | <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" border style="width: 100%"> |
| | | <el-table-column prop="channelId" label="通道编号" width="200"> |
| | | </el-table-column> |
| | | <el-table-column prop="name" label="通道名称"> |
| | | </el-table-column> |
| | | <el-table-column label="快照" width="80" align="center"> |
| | | <template slot-scope="scope"> |
| | | <img style="max-height: 3rem;max-width: 4rem;" |
| | | :id="scope.row.deviceId + '_' + scope.row.channelId" |
| | | :src="getSnap(scope.row)" |
| | | @error="getSnapErrorEvent($event.target.id)" |
| | | alt=""> |
| | | <!-- <el-image--> |
| | | <!-- :id="'snapImg_' + scope.row.deviceId + '_' + scope.row.channelId"--> |
| | | <!-- :src="getSnap(scope.row)"--> |
| | | <!-- @error="getSnapErrorEvent($event, scope.row)"--> |
| | | <!-- :fit="'contain'">--> |
| | | <!-- <div slot="error" class="image-slot">--> |
| | | <!-- <i class="el-icon-picture-outline"></i>--> |
| | | <!-- </div>--> |
| | | <!-- </el-image>--> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="subCount" label="子节点数"> |
| | | </el-table-column> |
| | | <el-table-column prop="manufacture" label="厂家"> |
| | | </el-table-column> |
| | | <el-table-column label="位置信息" align="center"> |
| | | <template slot-scope="scope"> |
| | | <span>{{scope.row.longitude}},{{scope.row.latitude}}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="ptztypeText" label="云台类型"/> |
| | | <el-table-column label="开启音频" align="center"> |
| | | <template slot-scope="scope"> |
| | | <el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF"> |
| | | </el-switch> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="状态" width="180" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.status == 1">开启</el-tag> |
| | | <el-tag size="medium" type="info" v-if="scope.row.status == 0">关闭</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | 通道类型: |
| | | <el-select size="mini" @change="search" style="margin-right: 1rem;" v-model="channelType" placeholder="请选择" |
| | | default-first-option> |
| | | <el-option label="全部" value=""></el-option> |
| | | <el-option label="设备" value="false"></el-option> |
| | | <el-option label="子目录" value="true"></el-option> |
| | | </el-select> |
| | | 在线状态: |
| | | <el-select size="mini" style="margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择" |
| | | default-first-option> |
| | | <el-option label="全部" value=""></el-option> |
| | | <el-option label="在线" value="true"></el-option> |
| | | <el-option label="离线" value="false"></el-option> |
| | | </el-select> |
| | | <el-checkbox size="mini" style="margin-right: 1rem; float: right;" v-model="autoList" @change="autoListChange"> |
| | | 自动刷新 |
| | | </el-checkbox> |
| | | </div> |
| | | <devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer> |
| | | <!--设备列表--> |
| | | <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" border style="width: 100%"> |
| | | <el-table-column prop="channelId" label="通道编号" width="200"> |
| | | </el-table-column> |
| | | <el-table-column prop="name" label="通道名称"> |
| | | </el-table-column> |
| | | <el-table-column label="快照" width="80" align="center"> |
| | | <template slot-scope="scope"> |
| | | <img style="max-height: 3rem;max-width: 4rem;" |
| | | :id="scope.row.deviceId + '_' + scope.row.channelId" |
| | | :src="getSnap(scope.row)" |
| | | @error="getSnapErrorEvent($event.target.id)" |
| | | alt=""> |
| | | <!-- <el-image--> |
| | | <!-- :id="'snapImg_' + scope.row.deviceId + '_' + scope.row.channelId"--> |
| | | <!-- :src="getSnap(scope.row)"--> |
| | | <!-- @error="getSnapErrorEvent($event, scope.row)"--> |
| | | <!-- :fit="'contain'">--> |
| | | <!-- <div slot="error" class="image-slot">--> |
| | | <!-- <i class="el-icon-picture-outline"></i>--> |
| | | <!-- </div>--> |
| | | <!-- </el-image>--> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="subCount" label="子节点数"> |
| | | </el-table-column> |
| | | <el-table-column prop="manufacture" label="厂家"> |
| | | </el-table-column> |
| | | <el-table-column label="位置信息" align="center"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ scope.row.longitude }},{{ scope.row.latitude }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="ptztypeText" label="云台类型"/> |
| | | <el-table-column label="开启音频" align="center"> |
| | | <template slot-scope="scope"> |
| | | <el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF"> |
| | | </el-switch> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="状态" width="180" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.status == 1">开启</el-tag> |
| | | <el-tag size="medium" type="info" v-if="scope.row.status == 0">关闭</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | |
| | | <el-table-column label="操作" width="280" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button-group> |
| | | <!-- <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">播放</el-button> --> |
| | | <el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">播放</el-button> |
| | | <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" @click="stopDevicePush(scope.row)">停止</el-button> |
| | | <el-button size="mini" icon="el-icon-s-open" type="primary" v-if="scope.row.subCount > 0" @click="changeSubchannel(scope.row)">查看</el-button> |
| | | <el-button size="mini" icon="el-icon-video-camera" type="primary" @click="queryRecords(scope.row)">设备录象</el-button> |
| | | <!-- <el-button size="mini" @click="sendDevicePush(scope.row)">录像查询</el-button> --> |
| | | </el-button-group> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination style="float: right" @size-change="handleSizeChange" @current-change="currentChange" :current-page="currentPage" :page-size="count" :page-sizes="[15, 20, 30, 50]" layout="total, sizes, prev, pager, next" :total="total"> |
| | | </el-pagination> |
| | | |
| | | </el-main> |
| | | </el-container> |
| | | </div> |
| | | <el-table-column label="操作" width="280" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button-group> |
| | | <!-- <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">播放</el-button> --> |
| | | <el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">播放</el-button> |
| | | <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" |
| | | @click="stopDevicePush(scope.row)">停止 |
| | | </el-button> |
| | | <el-button size="mini" icon="el-icon-s-open" type="primary" v-if="scope.row.subCount > 0" |
| | | @click="changeSubchannel(scope.row)">查看 |
| | | </el-button> |
| | | <el-button size="mini" icon="el-icon-video-camera" type="primary" @click="queryRecords(scope.row)">设备录象 |
| | | </el-button> |
| | | <!-- <el-button size="mini" @click="sendDevicePush(scope.row)">录像查询</el-button> --> |
| | | </el-button-group> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination style="float: right" @size-change="handleSizeChange" @current-change="currentChange" |
| | | :current-page="currentPage" :page-size="count" :page-sizes="[15, 20, 30, 50]" |
| | | layout="total, sizes, prev, pager, next" :total="total"> |
| | | </el-pagination> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import devicePlayer from './dialog/devicePlayer.vue' |
| | | import uiHeader from './UiHeader.vue' |
| | | import uiHeader from '../layout/UiHeader.vue' |
| | | import moment from "moment"; |
| | | |
| | | export default { |
| | | name: 'channelList', |
| | | components: { |
| | | devicePlayer, |
| | | uiHeader |
| | | }, |
| | | data() { |
| | | return { |
| | | deviceId: this.$route.params.deviceId, |
| | | parentChannelId: this.$route.params.parentChannelId, |
| | | deviceChannelList: [], |
| | | videoComponentList: [], |
| | | currentPlayerInfo: {}, //当前播放对象 |
| | | updateLooper: 0, //数据刷新轮训标志 |
| | | searchSrt: "", |
| | | channelType: "", |
| | | online: "", |
| | | winHeight: window.innerHeight - 250, |
| | | currentPage: parseInt(this.$route.params.page), |
| | | count: parseInt(this.$route.params.count), |
| | | total: 0, |
| | | beforeUrl: "/deviceList", |
| | | isLoging: false, |
| | | autoList: true, |
| | | loadSnap:{} |
| | | }; |
| | | }, |
| | | name: 'channelList', |
| | | components: { |
| | | devicePlayer, |
| | | uiHeader |
| | | }, |
| | | data() { |
| | | return { |
| | | deviceId: this.$route.params.deviceId, |
| | | parentChannelId: this.$route.params.parentChannelId, |
| | | deviceChannelList: [], |
| | | videoComponentList: [], |
| | | currentPlayerInfo: {}, //当前播放对象 |
| | | updateLooper: 0, //数据刷新轮训标志 |
| | | searchSrt: "", |
| | | channelType: "", |
| | | online: "", |
| | | winHeight: window.innerHeight - 250, |
| | | currentPage: parseInt(this.$route.params.page), |
| | | count: parseInt(this.$route.params.count), |
| | | total: 0, |
| | | beforeUrl: "/deviceList", |
| | | isLoging: false, |
| | | autoList: true, |
| | | loadSnap: {} |
| | | }; |
| | | }, |
| | | |
| | | mounted() { |
| | | this.initData(); |
| | | if (this.autoList) { |
| | | this.updateLooper = setInterval(this.initData, 5000); |
| | | } |
| | | |
| | | }, |
| | | destroyed() { |
| | | this.$destroy('videojs'); |
| | | clearTimeout(this.updateLooper); |
| | | }, |
| | | methods: { |
| | | initData: function () { |
| | | if (typeof (this.parentChannelId) == "undefined" || this.parentChannelId == 0) { |
| | | this.getDeviceChannelList(); |
| | | } else { |
| | | this.showSubchannels(); |
| | | } |
| | | }, |
| | | initParam: function () { |
| | | this.deviceId = this.$route.params.deviceId; |
| | | this.parentChannelId = this.$route.params.parentChannelId; |
| | | this.currentPage = parseInt(this.$route.params.page); |
| | | this.count = parseInt(this.$route.params.count); |
| | | if (this.parentChannelId == "" || this.parentChannelId == 0) { |
| | | this.beforeUrl = "/deviceList" |
| | | } |
| | | |
| | | }, |
| | | currentChange: function (val) { |
| | | var url = `/${this.$router.currentRoute.name}/${this.deviceId}/${this.parentChannelId}/${this.count}/${val}` |
| | | this.$router.push(url).then(() => { |
| | | this.initParam(); |
| | | this.initData(); |
| | | }) |
| | | }, |
| | | handleSizeChange: function (val) { |
| | | var url = `/${this.$router.currentRoute.name}/${this.$router.params.deviceId}/${this.$router.params.parentChannelId}/${val}/1` |
| | | this.$router.push(url).then(() => { |
| | | this.initParam(); |
| | | this.initData(); |
| | | }) |
| | | |
| | | }, |
| | | getDeviceChannelList: function () { |
| | | let that = this; |
| | | if (typeof (this.$route.params.deviceId) == "undefined") return; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: `/api/device/query/devices/${this.$route.params.deviceId}/channels`, |
| | | params:{ |
| | | page: that.currentPage, |
| | | count: that.count, |
| | | query: that.searchSrt, |
| | | online: that.online, |
| | | channelType: that.channelType |
| | | } |
| | | }).then(function (res) { |
| | | that.total = res.data.total; |
| | | that.deviceChannelList = res.data.list; |
| | | // 防止出现表格错位 |
| | | that.$nextTick(() => { |
| | | that.$refs.channelListTable.doLayout(); |
| | | }) |
| | | }).catch(function (error) { |
| | | console.log(error); |
| | | }); |
| | | }, |
| | | |
| | | //通知设备上传媒体流 |
| | | sendDevicePush: function (itemData) { |
| | | let deviceId = this.deviceId; |
| | | this.isLoging = true; |
| | | let channelId = itemData.channelId; |
| | | console.log("通知设备推流1:" + deviceId + " : " + channelId ); |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/play/start/' + deviceId + '/' + channelId |
| | | }).then(function (res) { |
| | | that.isLoging = false; |
| | | if (res.data.code === 0) { |
| | | |
| | | setTimeout(()=>{ |
| | | |
| | | let snapId = deviceId + "_" + channelId; |
| | | that.loadSnap[snapId] = 0; |
| | | that.getSnapErrorEvent(snapId) |
| | | },5000) |
| | | that.$refs.devicePlayer.openDialog("media", deviceId, channelId, { |
| | | streamInfo: res.data.data, |
| | | hasAudio: itemData.hasAudio |
| | | }); |
| | | setTimeout(()=>{ |
| | | that.initData(); |
| | | },1000) |
| | | |
| | | }else { |
| | | that.$message.error(res.data.msg); |
| | | } |
| | | }).catch(function (e) {}); |
| | | }, |
| | | queryRecords: function (itemData) { |
| | | var format = moment().format("YYYY-M-D"); |
| | | let deviceId = this.deviceId; |
| | | let channelId = itemData.channelId; |
| | | this.$refs.devicePlayer.openDialog("record", deviceId, channelId, {date: format}) |
| | | }, |
| | | stopDevicePush: function (itemData) { |
| | | var that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/play/stop/' + this.deviceId + "/" + itemData.channelId |
| | | }).then(function (res) { |
| | | that.initData(); |
| | | }).catch(function (error) { |
| | | if (error.response.status === 402) { // 已经停止过 |
| | | that.initData(); |
| | | }else { |
| | | console.log(error) |
| | | } |
| | | }); |
| | | }, |
| | | getSnap: function (row){ |
| | | return '/static/snap/' + row.deviceId + '_' + row.channelId + '.jpg' |
| | | }, |
| | | getSnapErrorEvent: function (id){ |
| | | |
| | | if (typeof (this.loadSnap[id]) != "undefined") { |
| | | console.log("下载截图" + this.loadSnap[id]) |
| | | if (this.loadSnap[id] > 5) { |
| | | delete this.loadSnap[id]; |
| | | return; |
| | | } |
| | | setTimeout(()=>{ |
| | | this.loadSnap[id] ++ |
| | | document.getElementById(id).setAttribute("src", '/static/snap/' + id + '.jpg?' + new Date().getTime()) |
| | | },1000) |
| | | |
| | | } |
| | | }, |
| | | showDevice: function () { |
| | | this.$router.push(this.beforeUrl).then(() => { |
| | | this.initParam(); |
| | | this.initData(); |
| | | }) |
| | | }, |
| | | changeSubchannel(itemData) { |
| | | this.beforeUrl = this.$router.currentRoute.path; |
| | | |
| | | var url = `/${this.$router.currentRoute.name}/${this.$router.currentRoute.params.deviceId}/${itemData.channelId}/${this.$router.currentRoute.params.count}/1` |
| | | this.$router.push(url).then(() => { |
| | | this.searchSrt = ""; |
| | | this.channelType = ""; |
| | | this.online = ""; |
| | | this.initParam(); |
| | | this.initData(); |
| | | }) |
| | | }, |
| | | showSubchannels: function (channelId) { |
| | | let that = this; |
| | | |
| | | this.$axios({ |
| | | method: 'get', |
| | | url:`/api/device/query/sub_channels/${this.deviceId}/${this.parentChannelId}/channels`, |
| | | params: { |
| | | page: that.currentPage, |
| | | count: that.count, |
| | | query: that.searchSrt, |
| | | online: that.online, |
| | | channelType: that.channelType |
| | | } |
| | | }).then(function (res) { |
| | | that.total = res.data.total; |
| | | that.deviceChannelList = res.data.list; |
| | | // 防止出现表格错位 |
| | | that.$nextTick(() => { |
| | | that.$refs.channelListTable.doLayout(); |
| | | }) |
| | | }).catch(function (error) { |
| | | console.log(error); |
| | | }); |
| | | }, |
| | | search: function () { |
| | | this.currentPage = 1; |
| | | this.total = 0; |
| | | this.initData(); |
| | | }, |
| | | updateChannel: function (row) { |
| | | this.$axios({ |
| | | method: 'post', |
| | | url: `/api/device/query/channel/update/${this.deviceId}`, |
| | | params: row |
| | | }).then(function (res) { |
| | | console.log(JSON.stringify(res)); |
| | | }); |
| | | }, |
| | | autoListChange: function () { |
| | | if (this.autoList) { |
| | | this.updateLooper = setInterval(this.initData, 1500); |
| | | }else{ |
| | | window.clearInterval(this.updateLooper); |
| | | } |
| | | } |
| | | |
| | | mounted() { |
| | | this.initData(); |
| | | if (this.autoList) { |
| | | this.updateLooper = setInterval(this.initData, 5000); |
| | | } |
| | | |
| | | }, |
| | | destroyed() { |
| | | this.$destroy('videojs'); |
| | | clearTimeout(this.updateLooper); |
| | | }, |
| | | methods: { |
| | | initData: function () { |
| | | if (typeof (this.parentChannelId) == "undefined" || this.parentChannelId == 0) { |
| | | this.getDeviceChannelList(); |
| | | } else { |
| | | this.showSubchannels(); |
| | | } |
| | | }, |
| | | initParam: function () { |
| | | this.deviceId = this.$route.params.deviceId; |
| | | this.parentChannelId = this.$route.params.parentChannelId; |
| | | this.currentPage = parseInt(this.$route.params.page); |
| | | this.count = parseInt(this.$route.params.count); |
| | | if (this.parentChannelId == "" || this.parentChannelId == 0) { |
| | | this.beforeUrl = "/deviceList" |
| | | } |
| | | |
| | | }, |
| | | currentChange: function (val) { |
| | | var url = `/${this.$router.currentRoute.name}/${this.deviceId}/${this.parentChannelId}/${this.count}/${val}` |
| | | this.$router.push(url).then(() => { |
| | | this.initParam(); |
| | | this.initData(); |
| | | }) |
| | | }, |
| | | handleSizeChange: function (val) { |
| | | var url = `/${this.$router.currentRoute.name}/${this.$router.params.deviceId}/${this.$router.params.parentChannelId}/${val}/1` |
| | | this.$router.push(url).then(() => { |
| | | this.initParam(); |
| | | this.initData(); |
| | | }) |
| | | |
| | | }, |
| | | getDeviceChannelList: function () { |
| | | let that = this; |
| | | if (typeof (this.$route.params.deviceId) == "undefined") return; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: `/api/device/query/devices/${this.$route.params.deviceId}/channels`, |
| | | params: { |
| | | page: that.currentPage, |
| | | count: that.count, |
| | | query: that.searchSrt, |
| | | online: that.online, |
| | | channelType: that.channelType |
| | | } |
| | | }).then(function (res) { |
| | | that.total = res.data.total; |
| | | that.deviceChannelList = res.data.list; |
| | | // 防止出现表格错位 |
| | | that.$nextTick(() => { |
| | | that.$refs.channelListTable.doLayout(); |
| | | }) |
| | | }).catch(function (error) { |
| | | console.log(error); |
| | | }); |
| | | }, |
| | | |
| | | //通知设备上传媒体流 |
| | | sendDevicePush: function (itemData) { |
| | | let deviceId = this.deviceId; |
| | | this.isLoging = true; |
| | | let channelId = itemData.channelId; |
| | | console.log("通知设备推流1:" + deviceId + " : " + channelId); |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/play/start/' + deviceId + '/' + channelId |
| | | }).then(function (res) { |
| | | that.isLoging = false; |
| | | if (res.data.code === 0) { |
| | | |
| | | setTimeout(() => { |
| | | |
| | | let snapId = deviceId + "_" + channelId; |
| | | that.loadSnap[snapId] = 0; |
| | | that.getSnapErrorEvent(snapId) |
| | | }, 5000) |
| | | that.$refs.devicePlayer.openDialog("media", deviceId, channelId, { |
| | | streamInfo: res.data.data, |
| | | hasAudio: itemData.hasAudio |
| | | }); |
| | | setTimeout(() => { |
| | | that.initData(); |
| | | }, 1000) |
| | | |
| | | } else { |
| | | that.$message.error(res.data.msg); |
| | | } |
| | | }).catch(function (e) { |
| | | }); |
| | | }, |
| | | queryRecords: function (itemData) { |
| | | var format = moment().format("YYYY-M-D"); |
| | | let deviceId = this.deviceId; |
| | | let channelId = itemData.channelId; |
| | | this.$refs.devicePlayer.openDialog("record", deviceId, channelId, {date: format}) |
| | | }, |
| | | stopDevicePush: function (itemData) { |
| | | var that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/play/stop/' + this.deviceId + "/" + itemData.channelId |
| | | }).then(function (res) { |
| | | that.initData(); |
| | | }).catch(function (error) { |
| | | if (error.response.status === 402) { // 已经停止过 |
| | | that.initData(); |
| | | } else { |
| | | console.log(error) |
| | | } |
| | | }); |
| | | }, |
| | | getSnap: function (row) { |
| | | return '/static/snap/' + row.deviceId + '_' + row.channelId + '.jpg' |
| | | }, |
| | | getSnapErrorEvent: function (id) { |
| | | |
| | | if (typeof (this.loadSnap[id]) != "undefined") { |
| | | console.log("下载截图" + this.loadSnap[id]) |
| | | if (this.loadSnap[id] > 5) { |
| | | delete this.loadSnap[id]; |
| | | return; |
| | | } |
| | | setTimeout(() => { |
| | | this.loadSnap[id]++ |
| | | document.getElementById(id).setAttribute("src", '/static/snap/' + id + '.jpg?' + new Date().getTime()) |
| | | }, 1000) |
| | | |
| | | } |
| | | }, |
| | | showDevice: function () { |
| | | this.$router.push(this.beforeUrl).then(() => { |
| | | this.initParam(); |
| | | this.initData(); |
| | | }) |
| | | }, |
| | | changeSubchannel(itemData) { |
| | | this.beforeUrl = this.$router.currentRoute.path; |
| | | |
| | | var url = `/${this.$router.currentRoute.name}/${this.$router.currentRoute.params.deviceId}/${itemData.channelId}/${this.$router.currentRoute.params.count}/1` |
| | | this.$router.push(url).then(() => { |
| | | this.searchSrt = ""; |
| | | this.channelType = ""; |
| | | this.online = ""; |
| | | this.initParam(); |
| | | this.initData(); |
| | | }) |
| | | }, |
| | | showSubchannels: function (channelId) { |
| | | let that = this; |
| | | |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: `/api/device/query/sub_channels/${this.deviceId}/${this.parentChannelId}/channels`, |
| | | params: { |
| | | page: that.currentPage, |
| | | count: that.count, |
| | | query: that.searchSrt, |
| | | online: that.online, |
| | | channelType: that.channelType |
| | | } |
| | | }).then(function (res) { |
| | | that.total = res.data.total; |
| | | that.deviceChannelList = res.data.list; |
| | | // 防止出现表格错位 |
| | | that.$nextTick(() => { |
| | | that.$refs.channelListTable.doLayout(); |
| | | }) |
| | | }).catch(function (error) { |
| | | console.log(error); |
| | | }); |
| | | }, |
| | | search: function () { |
| | | this.currentPage = 1; |
| | | this.total = 0; |
| | | this.initData(); |
| | | }, |
| | | updateChannel: function (row) { |
| | | this.$axios({ |
| | | method: 'post', |
| | | url: `/api/device/query/channel/update/${this.deviceId}`, |
| | | params: row |
| | | }).then(function (res) { |
| | | console.log(JSON.stringify(res)); |
| | | }); |
| | | }, |
| | | autoListChange: function () { |
| | | if (this.autoList) { |
| | | this.updateLooper = setInterval(this.initData, 1500); |
| | | } else { |
| | | window.clearInterval(this.updateLooper); |
| | | } |
| | | } |
| | | |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | .videoList { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-content: flex-start; |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-content: flex-start; |
| | | } |
| | | |
| | | .video-item { |
| | | position: relative; |
| | | width: 15rem; |
| | | height: 10rem; |
| | | margin-right: 1rem; |
| | | background-color: #000000; |
| | | position: relative; |
| | | width: 15rem; |
| | | height: 10rem; |
| | | margin-right: 1rem; |
| | | background-color: #000000; |
| | | } |
| | | |
| | | .video-item-img { |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 100%; |
| | | height: 100%; |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .video-item-img:after { |
| | | content: ""; |
| | | display: inline-block; |
| | | position: absolute; |
| | | z-index: 2; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 3rem; |
| | | height: 3rem; |
| | | background-image: url("../assets/loading.png"); |
| | | background-size: cover; |
| | | background-color: #000000; |
| | | content: ""; |
| | | display: inline-block; |
| | | position: absolute; |
| | | z-index: 2; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 3rem; |
| | | height: 3rem; |
| | | background-image: url("../assets/loading.png"); |
| | | background-size: cover; |
| | | background-color: #000000; |
| | | } |
| | | |
| | | .video-item-title { |
| | | position: absolute; |
| | | bottom: 0; |
| | | color: #000000; |
| | | background-color: #ffffff; |
| | | line-height: 1.5rem; |
| | | padding: 0.3rem; |
| | | width: 14.4rem; |
| | | position: absolute; |
| | | bottom: 0; |
| | | color: #000000; |
| | | background-color: #ffffff; |
| | | line-height: 1.5rem; |
| | | padding: 0.3rem; |
| | | width: 14.4rem; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div id="app"> |
| | | <el-container> |
| | | <el-header> |
| | | <uiHeader></uiHeader> |
| | | </el-header> |
| | | <el-main> |
| | | <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;"> |
| | | <span style="font-size: 1rem; font-weight: bold;">控制台</span> |
| | | <div style="position: absolute; right: 17rem; top: 0.3rem;"> |
| | | 节点选择: <el-select size="mini" @change="chooseMediaChange" style="width: 18rem; margin-right: 8rem;" v-model="mediaServerChoose" placeholder="请选择" default-first-option> |
| | | <el-option |
| | | v-for="item in mediaServerList" |
| | | :key="item.id" |
| | | :label="item.id + '( ' + item.streamIp + ' )'" |
| | | :value="item.id"> |
| | | </el-option> |
| | | </el-select> |
| | | <span >{{loadCount}}</span> |
| | | </div> |
| | | <div style="position: absolute; right: 1rem; top: 0.3rem;"> |
| | | <el-popover placement="bottom" width="900" height="300" trigger="click"> |
| | | <div style="height: 600px; overflow:auto; padding: 20px"> |
| | | <el-descriptions v-for="(value, key, index) in serverConfig" :key="key" border :column="1" style="margin-bottom: 1rem"> |
| | | <template slot="title"> |
| | | {{key}} |
| | | </template> |
| | | <el-descriptions-item v-for="(value1, key1, index1) in serverConfig[key]" :key="key1"> |
| | | <template slot="label" > |
| | | {{ getMediaKeyNameFromKey(key1) }} |
| | | </template> |
| | | {{ value1 }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </div> |
| | | <el-button type="primary" slot="reference" size="mini" @click="getServerConfig()">媒体服务器配置</el-button> |
| | | </el-popover> |
| | | <el-popover placement="bottom" width="900" height="300" trigger="click"> |
| | | <div style="height: 600px;overflow:auto; padding: 20px"> |
| | | <el-descriptions title="国标配置" border :column="1"> |
| | | <template slot="extra"> |
| | | <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="JSON.stringify(wvpServerConfig.sip)|| ''" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button> |
| | | </template> |
| | | <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.sip" :key="key"> |
| | | <template slot="label"> |
| | | {{ getNameFromKey(key) }} |
| | | </template> |
| | | {{ value }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <div id="app" style="width: 100%"> |
| | | <div class="page-header"> |
| | | <div class="page-title">控制台</div> |
| | | <div class="page-header-btn"> |
| | | 节点选择: |
| | | <el-select size="mini" @change="chooseMediaChange" style="width: 18rem; margin-right: 8rem;" |
| | | v-model="mediaServerChoose" placeholder="请选择" default-first-option> |
| | | <el-option |
| | | v-for="item in mediaServerList" |
| | | :key="item.id" |
| | | :label="item.id + '( ' + item.streamIp + ' )'" |
| | | :value="item.id"> |
| | | </el-option> |
| | | </el-select> |
| | | <span>{{ loadCount }}</span> |
| | | </div> |
| | | <div class="page-header-btn"> |
| | | <el-popover placement="bottom" width="900" height="300" trigger="click"> |
| | | <div style="height: 600px; overflow:auto; padding: 20px"> |
| | | <el-descriptions v-for="(value, key, index) in serverConfig" :key="key" border :column="1" |
| | | style="margin-bottom: 1rem"> |
| | | <template slot="title"> |
| | | {{ key }} |
| | | </template> |
| | | <el-descriptions-item v-for="(value1, key1, index1) in serverConfig[key]" :key="key1"> |
| | | <template slot="label"> |
| | | {{ getMediaKeyNameFromKey(key1) }} |
| | | </template> |
| | | {{ value1 }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </div> |
| | | <el-button type="primary" slot="reference" size="mini" @click="getServerConfig()">媒体服务器配置</el-button> |
| | | </el-popover> |
| | | <el-popover placement="bottom" width="900" height="300" trigger="click"> |
| | | <div style="height: 600px;overflow:auto; padding: 20px"> |
| | | <el-descriptions title="国标配置" border :column="1"> |
| | | <template slot="extra"> |
| | | <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" |
| | | v-clipboard="JSON.stringify(wvpServerConfig.sip)|| ''" |
| | | @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button> |
| | | </template> |
| | | <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.sip" :key="key"> |
| | | <template slot="label"> |
| | | {{ getNameFromKey(key) }} |
| | | </template> |
| | | {{ value }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <div style="margin-top: 1rem"> |
| | | <el-descriptions title="基础配置" border :column="1"> |
| | | <template slot="extra"> |
| | | <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="JSON.stringify(wvpServerConfig.base)|| ''" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button> |
| | | </template> |
| | | <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.base" :key="key"> |
| | | <template slot="label" > |
| | | {{ getNameFromKey(key) }} |
| | | </template> |
| | | <div v-if="key === 'interfaceAuthenticationExcludes'"> |
| | | <el-dropdown> |
| | | <div style="margin-top: 1rem"> |
| | | <el-descriptions title="基础配置" border :column="1"> |
| | | <template slot="extra"> |
| | | <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" |
| | | v-clipboard="JSON.stringify(wvpServerConfig.base)|| ''" |
| | | @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button> |
| | | </template> |
| | | <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.base" :key="key"> |
| | | <template slot="label"> |
| | | {{ getNameFromKey(key) }} |
| | | </template> |
| | | <div v-if="key === 'interfaceAuthenticationExcludes'"> |
| | | <el-dropdown> |
| | | <span class="el-dropdown-link"> |
| | | 查看<i class="el-icon-arrow-down el-icon--right"></i> |
| | | </span> |
| | | <el-dropdown-menu slot="dropdown"> |
| | | <el-dropdown-item v-for="(value, key, index) in wvpServerConfig.base.interfaceAuthenticationExcludes" :key="key">{{value}}</el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </el-dropdown> |
| | | </div> |
| | | <div v-if="key !== 'interfaceAuthenticationExcludes'"> |
| | | <div v-if="value === true"> |
| | | 已启用 |
| | | </div> |
| | | <div v-if="value === false"> |
| | | 未启用 |
| | | </div> |
| | | <div v-if="value !== true && value !== false"> |
| | | {{ value }} |
| | | </div> |
| | | </div> |
| | | <el-dropdown-menu slot="dropdown"> |
| | | <el-dropdown-item |
| | | v-for="(value, key, index) in wvpServerConfig.base.interfaceAuthenticationExcludes" |
| | | :key="key">{{ value }} |
| | | </el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </el-dropdown> |
| | | </div> |
| | | <div v-if="key !== 'interfaceAuthenticationExcludes'"> |
| | | <div v-if="value === true"> |
| | | 已启用 |
| | | </div> |
| | | <div v-if="value === false"> |
| | | 未启用 |
| | | </div> |
| | | <div v-if="value !== true && value !== false"> |
| | | {{ value }} |
| | | </div> |
| | | </div> |
| | | |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </div> |
| | | <div style="margin-top: 1rem"> |
| | | <el-descriptions title="版本信息" border :column="1"> |
| | | <template slot="extra"> |
| | | <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="JSON.stringify(wvpServerVersion) || ''" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button> |
| | | </template> |
| | | <el-descriptions-item v-for="(value, key, index) in wvpServerVersion" :key="key"> |
| | | <template slot="label"> |
| | | {{ getNameFromKey(key) }} |
| | | </template> |
| | | {{ value }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | |
| | | </div> |
| | | </div> |
| | | <el-button type="primary" slot="reference" size="mini" @click="getWVPServerConfig()">信令服务器配置</el-button> |
| | | </el-popover> |
| | | <el-button style="margin-left: 1rem;" type="danger" size="mini" @click="reStartServer()">重启媒体服务器</el-button> |
| | | </div> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </div> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="control-table" id="ThreadsLoad">table1</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="control-table" id="WorkThreadsLoad">table2</div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-table :data="allSessionData" style="margin-top: 1rem;"> |
| | | <el-table-column prop="peer_ip" label="远端"></el-table-column> |
| | | <el-table-column prop="local_ip" label="本地"></el-table-column> |
| | | <el-table-column prop="typeid" label="类型"></el-table-column> |
| | | <el-table-column align="right"> |
| | | <template slot="header" slot-scope="scope"> |
| | | <el-button icon="el-icon-refresh-right" circle @click="getAllSession()"></el-button> |
| | | </template> |
| | | <template slot-scope="scope"> |
| | | <el-button @click.native.prevent="deleteRow(scope.$index, allSessionData)" type="text" size="small">移除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <div style="margin-top: 1rem"> |
| | | <el-descriptions title="版本信息" border :column="1"> |
| | | <template slot="extra"> |
| | | <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" |
| | | v-clipboard="JSON.stringify(wvpServerVersion) || ''" |
| | | @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button> |
| | | </template> |
| | | <el-descriptions-item v-for="(value, key, index) in wvpServerVersion" :key="key"> |
| | | <template slot="label"> |
| | | {{ getNameFromKey(key) }} |
| | | </template> |
| | | {{ value }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | </el-main> |
| | | <!-- <el-footer style="position: absolute; bottom: 0; width: 100%;">ZLMediaKit-VUE_UI v1</el-footer> --> |
| | | </el-container> |
| | | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <el-button type="primary" slot="reference" size="mini" @click="getWVPServerConfig()">信令服务器配置</el-button> |
| | | </el-popover> |
| | | <el-button style="margin-left: 1rem;" type="danger" size="mini" @click="reStartServer()">重启媒体服务器</el-button> |
| | | </div> |
| | | </div> |
| | | <!-- <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">--> |
| | | <!-- <span style="font-size: 1rem; font-weight: bold;">控制台</span>--> |
| | | <!-- <div style="position: absolute; right: 17rem; top: 0.3rem;">--> |
| | | <!-- 节点选择:--> |
| | | <!-- <el-select size="mini" @change="chooseMediaChange" style="width: 18rem; margin-right: 8rem;"--> |
| | | <!-- v-model="mediaServerChoose" placeholder="请选择" default-first-option>--> |
| | | <!-- <el-option--> |
| | | <!-- v-for="item in mediaServerList"--> |
| | | <!-- :key="item.id"--> |
| | | <!-- :label="item.id + '( ' + item.streamIp + ' )'"--> |
| | | <!-- :value="item.id">--> |
| | | <!-- </el-option>--> |
| | | <!-- </el-select>--> |
| | | <!-- <span>{{ loadCount }}</span>--> |
| | | <!-- </div>--> |
| | | <!-- <div style="position: absolute; right: 1rem; top: 0.3rem;">--> |
| | | <!-- <el-popover placement="bottom" width="900" height="300" trigger="click">--> |
| | | <!-- <div style="height: 600px; overflow:auto; padding: 20px">--> |
| | | <!-- <el-descriptions v-for="(value, key, index) in serverConfig" :key="key" border :column="1"--> |
| | | <!-- style="margin-bottom: 1rem">--> |
| | | <!-- <template slot="title">--> |
| | | <!-- {{ key }}--> |
| | | <!-- </template>--> |
| | | <!-- <el-descriptions-item v-for="(value1, key1, index1) in serverConfig[key]" :key="key1">--> |
| | | <!-- <template slot="label">--> |
| | | <!-- {{ getMediaKeyNameFromKey(key1) }}--> |
| | | <!-- </template>--> |
| | | <!-- {{ value1 }}--> |
| | | <!-- </el-descriptions-item>--> |
| | | <!-- </el-descriptions>--> |
| | | <!-- </div>--> |
| | | <!-- <el-button type="primary" slot="reference" size="mini" @click="getServerConfig()">媒体服务器配置</el-button>--> |
| | | <!-- </el-popover>--> |
| | | <!-- <el-popover placement="bottom" width="900" height="300" trigger="click">--> |
| | | <!-- <div style="height: 600px;overflow:auto; padding: 20px">--> |
| | | <!-- <el-descriptions title="国标配置" border :column="1">--> |
| | | <!-- <template slot="extra">--> |
| | | <!-- <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝"--> |
| | | <!-- v-clipboard="JSON.stringify(wvpServerConfig.sip)|| ''"--> |
| | | <!-- @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>--> |
| | | <!-- </template>--> |
| | | <!-- <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.sip" :key="key">--> |
| | | <!-- <template slot="label">--> |
| | | <!-- {{ getNameFromKey(key) }}--> |
| | | <!-- </template>--> |
| | | <!-- {{ value }}--> |
| | | <!-- </el-descriptions-item>--> |
| | | <!-- </el-descriptions>--> |
| | | |
| | | <!-- <div style="margin-top: 1rem">--> |
| | | <!-- <el-descriptions title="基础配置" border :column="1">--> |
| | | <!-- <template slot="extra">--> |
| | | <!-- <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝"--> |
| | | <!-- v-clipboard="JSON.stringify(wvpServerConfig.base)|| ''"--> |
| | | <!-- @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>--> |
| | | <!-- </template>--> |
| | | <!-- <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.base" :key="key">--> |
| | | <!-- <template slot="label">--> |
| | | <!-- {{ getNameFromKey(key) }}--> |
| | | <!-- </template>--> |
| | | <!-- <div v-if="key === 'interfaceAuthenticationExcludes'">--> |
| | | <!-- <el-dropdown>--> |
| | | <!-- <span class="el-dropdown-link">--> |
| | | <!-- 查看<i class="el-icon-arrow-down el-icon--right"></i>--> |
| | | <!-- </span>--> |
| | | <!-- <el-dropdown-menu slot="dropdown">--> |
| | | <!-- <el-dropdown-item--> |
| | | <!-- v-for="(value, key, index) in wvpServerConfig.base.interfaceAuthenticationExcludes"--> |
| | | <!-- :key="key">{{ value }}--> |
| | | <!-- </el-dropdown-item>--> |
| | | <!-- </el-dropdown-menu>--> |
| | | <!-- </el-dropdown>--> |
| | | <!-- </div>--> |
| | | <!-- <div v-if="key !== 'interfaceAuthenticationExcludes'">--> |
| | | <!-- <div v-if="value === true">--> |
| | | <!-- 已启用--> |
| | | <!-- </div>--> |
| | | <!-- <div v-if="value === false">--> |
| | | <!-- 未启用--> |
| | | <!-- </div>--> |
| | | <!-- <div v-if="value !== true && value !== false">--> |
| | | <!-- {{ value }}--> |
| | | <!-- </div>--> |
| | | <!-- </div>--> |
| | | |
| | | <!-- </el-descriptions-item>--> |
| | | <!-- </el-descriptions>--> |
| | | <!-- </div>--> |
| | | <!-- <div style="margin-top: 1rem">--> |
| | | <!-- <el-descriptions title="版本信息" border :column="1">--> |
| | | <!-- <template slot="extra">--> |
| | | <!-- <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝"--> |
| | | <!-- v-clipboard="JSON.stringify(wvpServerVersion) || ''"--> |
| | | <!-- @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>--> |
| | | <!-- </template>--> |
| | | <!-- <el-descriptions-item v-for="(value, key, index) in wvpServerVersion" :key="key">--> |
| | | <!-- <template slot="label">--> |
| | | <!-- {{ getNameFromKey(key) }}--> |
| | | <!-- </template>--> |
| | | <!-- {{ value }}--> |
| | | <!-- </el-descriptions-item>--> |
| | | <!-- </el-descriptions>--> |
| | | |
| | | |
| | | <!-- </div>--> |
| | | <!-- </div>--> |
| | | <!-- <el-button type="primary" slot="reference" size="mini" @click="getWVPServerConfig()">信令服务器配置</el-button>--> |
| | | <!-- </el-popover>--> |
| | | <!-- <el-button style="margin-left: 1rem;" type="danger" size="mini" @click="reStartServer()">重启媒体服务器</el-button>--> |
| | | <!-- </div>--> |
| | | <!-- </div>--> |
| | | <el-row style="width: 100%"> |
| | | <el-col :span="12"> |
| | | <div class="control-table" id="ThreadsLoad" style="margin-right:10px;">table1</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="control-table" id="WorkThreadsLoad" style="margin-left:10px;">table2</div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-table :data="allSessionData" style="margin-top: 1rem;"> |
| | | <el-table-column prop="peer_ip" label="远端"></el-table-column> |
| | | <el-table-column prop="local_ip" label="本地"></el-table-column> |
| | | <el-table-column prop="typeid" label="类型"></el-table-column> |
| | | <el-table-column align="right"> |
| | | <template slot="header" slot-scope="scope"> |
| | | <el-button icon="el-icon-refresh-right" circle @click="getAllSession()"></el-button> |
| | | </template> |
| | | <template slot-scope="scope"> |
| | | <el-button @click.native.prevent="deleteRow(scope.$index, allSessionData)" type="text" size="small">移除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import uiHeader from './UiHeader.vue' |
| | | import uiHeader from '../layout/UiHeader.vue' |
| | | import MediaServer from './service/MediaServer' |
| | | |
| | | import echarts from 'echarts'; |
| | | |
| | | export default { |
| | | name: 'app', |
| | | components: { |
| | | echarts, |
| | | uiHeader |
| | | name: 'app', |
| | | components: { |
| | | echarts, |
| | | uiHeader |
| | | }, |
| | | data() { |
| | | return { |
| | | tableOption: { |
| | | // legend: {}, |
| | | xAxis: {}, |
| | | yAxis: {}, |
| | | label: {}, |
| | | tooltip: {}, |
| | | dataZoom: [], |
| | | series: [] |
| | | }, |
| | | table1Option: { |
| | | // legend: {}, |
| | | xAxis: {}, |
| | | yAxis: {}, |
| | | label: {}, |
| | | tooltip: {}, |
| | | series: [] |
| | | }, |
| | | mChart: null, |
| | | mChart1: null, |
| | | charZoomStart: 0, |
| | | charZoomEnd: 100, |
| | | chartInterval: 0, //更新图表统计图定时任务标识 |
| | | allSessionData: [], |
| | | visible: false, |
| | | wvpVisible: false, |
| | | serverConfig: {}, |
| | | wvpServerConfig: {}, |
| | | wvpServerVersion: {}, |
| | | mediaServer: new MediaServer(), |
| | | mediaServerChoose: null, |
| | | loadCount: 0, |
| | | mediaServerList: [] |
| | | }; |
| | | }, |
| | | mounted() { |
| | | this.initTable() |
| | | this.chartInterval = setInterval(this.updateData, 3000); |
| | | this.mediaServer.getOnlineMediaServerList((data) => { |
| | | this.mediaServerList = data.data; |
| | | if (this.mediaServerList && this.mediaServerList.length > 0) { |
| | | this.mediaServerChoose = this.mediaServerList[0].id |
| | | this.loadCount = this.mediaServerList[0].count; |
| | | this.updateData(); |
| | | } |
| | | }) |
| | | }, |
| | | destroyed() { |
| | | clearInterval(this.chartInterval); //释放定时任务 |
| | | }, |
| | | methods: { |
| | | chooseMediaChange: function (val) { |
| | | this.loadCount = 0 |
| | | this.initTable() |
| | | this.updateData(); |
| | | }, |
| | | data() { |
| | | return { |
| | | tableOption: { |
| | | // legend: {}, |
| | | xAxis: {}, |
| | | yAxis: {}, |
| | | label: {}, |
| | | tooltip: {}, |
| | | dataZoom: [], |
| | | series: [] |
| | | }, |
| | | table1Option: { |
| | | // legend: {}, |
| | | xAxis: {}, |
| | | yAxis: {}, |
| | | label: {}, |
| | | tooltip: {}, |
| | | series: [] |
| | | }, |
| | | mChart: null, |
| | | mChart1: null, |
| | | charZoomStart: 0, |
| | | charZoomEnd: 100, |
| | | chartInterval: 0, //更新图表统计图定时任务标识 |
| | | allSessionData: [], |
| | | visible: false, |
| | | wvpVisible: false, |
| | | serverConfig: {}, |
| | | wvpServerConfig: {}, |
| | | wvpServerVersion: {}, |
| | | mediaServer : new MediaServer(), |
| | | mediaServerChoose : null, |
| | | loadCount : 0, |
| | | mediaServerList : [] |
| | | }; |
| | | updateData: function () { |
| | | this.getThreadsLoad(); |
| | | this.getLoadCount(); |
| | | this.getAllSession(); |
| | | }, |
| | | mounted() { |
| | | /** |
| | | * 获取线程状态 |
| | | */ |
| | | getThreadsLoad: function () { |
| | | let that = this; |
| | | if (that.mediaServerChoose != null) { |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/zlm/' + that.mediaServerChoose + '/index/api/getThreadsLoad' |
| | | }).then(function (res) { |
| | | if (res.data.code == 0) { |
| | | that.tableOption.xAxis.data.push(new Date().toLocaleTimeString('chinese', { |
| | | hour12: false |
| | | })); |
| | | that.table1Option.xAxis.data.push(new Date().toLocaleTimeString('chinese', { |
| | | hour12: false |
| | | })); |
| | | |
| | | this.initTable(); |
| | | this.chartInterval = setInterval(this.updateData, 3000); |
| | | this.mediaServer.getOnlineMediaServerList((data)=>{ |
| | | this.mediaServerList = data.data; |
| | | if (this.mediaServerList && this.mediaServerList.length > 0) { |
| | | this.mediaServerChoose = this.mediaServerList[0].id |
| | | this.loadCount = this.mediaServerList[0].count; |
| | | this.updateData(); |
| | | } |
| | | }) |
| | | }, |
| | | destroyed() { |
| | | clearInterval(this.chartInterval); //释放定时任务 |
| | | }, |
| | | methods: { |
| | | chooseMediaChange: function (val) { |
| | | this.loadCount = 0 |
| | | this.initTable() |
| | | this.updateData(); |
| | | }, |
| | | updateData: function () { |
| | | this.getThreadsLoad(); |
| | | this.getLoadCount(); |
| | | this.getAllSession(); |
| | | }, |
| | | /** |
| | | * 获取线程状态 |
| | | */ |
| | | getThreadsLoad: function () { |
| | | let that = this; |
| | | if (that.mediaServerChoose != null) { |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/zlm/' + that.mediaServerChoose +'/index/api/getThreadsLoad' |
| | | }).then(function (res) { |
| | | if (res.data.code == 0) { |
| | | that.tableOption.xAxis.data.push(new Date().toLocaleTimeString('chinese', { |
| | | hour12: false |
| | | })); |
| | | that.table1Option.xAxis.data.push(new Date().toLocaleTimeString('chinese', { |
| | | hour12: false |
| | | })); |
| | | |
| | | for (var i = 0; i < res.data.data.length; i++) { |
| | | if (that.tableOption.series[i] === undefined) { |
| | | let data = { |
| | | data: [], |
| | | type: 'line' |
| | | }; |
| | | let data1 = { |
| | | data: [], |
| | | type: 'line' |
| | | }; |
| | | data.data.push(res.data.data[i].delay); |
| | | data1.data.push(res.data.data[i].load); |
| | | that.tableOption.series.push(data); |
| | | that.table1Option.series.push(data1); |
| | | } else { |
| | | that.tableOption.series[i].data.push(res.data.data[i].delay); |
| | | that.table1Option.series[i].data.push(res.data.data[i].load); |
| | | } |
| | | } |
| | | that.tableOption.dataZoom[0].start = that.charZoomStart; |
| | | that.tableOption.dataZoom[0].end = that.charZoomEnd; |
| | | that.table1Option.dataZoom[0].start = that.charZoomStart; |
| | | that.table1Option.dataZoom[0].end = that.charZoomEnd; |
| | | //that.myChart = echarts.init(document.getElementById('ThreadsLoad')); |
| | | that.myChart.setOption(that.tableOption, true); |
| | | // that.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad')); |
| | | that.myChart1.setOption(that.table1Option, true); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | }, |
| | | getLoadCount: function (){ |
| | | let that = this; |
| | | if (that.mediaServerChoose != null) { |
| | | that.mediaServer.getMediaServer(that.mediaServerChoose, (data)=>{ |
| | | if (data.code == 0) { |
| | | that.loadCount = data.data.count |
| | | for (var i = 0; i < res.data.data.length; i++) { |
| | | if (that.tableOption.series[i] === undefined) { |
| | | let data = { |
| | | data: [], |
| | | type: 'line' |
| | | }; |
| | | let data1 = { |
| | | data: [], |
| | | type: 'line' |
| | | }; |
| | | data.data.push(res.data.data[i].delay); |
| | | data1.data.push(res.data.data[i].load); |
| | | that.tableOption.series.push(data); |
| | | that.table1Option.series.push(data1); |
| | | } else { |
| | | that.tableOption.series[i].data.push(res.data.data[i].delay); |
| | | that.table1Option.series[i].data.push(res.data.data[i].load); |
| | | } |
| | | } |
| | | that.tableOption.dataZoom[0].start = that.charZoomStart; |
| | | that.tableOption.dataZoom[0].end = that.charZoomEnd; |
| | | that.table1Option.dataZoom[0].start = that.charZoomStart; |
| | | that.table1Option.dataZoom[0].end = that.charZoomEnd; |
| | | //that.myChart = echarts.init(document.getElementById('ThreadsLoad')); |
| | | that.myChart.setOption(that.tableOption, true); |
| | | // that.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad')); |
| | | that.myChart1.setOption(that.table1Option, true); |
| | | that.$nextTick(() => { |
| | | that.myChart.resize() |
| | | that.myChart1.resize() |
| | | }) |
| | | } |
| | | }, |
| | | initTable: function () { |
| | | let that = this; |
| | | this.tableOption.xAxis = { |
| | | type: 'category', |
| | | data: [], // x轴数据 |
| | | name: '时间', // x轴名称 |
| | | // x轴名称样式 |
| | | nameTextStyle: { |
| | | fontWeight: 300, |
| | | fontSize: 15 |
| | | } |
| | | }; |
| | | this.tableOption.yAxis = { |
| | | type: 'value', |
| | | name: '延迟率', // y轴名称 |
| | | boundaryGap: [0, '100%'], |
| | | max: 100, |
| | | axisLabel: { |
| | | show: true, |
| | | interval: 'auto', |
| | | formatter: '{value} %' |
| | | }, |
| | | // y轴名称样式 |
| | | nameTextStyle: { |
| | | fontWeight: 300, |
| | | fontSize: 15 |
| | | } |
| | | }; |
| | | this.tableOption.dataZoom = [{ |
| | | show: true, |
| | | start: this.charZoomStart, |
| | | end: this.charZoomEnd |
| | | }]; |
| | | this.myChart = echarts.init(document.getElementById('ThreadsLoad')); |
| | | this.myChart.setOption(this.tableOption); |
| | | this.myChart.on('dataZoom', function (event) { |
| | | if (event.batch) { |
| | | that.charZoomStart = event.batch[0].start; |
| | | that.charZoomEnd = event.batch[0].end; |
| | | } else { |
| | | that.charZoomStart = event.start; |
| | | that.charZoomEnd = event.end; |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | this.table1Option.xAxis = { |
| | | type: 'category', |
| | | data: [], // x轴数据 |
| | | name: '时间', // x轴名称 |
| | | // x轴名称样式 |
| | | nameTextStyle: { |
| | | fontWeight: 300, |
| | | fontSize: 15 |
| | | } |
| | | }; |
| | | this.table1Option.yAxis = { |
| | | type: 'value', |
| | | name: '负载率', // y轴名称 |
| | | boundaryGap: [0, '100%'], |
| | | max: 100, |
| | | axisLabel: { |
| | | show: true, |
| | | interval: 'auto', |
| | | formatter: '{value} %' |
| | | }, |
| | | // y轴名称样式 |
| | | nameTextStyle: { |
| | | fontWeight: 300, |
| | | fontSize: 15 |
| | | } |
| | | }; |
| | | this.table1Option.dataZoom = [{ |
| | | show: true, |
| | | start: this.charZoomStart, |
| | | end: this.charZoomEnd |
| | | }]; |
| | | this.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad')); |
| | | this.myChart1.setOption(this.table1Option); |
| | | this.myChart1.on('dataZoom', function (event) { |
| | | if (event.batch) { |
| | | that.charZoomStart = event.batch[0].start; |
| | | that.charZoomEnd = event.batch[0].end; |
| | | } else { |
| | | that.charZoomStart = event.start; |
| | | that.charZoomEnd = event.end; |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | getAllSession: function () { |
| | | let that = this; |
| | | that.allSessionData = []; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/zlm/' + that.mediaServerChoose +'/index/api/getAllSession' |
| | | }).then(function (res) { |
| | | res.data.data.forEach(item => { |
| | | let data = { |
| | | peer_ip: item.peer_ip, |
| | | local_ip: item.local_ip, |
| | | typeid: item.typeid, |
| | | id: item.id |
| | | }; |
| | | that.allSessionData.push(data); |
| | | }); |
| | | }); |
| | | }, |
| | | getServerConfig: function () { |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/zlm/' + that.mediaServerChoose +'/index/api/getServerConfig' |
| | | }).then(function (res) { |
| | | let info = res.data.data[0]; |
| | | let serverInfo = {} |
| | | for (let i = 0; i < Object.keys(info).length; i++) { |
| | | let key = Object.keys(info)[i]; |
| | | let group = key.substring(0, key.indexOf(".")) |
| | | let itemKey = key.substring(key.indexOf(".") + 1) |
| | | if (!serverInfo[group]) serverInfo[group] = {} |
| | | serverInfo[group][itemKey] = info[key] |
| | | } |
| | | |
| | | that.serverConfig = serverInfo; |
| | | that.visible = true; |
| | | }); |
| | | }, |
| | | getWVPServerConfig: function () { |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/server/config' |
| | | }).then(function (res) { |
| | | console.log(res) |
| | | that.wvpServerConfig = res.data.data; |
| | | that.wvpVisible = true; |
| | | }); |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/server/version' |
| | | }).then(function (res) { |
| | | console.log(res) |
| | | that.wvpServerVersion = res.data.data; |
| | | that.wvpVisible = true; |
| | | }); |
| | | }, |
| | | reStartServer: function () { |
| | | let that = this; |
| | | this.$confirm('此操作将重启媒体服务器, 是否继续?', '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/zlm/' + that.mediaServerChoose +'/index/api/restartServer' |
| | | }).then(function (res) { |
| | | that.getAllSession(); |
| | | if (res.data.code == 0) { |
| | | that.$message({ |
| | | type: 'success', |
| | | message: '操作完成' |
| | | }); |
| | | } |
| | | }); |
| | | }); |
| | | }, |
| | | deleteRow: function (index, tabledata) { |
| | | let that = this; |
| | | this.$confirm('此操作将断开该通信链路, 是否继续?', '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }) |
| | | .then(() => { |
| | | that.deleteSession(tabledata[index].id); |
| | | }) |
| | | .catch(() => { |
| | | console.log('id:' + JSON.stringify(tabledata[index])); |
| | | this.$message({ |
| | | type: 'info', |
| | | message: '已取消删除' |
| | | }); |
| | | }); |
| | | console.log(JSON.stringify(tabledata[index])); |
| | | }, |
| | | deleteSession: function (id) { |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/zlm/' + that.mediaServerChoose +'/index/api/kick_session&id=' + id |
| | | }).then(function (res) { |
| | | that.getAllSession(); |
| | | that.$message({ |
| | | type: 'success', |
| | | message: '删除成功!' |
| | | }); |
| | | }); |
| | | }, |
| | | getNameFromKey: function(key) { |
| | | let nameData = { |
| | | "waitTrack": "等待编码信息", |
| | | "interfaceAuthenticationExcludes": "不进行鉴权的接口", |
| | | "playTimeout": "点播超时时间", |
| | | "autoApplyPlay": "自动点播", |
| | | "recordPushLive": "推流录像", |
| | | "redisConfig": "自动配置redis", |
| | | "thirdPartyGBIdReg": "stream信息正则", |
| | | "savePositionHistory": "保存轨迹信息", |
| | | "interfaceAuthentication": "接口鉴权", |
| | | "serverId": "服务ID", |
| | | "logInDatebase": "日志存储进数据库", |
| | | "seniorSdp": "扩展SDP", |
| | | "password": "密码", |
| | | "port": "端口号", |
| | | "keepaliveTimeOut": "心跳超时", |
| | | "domain": "国标域", |
| | | "ip": "IP地址", |
| | | "monitorIp": "监听IP", |
| | | "alarm": "存储报警信息", |
| | | "ptzSpeed": "云台控制速度", |
| | | "id": "国标ID", |
| | | "registerTimeInterval": "注册间隔", |
| | | "artifactId": "模块名称", |
| | | "version": "版本", |
| | | "project": "工程", |
| | | "git_Revision": "GIT修订版本", |
| | | "git_BRANCH": "GIT分支", |
| | | "git_URL": "GIT地址", |
| | | "build_DATE": "构建时间", |
| | | "create_By": "作者", |
| | | "git_Revision_SHORT": "GIT修订版本(短)", |
| | | "build_Jdk": "构建用JDK", |
| | | }; |
| | | console.log(key + ": " + nameData[key]) |
| | | |
| | | if (nameData[key]) { |
| | | return nameData[key] |
| | | }else { |
| | | return key; |
| | | }, |
| | | getLoadCount: function () { |
| | | let that = this; |
| | | if (that.mediaServerChoose != null) { |
| | | that.mediaServer.getMediaServer(that.mediaServerChoose, (data) => { |
| | | if (data.code == 0) { |
| | | that.loadCount = data.data.count |
| | | } |
| | | }, |
| | | getMediaKeyNameFromKey: function(key) { |
| | | let nameData = { |
| | | "waitTrack": "等待编码信息", |
| | | "interfaceAuthenticationExcludes": "不进行鉴权的接口", |
| | | "playTimeout": "点播超时时间", |
| | | "autoApplyPlay": "自动点播", |
| | | "recordPushLive": "推流录像", |
| | | "redisConfig": "自动配置redis", |
| | | "thirdPartyGBIdReg": "stream信息正则", |
| | | "savePositionHistory": "保存轨迹信息", |
| | | "interfaceAuthentication": "接口鉴权", |
| | | "serverId": "服务ID", |
| | | "logInDatebase": "日志存储进数据库", |
| | | "seniorSdp": "扩展SDP", |
| | | "password": "密码", |
| | | "port": "端口号", |
| | | "keepaliveTimeOut": "心跳超时", |
| | | "domain": "国标域", |
| | | "ip": "IP地址", |
| | | "monitorIp": "监听IP", |
| | | "alarm": "存储报警信息", |
| | | "ptzSpeed": "云台控制速度", |
| | | "id": "国标ID", |
| | | "registerTimeInterval": "注册间隔", |
| | | "artifactId": "模块名称", |
| | | "version": "版本", |
| | | "project": "工程", |
| | | "git_Revision": "GIT修订版本", |
| | | "git_BRANCH": "GIT分支", |
| | | "git_URL": "GIT地址", |
| | | "build_DATE": "构建时间", |
| | | "create_By": "作者", |
| | | "git_Revision_SHORT": "GIT修订版本(短)", |
| | | "build_Jdk": "构建用JDK", |
| | | }; |
| | | console.log(key + ": " + nameData[key]) |
| | | |
| | | if (nameData[key]) { |
| | | return nameData[key] |
| | | }else { |
| | | return key; |
| | | } |
| | | }) |
| | | } |
| | | }, |
| | | initTable: function () { |
| | | let that = this; |
| | | this.tableOption.xAxis = { |
| | | type: 'category', |
| | | data: [], // x轴数据 |
| | | name: '时间', // x轴名称 |
| | | // x轴名称样式 |
| | | nameTextStyle: { |
| | | fontWeight: 300, |
| | | fontSize: 15 |
| | | } |
| | | }; |
| | | this.tableOption.yAxis = { |
| | | type: 'value', |
| | | name: '延迟率', // y轴名称 |
| | | boundaryGap: [0, '100%'], |
| | | max: 100, |
| | | axisLabel: { |
| | | show: true, |
| | | interval: 'auto', |
| | | formatter: '{value} %' |
| | | }, |
| | | // y轴名称样式 |
| | | nameTextStyle: { |
| | | fontWeight: 300, |
| | | fontSize: 15 |
| | | } |
| | | }; |
| | | this.tableOption.dataZoom = [{ |
| | | show: true, |
| | | start: this.charZoomStart, |
| | | end: this.charZoomEnd |
| | | }]; |
| | | this.myChart = echarts.init(document.getElementById('ThreadsLoad')); |
| | | this.myChart.setOption(this.tableOption); |
| | | this.myChart.on('dataZoom', function (event) { |
| | | if (event.batch) { |
| | | that.charZoomStart = event.batch[0].start; |
| | | that.charZoomEnd = event.batch[0].end; |
| | | } else { |
| | | that.charZoomStart = event.start; |
| | | that.charZoomEnd = event.end; |
| | | } |
| | | }); |
| | | |
| | | this.table1Option.xAxis = { |
| | | type: 'category', |
| | | data: [], // x轴数据 |
| | | name: '时间', // x轴名称 |
| | | // x轴名称样式 |
| | | nameTextStyle: { |
| | | fontWeight: 300, |
| | | fontSize: 15 |
| | | } |
| | | }; |
| | | this.table1Option.yAxis = { |
| | | type: 'value', |
| | | name: '负载率', // y轴名称 |
| | | boundaryGap: [0, '100%'], |
| | | max: 100, |
| | | axisLabel: { |
| | | show: true, |
| | | interval: 'auto', |
| | | formatter: '{value} %' |
| | | }, |
| | | // y轴名称样式 |
| | | nameTextStyle: { |
| | | fontWeight: 300, |
| | | fontSize: 15 |
| | | } |
| | | }; |
| | | this.table1Option.dataZoom = [{ |
| | | show: true, |
| | | start: this.charZoomStart, |
| | | end: this.charZoomEnd |
| | | }]; |
| | | this.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad')); |
| | | this.myChart1.setOption(this.table1Option); |
| | | this.myChart1.on('dataZoom', function (event) { |
| | | if (event.batch) { |
| | | that.charZoomStart = event.batch[0].start; |
| | | that.charZoomEnd = event.batch[0].end; |
| | | } else { |
| | | that.charZoomStart = event.start; |
| | | that.charZoomEnd = event.end; |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | getAllSession: function () { |
| | | let that = this; |
| | | that.allSessionData = []; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/zlm/' + that.mediaServerChoose + '/index/api/getAllSession' |
| | | }).then(function (res) { |
| | | res.data.data.forEach(item => { |
| | | let data = { |
| | | peer_ip: item.peer_ip, |
| | | local_ip: item.local_ip, |
| | | typeid: item.typeid, |
| | | id: item.id |
| | | }; |
| | | that.allSessionData.push(data); |
| | | }); |
| | | }); |
| | | }, |
| | | getServerConfig: function () { |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/zlm/' + that.mediaServerChoose + '/index/api/getServerConfig' |
| | | }).then(function (res) { |
| | | let info = res.data.data[0]; |
| | | let serverInfo = {} |
| | | for (let i = 0; i < Object.keys(info).length; i++) { |
| | | let key = Object.keys(info)[i]; |
| | | let group = key.substring(0, key.indexOf(".")) |
| | | let itemKey = key.substring(key.indexOf(".") + 1) |
| | | if (!serverInfo[group]) serverInfo[group] = {} |
| | | serverInfo[group][itemKey] = info[key] |
| | | } |
| | | |
| | | that.serverConfig = serverInfo; |
| | | that.visible = true; |
| | | }); |
| | | }, |
| | | getWVPServerConfig: function () { |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/server/config' |
| | | }).then(function (res) { |
| | | console.log(res) |
| | | that.wvpServerConfig = res.data.data; |
| | | that.wvpVisible = true; |
| | | }); |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/server/version' |
| | | }).then(function (res) { |
| | | console.log(res) |
| | | that.wvpServerVersion = res.data.data; |
| | | that.wvpVisible = true; |
| | | }); |
| | | }, |
| | | reStartServer: function () { |
| | | let that = this; |
| | | this.$confirm('此操作将重启媒体服务器, 是否继续?', '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/zlm/' + that.mediaServerChoose + '/index/api/restartServer' |
| | | }).then(function (res) { |
| | | that.getAllSession(); |
| | | if (res.data.code == 0) { |
| | | that.$message({ |
| | | type: 'success', |
| | | message: '操作完成' |
| | | }); |
| | | } |
| | | }); |
| | | }); |
| | | }, |
| | | deleteRow: function (index, tabledata) { |
| | | let that = this; |
| | | this.$confirm('此操作将断开该通信链路, 是否继续?', '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }) |
| | | .then(() => { |
| | | that.deleteSession(tabledata[index].id); |
| | | }) |
| | | .catch(() => { |
| | | console.log('id:' + JSON.stringify(tabledata[index])); |
| | | this.$message({ |
| | | type: 'info', |
| | | message: '已取消删除' |
| | | }); |
| | | }); |
| | | console.log(JSON.stringify(tabledata[index])); |
| | | }, |
| | | deleteSession: function (id) { |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/zlm/' + that.mediaServerChoose + '/index/api/kick_session&id=' + id |
| | | }).then(function (res) { |
| | | that.getAllSession(); |
| | | that.$message({ |
| | | type: 'success', |
| | | message: '删除成功!' |
| | | }); |
| | | }); |
| | | }, |
| | | getNameFromKey: function (key) { |
| | | let nameData = { |
| | | "waitTrack": "等待编码信息", |
| | | "interfaceAuthenticationExcludes": "不进行鉴权的接口", |
| | | "playTimeout": "点播超时时间", |
| | | "autoApplyPlay": "自动点播", |
| | | "recordPushLive": "推流录像", |
| | | "redisConfig": "自动配置redis", |
| | | "thirdPartyGBIdReg": "stream信息正则", |
| | | "savePositionHistory": "保存轨迹信息", |
| | | "interfaceAuthentication": "接口鉴权", |
| | | "serverId": "服务ID", |
| | | "logInDatebase": "日志存储进数据库", |
| | | "seniorSdp": "扩展SDP", |
| | | "password": "密码", |
| | | "port": "端口号", |
| | | "keepaliveTimeOut": "心跳超时", |
| | | "domain": "国标域", |
| | | "ip": "IP地址", |
| | | "monitorIp": "监听IP", |
| | | "alarm": "存储报警信息", |
| | | "ptzSpeed": "云台控制速度", |
| | | "id": "国标ID", |
| | | "registerTimeInterval": "注册间隔", |
| | | "artifactId": "模块名称", |
| | | "version": "版本", |
| | | "project": "工程", |
| | | "git_Revision": "GIT修订版本", |
| | | "git_BRANCH": "GIT分支", |
| | | "git_URL": "GIT地址", |
| | | "build_DATE": "构建时间", |
| | | "create_By": "作者", |
| | | "git_Revision_SHORT": "GIT修订版本(短)", |
| | | "build_Jdk": "构建用JDK", |
| | | }; |
| | | console.log(key + ": " + nameData[key]) |
| | | |
| | | if (nameData[key]) { |
| | | return nameData[key] |
| | | } else { |
| | | return key; |
| | | } |
| | | }, |
| | | getMediaKeyNameFromKey: function (key) { |
| | | let nameData = { |
| | | "waitTrack": "等待编码信息", |
| | | "interfaceAuthenticationExcludes": "不进行鉴权的接口", |
| | | "playTimeout": "点播超时时间", |
| | | "autoApplyPlay": "自动点播", |
| | | "recordPushLive": "推流录像", |
| | | "redisConfig": "自动配置redis", |
| | | "thirdPartyGBIdReg": "stream信息正则", |
| | | "savePositionHistory": "保存轨迹信息", |
| | | "interfaceAuthentication": "接口鉴权", |
| | | "serverId": "服务ID", |
| | | "logInDatebase": "日志存储进数据库", |
| | | "seniorSdp": "扩展SDP", |
| | | "password": "密码", |
| | | "port": "端口号", |
| | | "keepaliveTimeOut": "心跳超时", |
| | | "domain": "国标域", |
| | | "ip": "IP地址", |
| | | "monitorIp": "监听IP", |
| | | "alarm": "存储报警信息", |
| | | "ptzSpeed": "云台控制速度", |
| | | "id": "国标ID", |
| | | "registerTimeInterval": "注册间隔", |
| | | "artifactId": "模块名称", |
| | | "version": "版本", |
| | | "project": "工程", |
| | | "git_Revision": "GIT修订版本", |
| | | "git_BRANCH": "GIT分支", |
| | | "git_URL": "GIT地址", |
| | | "build_DATE": "构建时间", |
| | | "create_By": "作者", |
| | | "git_Revision_SHORT": "GIT修订版本(短)", |
| | | "build_Jdk": "构建用JDK", |
| | | }; |
| | | console.log(key + ": " + nameData[key]) |
| | | |
| | | if (nameData[key]) { |
| | | return nameData[key] |
| | | } else { |
| | | return key; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | #app { |
| | | height: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .control-table { |
| | | background-color: #ffffff; |
| | | height: 25rem; |
| | | background-color: #ffffff; |
| | | height: 25rem; |
| | | } |
| | | |
| | | .table-c { |
| | | border-right: 1px solid #dcdcdc; |
| | | border-bottom: 1px solid #dcdcdc; |
| | | border-right: 1px solid #dcdcdc; |
| | | border-bottom: 1px solid #dcdcdc; |
| | | } |
| | | |
| | | .table-c td { |
| | | border-left: 1px solid #dcdcdc; |
| | | border-top: 1px solid #dcdcdc; |
| | | padding: 0.2rem; |
| | | border-left: 1px solid #dcdcdc; |
| | | border-top: 1px solid #dcdcdc; |
| | | padding: 0.2rem; |
| | | } |
| | | |
| | | .el-table { |
| | | width: 99.9% !important; |
| | | width: 99.9% !important; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div id="devicePosition" style="height: 100%"> |
| | | <el-container style="height: 100%"> |
| | | <el-header> |
| | | <uiHeader></uiHeader> |
| | | </el-header> |
| | | <el-main> |
| | | <div style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center;"> |
| | | <span style="font-size: 1rem; font-weight: 500">设备定位 ({{ parentChannelId == 0 ? deviceId : parentChannelId }})</span> |
| | | </div> |
| | | <div style="background-color: #ffffff; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left; font-size: 14px;"> |
| | | <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem" type="primary" @click="showDevice">返回</el-button> |
| | | <!-- <span class="demonstration">从</span> --> |
| | | <el-date-picker v-model="searchFrom" type="datetime" placeholder="选择开始日期时间" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker> |
| | | <el-date-picker v-model="searchTo" type="datetime" placeholder="选择结束日期时间" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker> |
| | | <el-button-group> |
| | | <el-button icon="el-icon-search" size="mini" type="primary" @click="showHistoryPath">历史轨迹</el-button> |
| | | <el-button icon="el-icon-search" size="mini" style="margin-right: 1rem" type="primary" @click="showLatestPosition">最新位置</el-button> |
| | | </el-button-group> |
| | | <el-tag style="width: 5rem; text-align: center" size="medium">过期时间</el-tag> |
| | | <el-input-number size="mini" v-model="expired" :min="300" :controls="false" style="width: 4rem;"></el-input-number> |
| | | <el-tag style="width: 5rem; text-align: center" size="medium">上报周期</el-tag> |
| | | <el-input-number size="mini" v-model="interval" :min="1" :controls="false" style="width: 4rem;"></el-input-number> |
| | | <el-button-group> |
| | | <el-button icon="el-icon-search" size="mini" type="primary" @click="subscribeMobilePosition">位置订阅</el-button> |
| | | <el-button icon="el-icon-search" size="mini" type="primary" @click="unSubscribeMobilePosition">取消订阅</el-button> |
| | | </el-button-group> |
| | | <el-checkbox size="mini" style="margin-right: 1rem; float: right" v-model="autoList" @change="autoListChange" >自动刷新</el-checkbox> |
| | | </div> |
| | | <div class="mapContainer" style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center; height: calc(100% - 10rem);"> |
| | | <div class="baidumap" id="allmap"></div> |
| | | </div> |
| | | </el-main> |
| | | </el-container> |
| | | <div style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center;"> |
| | | <span style="font-size: 1rem; font-weight: 500">设备定位 ({{ parentChannelId == 0 ? deviceId : parentChannelId }})</span> |
| | | </div> |
| | | <div style="background-color: #ffffff; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left; font-size: 14px;"> |
| | | <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem" type="primary" @click="showDevice">返回</el-button> |
| | | <!-- <span class="demonstration">从</span> --> |
| | | <el-date-picker v-model="searchFrom" type="datetime" placeholder="选择开始日期时间" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker> |
| | | <el-date-picker v-model="searchTo" type="datetime" placeholder="选择结束日期时间" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker> |
| | | <el-button-group> |
| | | <el-button icon="el-icon-search" size="mini" type="primary" @click="showHistoryPath">历史轨迹</el-button> |
| | | <el-button icon="el-icon-search" size="mini" style="margin-right: 1rem" type="primary" @click="showLatestPosition">最新位置</el-button> |
| | | </el-button-group> |
| | | <el-tag style="width: 5rem; text-align: center" size="medium">过期时间</el-tag> |
| | | <el-input-number size="mini" v-model="expired" :min="300" :controls="false" style="width: 4rem;"></el-input-number> |
| | | <el-tag style="width: 5rem; text-align: center" size="medium">上报周期</el-tag> |
| | | <el-input-number size="mini" v-model="interval" :min="1" :controls="false" style="width: 4rem;"></el-input-number> |
| | | <el-button-group> |
| | | <el-button icon="el-icon-search" size="mini" type="primary" @click="subscribeMobilePosition">位置订阅</el-button> |
| | | <el-button icon="el-icon-search" size="mini" type="primary" @click="unSubscribeMobilePosition">取消订阅</el-button> |
| | | </el-button-group> |
| | | <el-checkbox size="mini" style="margin-right: 1rem; float: right" v-model="autoList" @change="autoListChange" >自动刷新</el-checkbox> |
| | | </div> |
| | | <div class="mapContainer" style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center; height: calc(100% - 10rem);"> |
| | | <div class="baidumap" id="allmap"></div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import uiHeader from "./UiHeader.vue"; |
| | | import moment from "moment"; |
| | | import uiHeader from "../layout/UiHeader.vue"; |
| | | import geoTools from "./GeoConvertTools.js"; |
| | | export default { |
| | | name: "devicePosition", |
| | |
| | | let self = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url:`/api/position/history/${this.deviceId}`, |
| | | url:`/api/position/history/${this.deviceId}`, |
| | | params: { |
| | | start: self.startTime, |
| | | end: self.endTime, |
| | |
| | | }, |
| | | toGBString: function (dateTime) { |
| | | return ( |
| | | dateTime.getFullYear() + |
| | | dateTime.getFullYear() + |
| | | "-" + this.twoDigits(dateTime.getMonth() + 1) + |
| | | "-" + this.twoDigits(dateTime.getDate()) + |
| | | "T" + this.twoDigits(dateTime.getHours()) + |
| | |
| | | <template> |
| | | <div id="devicePosition" style="height: 100%"> |
| | | <el-container style="height: 100%"> |
| | | <el-header> |
| | | <uiHeader></uiHeader> |
| | | </el-header> |
| | | <el-container v-loading="loading" element-loading-text="拼命加载中" style="margin: 0 20px;"> |
| | | <el-aside width="300px" style="background-color: #ffffff"> |
| | | <div style="text-align: center;padding-top: 20px;">设备列表</div> |
| | | <el-menu v-loading="loading"> |
| | | <el-submenu v-for="device in deviceList" :key="device.deviceId" :index="device.deviceId" @click="sendDevicePush(item)"> |
| | | <template slot="title" > |
| | | <i class="el-icon-location-outline"></i> |
| | | {{device.name}} |
| | | </template> |
| | | <ChannelTree :device="device" @sendDevicePush="sendDevicePush"></ChannelTree> |
| | | </el-submenu> |
| | | </el-menu> |
| | | </el-aside> |
| | | <el-container> |
| | | <!-- <LivePlay></LivePlay> --> |
| | | <el-header height="40px" style="text-align: left;font-size: 17px;line-height: 40px;"> |
| | | 分屏: |
| | | <i class="el-icon-full-screen btn" :class="{active:spilt==1}" @click="spilt=1"/> |
| | | <i class="el-icon-menu btn" :class="{active:spilt==4}" @click="spilt=4"/> |
| | | <i class="el-icon-s-grid btn" :class="{active:spilt==9}" @click="spilt=9"/> |
| | | </el-header> |
| | | <el-main> |
| | | <div style="width: 100%;height: calc( 100vh - 110px );display: flex;flex-wrap: wrap;background-color: #000;"> |
| | | <div v-for="i in spilt" :key="i" class="play-box" |
| | | :style="liveStyle" :class="{redborder:playerIdx == (i-1)}" |
| | | @click="playerIdx = (i-1)" |
| | | > |
| | | <div v-if="!videoUrl[i-1]" style="color: #ffffff;font-size: 30px;font-weight: bold;">{{i}}</div> |
| | | <player v-else :ref="'player'+i" :videoUrl="videoUrl[i-1]" fluent autoplay :height="true" |
| | | :containerId="'player'+i" @screenshot="shot" @destroy="destroy"></player> |
| | | <!-- <player v-else ref="'player'+i" :idx="'player'+i" :visible.sync="showVideoDialog" :videoUrl="videoUrl[i-1]" :height="true" :hasAudio="hasAudio" fluent autoplay live ></player> --> |
| | | </div> |
| | | </div> |
| | | </el-main> |
| | | </el-container> |
| | | <div id="devicePosition" style="height: 100%;width: 100%"> |
| | | <el-container v-loading="loading" element-loading-text="拼命加载中"> |
| | | <el-aside width="300px" style="background-color: #ffffff"> |
| | | <div style="text-align: center;padding-top: 20px;">设备列表</div> |
| | | <el-menu v-loading="loading"> |
| | | <el-submenu v-for="device in deviceList" :key="device.deviceId" :index="device.deviceId" @click="sendDevicePush(item)"> |
| | | <template slot="title" > |
| | | <i class="el-icon-location-outline"></i> |
| | | {{device.name}} |
| | | </template> |
| | | <ChannelTree :device="device" @sendDevicePush="sendDevicePush"></ChannelTree> |
| | | </el-submenu> |
| | | </el-menu> |
| | | </el-aside> |
| | | <el-container> |
| | | <!-- <LivePlay></LivePlay> --> |
| | | <el-header height="40px" style="text-align: left;font-size: 17px;line-height: 40px;"> |
| | | 分屏: |
| | | <i class="el-icon-full-screen btn" :class="{active:spilt==1}" @click="spilt=1"/> |
| | | <i class="el-icon-menu btn" :class="{active:spilt==4}" @click="spilt=4"/> |
| | | <i class="el-icon-s-grid btn" :class="{active:spilt==9}" @click="spilt=9"/> |
| | | </el-header> |
| | | <el-main> |
| | | <div style="width: 100%;height: calc( 100vh - 150px );display: flex;flex-wrap: wrap;background-color: #000;"> |
| | | <div v-for="i in spilt" :key="i" class="play-box" |
| | | :style="liveStyle" :class="{redborder:playerIdx == (i-1)}" |
| | | @click="playerIdx = (i-1)" |
| | | > |
| | | <div v-if="!videoUrl[i-1]" style="color: #ffffff;font-size: 30px;font-weight: bold;">{{i}}</div> |
| | | <player v-else :ref="'player'+i" :videoUrl="videoUrl[i-1]" fluent autoplay :height="true" |
| | | :containerId="'player'+i" @screenshot="shot" @destroy="destroy"></player> |
| | | <!-- <player v-else ref="'player'+i" :idx="'player'+i" :visible.sync="showVideoDialog" :videoUrl="videoUrl[i-1]" :height="true" :hasAudio="hasAudio" fluent autoplay live ></player> --> |
| | | </div> |
| | | </div> |
| | | </el-main> |
| | | </el-container> |
| | | </el-container> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import uiHeader from "./UiHeader.vue"; |
| | | import uiHeader from "../layout/UiHeader.vue"; |
| | | import player from './dialog/jessibuca.vue' |
| | | import ChannelTree from './channelTree.vue' |
| | | |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import uiHeader from '../UiHeader.vue' |
| | | import uiHeader from '../../layout/UiHeader.vue' |
| | | export default { |
| | | name: "SettingForMedia", |
| | | components: { |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import uiHeader from '../UiHeader.vue' |
| | | import uiHeader from '../../layout/UiHeader.vue' |
| | | export default { |
| | | name: "SettingForSip", |
| | | components: { |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import uiHeader from '../UiHeader.vue' |
| | | import uiHeader from '../../layout/UiHeader.vue' |
| | | export default { |
| | | name: "SettingForWeb", |
| | | components: { |
New file |
| | |
| | | <template> |
| | | <div id="UiHeader"> |
| | | <el-menu router :default-active="activeIndex" menu-trigger="click" background-color="#545c64" text-color="#fff" |
| | | active-text-color="#ffd04b" mode="horizontal"> |
| | | <el-menu-item index="/control">控制台</el-menu-item> |
| | | <el-menu-item index="/live">实时监控</el-menu-item> |
| | | <el-menu-item index="/deviceList">国标设备</el-menu-item> |
| | | <el-menu-item index="/pushVideoList">推流列表</el-menu-item> |
| | | <el-menu-item index="/streamProxyList">拉流代理</el-menu-item> |
| | | <el-menu-item index="/cloudRecord">云端录像</el-menu-item> |
| | | <el-menu-item index="/mediaServerManger">节点管理</el-menu-item> |
| | | <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item> |
| | | <el-menu-item @click="openDoc">在线文档</el-menu-item> |
| | | <!-- <el-submenu index="/setting">--> |
| | | <!-- <template slot="title">系统设置</template>--> |
| | | <!-- <el-menu-item index="/setting/web">WEB服务</el-menu-item>--> |
| | | <!-- <el-menu-item index="/setting/sip">国标服务</el-menu-item>--> |
| | | <!-- <el-menu-item index="/setting/media">媒体服务</el-menu-item>--> |
| | | <!-- </el-submenu>--> |
| | | <el-switch v-model="alarmNotify" active-text="报警信息推送" @change="alarmNotifyChannge"></el-switch> |
| | | <!-- <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item>--> |
| | | <el-submenu index="" style="float: right;"> |
| | | <template slot="title">欢迎,{{ this.$cookies.get("session").username }}</template> |
| | | <el-menu-item @click="changePassword">修改密码</el-menu-item> |
| | | <el-menu-item @click="loginout">注销</el-menu-item> |
| | | </el-submenu> |
| | | </el-menu> |
| | | <changePasswordDialog ref="changePasswordDialog"></changePasswordDialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | |
| | | import changePasswordDialog from '../components/dialog/changePassword.vue' |
| | | |
| | | export default { |
| | | name: "UiHeader", |
| | | components: {Notification, changePasswordDialog}, |
| | | data() { |
| | | return { |
| | | alarmNotify: false, |
| | | sseSource: null, |
| | | activeIndex: this.$route.path, |
| | | }; |
| | | }, |
| | | created() { |
| | | if (this.$route.path.startsWith("/channelList")) { |
| | | this.activeIndex = "/deviceList" |
| | | } |
| | | |
| | | }, |
| | | mounted() { |
| | | window.addEventListener('beforeunload', e => this.beforeunloadHandler(e)) |
| | | // window.addEventListener('unload', e => this.unloadHandler(e)) |
| | | this.alarmNotify = this.getAlarmSwitchStatus() === "true"; |
| | | this.sseControl(); |
| | | }, |
| | | methods: { |
| | | loginout() { |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: "/api/user/logout" |
| | | }).then((res) => { |
| | | // 删除cookie,回到登录页面 |
| | | this.$cookies.remove("session"); |
| | | this.$router.push('/login'); |
| | | this.sseSource.close(); |
| | | }).catch((error) => { |
| | | console.error("登出失败") |
| | | console.error(error) |
| | | }); |
| | | }, |
| | | changePassword() { |
| | | this.$refs.changePasswordDialog.openDialog() |
| | | }, |
| | | openDoc() { |
| | | console.log(process.env.BASE_API) |
| | | window.open(!!process.env.BASE_API ? process.env.BASE_API + "/doc.html" : "/doc.html") |
| | | }, |
| | | beforeunloadHandler() { |
| | | this.sseSource.close(); |
| | | }, |
| | | alarmNotifyChannge() { |
| | | this.setAlarmSwitchStatus() |
| | | this.sseControl() |
| | | }, |
| | | sseControl() { |
| | | let that = this; |
| | | if (this.alarmNotify) { |
| | | console.log("申请SSE推送API调用,浏览器ID: " + this.$browserId); |
| | | this.sseSource = new EventSource('/api/emit?browserId=' + this.$browserId); |
| | | this.sseSource.addEventListener('message', function (evt) { |
| | | that.$notify({ |
| | | title: '收到报警信息', |
| | | dangerouslyUseHTMLString: true, |
| | | message: evt.data, |
| | | type: 'warning' |
| | | }); |
| | | console.log("收到信息:" + evt.data); |
| | | }); |
| | | this.sseSource.addEventListener('open', function (e) { |
| | | console.log("SSE连接打开."); |
| | | }, false); |
| | | this.sseSource.addEventListener('error', function (e) { |
| | | if (e.target.readyState == EventSource.CLOSED) { |
| | | console.log("SSE连接关闭"); |
| | | } else { |
| | | console.log(e.target.readyState); |
| | | } |
| | | }, false); |
| | | } else { |
| | | if (this.sseSource != null) { |
| | | this.sseSource.removeEventListener('open', null); |
| | | this.sseSource.removeEventListener('message', null); |
| | | this.sseSource.removeEventListener('error', null); |
| | | this.sseSource.close(); |
| | | } |
| | | |
| | | } |
| | | }, |
| | | getAlarmSwitchStatus() { |
| | | if (localStorage.getItem("alarmSwitchStatus") == null) { |
| | | localStorage.setItem("alarmSwitchStatus", false); |
| | | } |
| | | return localStorage.getItem("alarmSwitchStatus"); |
| | | }, |
| | | setAlarmSwitchStatus() { |
| | | localStorage.setItem("alarmSwitchStatus", this.alarmNotify); |
| | | } |
| | | }, |
| | | destroyed() { |
| | | window.removeEventListener('beforeunload', e => this.beforeunloadHandler(e)) |
| | | if (this.sseSource != null) { |
| | | this.sseSource.removeEventListener('open', null); |
| | | this.sseSource.removeEventListener('message', null); |
| | | this.sseSource.removeEventListener('error', null); |
| | | this.sseSource.close(); |
| | | } |
| | | }, |
| | | |
| | | } |
| | | |
| | | </script> |
| | | <style> |
| | | #UiHeader .el-switch__label { |
| | | color: white; |
| | | } |
| | | #UiHeader .el-switch__label.is-active{ |
| | | color: #409EFF; |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <el-container style="height: 100%"> |
| | | <el-header> |
| | | <ui-header/> |
| | | </el-header> |
| | | <el-main> |
| | | <el-container> |
| | | <transition name="fade"> |
| | | <router-view></router-view> |
| | | </transition> |
| | | </el-container> |
| | | </el-main> |
| | | </el-container> |
| | | </template> |
| | | |
| | | <script> |
| | | import uiHeader from "./UiHeader.vue"; |
| | | |
| | | export default { |
| | | name: "index", |
| | | components: { |
| | | uiHeader |
| | | }, |
| | | } |
| | | </script> |
| | | <style> |
| | | /*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/ |
| | | ::-webkit-scrollbar { |
| | | width: 8px; |
| | | height: 8px; |
| | | } |
| | | |
| | | /*定义滚动条轨道 内阴影+圆角*/ |
| | | ::-webkit-scrollbar-track { |
| | | border-radius: 4px; |
| | | background-color: #F5F5F5; |
| | | } |
| | | |
| | | /*定义滑块 内阴影+圆角*/ |
| | | ::-webkit-scrollbar-thumb { |
| | | border-radius: 4px; |
| | | background-color: #c8c8c8; |
| | | box-shadow: inset 0 0 6px rgba(0, 0, 0, .1); |
| | | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .1); |
| | | } |
| | | |
| | | /*定义标题栏*/ |
| | | .page-header { |
| | | background-color: #FFFFFF; |
| | | margin-bottom: 1rem; |
| | | padding: 0.5rem; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .page-title { |
| | | font-weight: bold; |
| | | text-align: left; |
| | | } |
| | | |
| | | .page-header-btn { |
| | | text-align: right; |
| | | } |
| | | </style> |
| | | <style scoped> |
| | | .el-main { |
| | | margin: 0; |
| | | } |
| | | |
| | | .fade-enter { |
| | | visibility: hidden; |
| | | opacity: 0; |
| | | } |
| | | |
| | | .fade-leave-to { |
| | | display: none; |
| | | } |
| | | |
| | | .fade-enter-active, |
| | | .fade-leave-active { |
| | | transition: opacity .5s ease; |
| | | } |
| | | |
| | | .fade-enter-to, |
| | | .fade-leave { |
| | | visibility: visible; |
| | | opacity: 1; |
| | | } |
| | | </style> |
| | |
| | | import Vue from 'vue' |
| | | import VueRouter from 'vue-router' |
| | | import Layout from "../layout/index.vue" |
| | | |
| | | import control from '../components/control.vue' |
| | | import deviceList from '../components/DeviceList.vue' |
| | |
| | | routes: [ |
| | | { |
| | | path: '/', |
| | | component: control, |
| | | }, |
| | | { |
| | | path: '/live', |
| | | component: live, |
| | | }, |
| | | { |
| | | path: '/deviceList', |
| | | component: deviceList, |
| | | }, |
| | | { |
| | | path: '/pushVideoList', |
| | | component: pushVideoList, |
| | | }, |
| | | { |
| | | path: '/streamProxyList', |
| | | component: streamProxyList, |
| | | name: 'home', |
| | | component: Layout, |
| | | redirect: '/control', |
| | | children: [ |
| | | { |
| | | path: '/control', |
| | | component: control, |
| | | }, |
| | | { |
| | | path: '/live', |
| | | component: live, |
| | | }, |
| | | { |
| | | path: '/deviceList', |
| | | component: deviceList, |
| | | }, |
| | | { |
| | | path: '/pushVideoList', |
| | | component: pushVideoList, |
| | | }, |
| | | { |
| | | path: '/streamProxyList', |
| | | component: streamProxyList, |
| | | }, |
| | | { |
| | | path: '/channelList/:deviceId/:parentChannelId/:count/:page', |
| | | name: 'channelList', |
| | | component: channelList, |
| | | }, |
| | | { |
| | | path: '/parentPlatformList/:count/:page', |
| | | name: 'parentPlatformList', |
| | | component: parentPlatformList, |
| | | }, |
| | | { |
| | | path: '/devicePosition/:deviceId/:parentChannelId/:count/:page', |
| | | name: 'devicePosition', |
| | | component: devicePosition, |
| | | }, |
| | | { |
| | | path: '/cloudRecord', |
| | | name: 'cloudRecord', |
| | | component: cloudRecord, |
| | | }, |
| | | { |
| | | path: '/mediaServerManger', |
| | | name: 'mediaServerManger', |
| | | component: mediaServerManger, |
| | | }, |
| | | { |
| | | path: '/setting/web', |
| | | name: 'web', |
| | | component: web, |
| | | }, |
| | | { |
| | | path: '/setting/sip', |
| | | name: 'sip', |
| | | component: sip, |
| | | }, |
| | | { |
| | | path: '/setting/media', |
| | | name: 'media', |
| | | component: media, |
| | | }, |
| | | { |
| | | path: '/play/wasm/:url', |
| | | name: 'wasmPlayer', |
| | | component: wasmPlayer, |
| | | }, |
| | | { |
| | | path: '/play/rtc/:url', |
| | | name: 'rtcPlayer', |
| | | component: rtcPlayer, |
| | | }, |
| | | ] |
| | | }, |
| | | { |
| | | path: '/login', |
| | | name: '登录', |
| | | component: login, |
| | | }, |
| | | { |
| | | path: '/channelList/:deviceId/:parentChannelId/:count/:page', |
| | | name: 'channelList', |
| | | component: channelList, |
| | | }, |
| | | { |
| | | path: '/parentPlatformList/:count/:page', |
| | | name: 'parentPlatformList', |
| | | component: parentPlatformList, |
| | | }, |
| | | { |
| | | path: '/devicePosition/:deviceId/:parentChannelId/:count/:page', |
| | | name: 'devicePosition', |
| | | component: devicePosition, |
| | | }, |
| | | { |
| | | path: '/cloudRecord', |
| | | name: 'cloudRecord', |
| | | component: cloudRecord, |
| | | }, |
| | | { |
| | | path: '/mediaServerManger', |
| | | name: 'mediaServerManger', |
| | | component: mediaServerManger, |
| | | }, |
| | | { |
| | | path: '/setting/web', |
| | | name: 'web', |
| | | component: web, |
| | | }, |
| | | { |
| | | path: '/setting/sip', |
| | | name: 'sip', |
| | | component: sip, |
| | | }, |
| | | { |
| | | path: '/setting/media', |
| | | name: 'media', |
| | | component: media, |
| | | }, |
| | | { |
| | | path: '/play/wasm/:url', |
| | | name: 'wasmPlayer', |
| | | component: wasmPlayer, |
| | | }, |
| | | { |
| | | path: '/play/rtc/:url', |
| | | name: 'rtcPlayer', |
| | | component: rtcPlayer, |
| | | }, |
| | | ] |
| | | }) |