Commit fb843d41c1e186b2109bfeea73509cad2b135cdc

Authored by xiaoxie
1 parent 3def634a

1.重构全局页面结构,从之前每个页面独立绘制改为路由嵌套

2.全局页面样式优化,如滚动条、标题栏等
web_src/src/components/CloudRecord.vue
1 <template> 1 <template>
2 - <div id="app">  
3 - <el-container>  
4 - <el-header>  
5 - <uiHeader></uiHeader>  
6 - </el-header>  
7 - <el-main>  
8 - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">  
9 - <span v-if="!recordDetail" >云端录像</span>  
10 - <el-page-header v-if="recordDetail" @back="backToList" content="云端录像">  
11 - </el-page-header>  
12 - <div style="position: absolute; right: 5rem; top: 0.3rem;">  
13 - 节点选择:  
14 - <el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServerId" placeholder="请选择" :disabled="recordDetail">  
15 - <el-option  
16 - v-for="item in mediaServerList"  
17 - :key="item.id"  
18 - :label="item.id"  
19 - :value="item.id">  
20 - </el-option>  
21 - </el-select>  
22 - </div>  
23 - <div style="position: absolute; right: 1rem; top: 0.3rem;">  
24 - <el-button v-if="!recordDetail" icon="el-icon-refresh-right" circle size="mini" :loading="loading" @click="getRecordList()"></el-button>  
25 - </div>  
26 - </div>  
27 - <div v-if="!recordDetail"> 2 + <div id="app" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">云端录像</div>
  5 + <div class="page-header-btn">
  6 + 节点选择:
  7 + <el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServerId" placeholder="请选择" :disabled="recordDetail">
  8 + <el-option
  9 + v-for="item in mediaServerList"
  10 + :key="item.id"
  11 + :label="item.id"
  12 + :value="item.id">
  13 + </el-option>
  14 + </el-select>
  15 + <el-button v-if="!recordDetail" icon="el-icon-refresh-right" circle size="mini" :loading="loading" @click="getRecordList()"></el-button>
  16 + </div>
  17 + </div>
  18 + <div v-if="!recordDetail">
28 19
29 - <!--设备列表-->  
30 - <el-table :data="recordList" border style="width: 100%" :height="winHeight">  
31 - <el-table-column prop="app" label="应用名" align="center">  
32 - </el-table-column>  
33 - <el-table-column prop="stream" label="流ID" align="center">  
34 - </el-table-column>  
35 - <el-table-column prop="time" label="时间" align="center">  
36 - </el-table-column>  
37 - <el-table-column label="操作" width="360" align="center" fixed="right">  
38 - <template slot-scope="scope">  
39 - <el-button-group>  
40 - <el-button size="mini" icon="el-icon-video-camera-solid" type="primary" @click="showRecordDetail(scope.row)">查看</el-button>  
41 -<!-- <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteRecord(scope.row)">删除</el-button>-->  
42 - </el-button-group>  
43 - </template>  
44 - </el-table-column>  
45 - </el-table>  
46 - <el-pagination  
47 - style="float: right"  
48 - @size-change="handleSizeChange"  
49 - @current-change="currentChange"  
50 - :current-page="currentPage"  
51 - :page-size="count"  
52 - :page-sizes="[15, 25, 35, 50]"  
53 - layout="total, sizes, prev, pager, next"  
54 - :total="total">  
55 - </el-pagination>  
56 - </div>  
57 - <cloud-record-detail ref="cloudRecordDetail" v-if="recordDetail" :recordFile="chooseRecord" :mediaServerId="mediaServerId" :mediaServerPath="mediaServerPath" ></cloud-record-detail>  
58 - </el-main>  
59 - </el-container>  
60 - </div> 20 + <!--设备列表-->
  21 + <el-table :data="recordList" border style="width: 100%" :height="winHeight">
  22 + <el-table-column prop="app" label="应用名" align="center">
  23 + </el-table-column>
  24 + <el-table-column prop="stream" label="流ID" align="center">
  25 + </el-table-column>
  26 + <el-table-column prop="time" label="时间" align="center">
  27 + </el-table-column>
  28 + <el-table-column label="操作" width="360" align="center" fixed="right">
  29 + <template slot-scope="scope">
  30 + <el-button-group>
  31 + <el-button size="mini" icon="el-icon-video-camera-solid" type="primary" @click="showRecordDetail(scope.row)">查看</el-button>
  32 + <!-- <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteRecord(scope.row)">删除</el-button>-->
  33 + </el-button-group>
  34 + </template>
  35 + </el-table-column>
  36 + </el-table>
  37 + <el-pagination
  38 + style="float: right"
  39 + @size-change="handleSizeChange"
  40 + @current-change="currentChange"
  41 + :current-page="currentPage"
  42 + :page-size="count"
  43 + :page-sizes="[15, 25, 35, 50]"
  44 + layout="total, sizes, prev, pager, next"
  45 + :total="total">
  46 + </el-pagination>
  47 + </div>
  48 + <cloud-record-detail ref="cloudRecordDetail" v-if="recordDetail" :recordFile="chooseRecord" :mediaServerId="mediaServerId" :mediaServerPath="mediaServerPath" ></cloud-record-detail>
  49 +
  50 + </div>
61 </template> 51 </template>
62 52
63 <script> 53 <script>
64 - import uiHeader from './UiHeader.vue' 54 + import uiHeader from '../layout/UiHeader.vue'
65 import cloudRecordDetail from './CloudRecordDetail.vue' 55 import cloudRecordDetail from './CloudRecordDetail.vue'
66 import MediaServer from './service/MediaServer' 56 import MediaServer from './service/MediaServer'
67 export default { 57 export default {
web_src/src/components/CloudRecordDetail.vue
@@ -104,7 +104,7 @@ @@ -104,7 +104,7 @@
104 104
105 <script> 105 <script>
106 // TODO 根据查询的时间列表设置滑轨的最大值与最小值, 106 // TODO 根据查询的时间列表设置滑轨的最大值与最小值,
107 - import uiHeader from './UiHeader.vue' 107 + import uiHeader from '../layout/UiHeader.vue'
108 import player from './dialog/easyPlayer.vue' 108 import player from './dialog/easyPlayer.vue'
109 import moment from 'moment' 109 import moment from 'moment'
110 export default { 110 export default {
web_src/src/components/DeviceList.vue
1 <template> 1 <template>
2 - <div id="app">  
3 - <el-container>  
4 - <el-header>  
5 - <uiHeader></uiHeader>  
6 - </el-header>  
7 - <el-main>  
8 - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">  
9 - <span style="font-size: 1rem; font-weight: bold;">设备列表</span>  
10 - <div style="position: absolute; right: 1rem; top: 0.3rem;">  
11 - <el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading" @click="getDeviceList()"></el-button>  
12 - </div>  
13 - </div>  
14 - <!-- <devicePlayer ref="devicePlayer"></devicePlayer> -->  
15 - <!--设备列表-->  
16 - <el-table :data="deviceList" border style="width: 100%;font-size: 12px;" :height="winHeight">  
17 - <el-table-column prop="name" label="名称" align="center">  
18 - </el-table-column>  
19 - <el-table-column prop="deviceId" label="设备编号" width="180" align="center">  
20 - </el-table-column>  
21 - <el-table-column label="地址" width="180" align="center">  
22 - <template slot-scope="scope">  
23 - <div slot="reference" class="name-wrapper">  
24 - <el-tag size="medium">{{ scope.row.hostAddress }}</el-tag>  
25 - </div>  
26 - </template>  
27 - </el-table-column>  
28 - <el-table-column prop="manufacturer" label="厂家" align="center">  
29 - </el-table-column>  
30 - <el-table-column label="流传输模式" align="center" width="120">  
31 - <template slot-scope="scope">  
32 - <el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择">  
33 - <el-option key="UDP" label="UDP" value="UDP"></el-option>  
34 - <el-option key="TCP-ACTIVE" label="TCP主动模式" :disabled="true" value="TCP-ACTIVE"></el-option>  
35 - <el-option key="TCP-PASSIVE" label="TCP被动模式" value="TCP-PASSIVE"></el-option>  
36 - </el-select>  
37 - </template>  
38 - </el-table-column>  
39 - <el-table-column prop="channelCount" label="通道数" align="center">  
40 - </el-table-column>  
41 - <el-table-column label="状态" width="120" align="center">  
42 - <template slot-scope="scope">  
43 - <div slot="reference" class="name-wrapper">  
44 - <el-tag size="medium" v-if="scope.row.online == 1">在线</el-tag>  
45 - <el-tag size="medium" type="info" v-if="scope.row.online == 0">离线</el-tag>  
46 - </div>  
47 - </template>  
48 - </el-table-column>  
49 - <el-table-column prop="keepaliveTime" label="最近心跳" align="center" width="140">  
50 - </el-table-column>  
51 - <el-table-column prop="registerTime" label="最近注册" align="center" width="140">  
52 - </el-table-column>  
53 - <el-table-column prop="updateTime" label="更新时间" align="center" width="140">  
54 - </el-table-column>  
55 - <el-table-column prop="createTime" label="创建时间" align="center" width="140">  
56 - </el-table-column> 2 + <div id="app" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">设备列表</div>
  5 + <div class="page-header-btn">
  6 + <el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading"
  7 + @click="getDeviceList()"></el-button>
  8 + </div>
  9 + </div>
  10 + <!-- <devicePlayer ref="devicePlayer"></devicePlayer> -->
  11 + <!--设备列表-->
  12 + <el-table :data="deviceList" border style="width: 100%;font-size: 12px;" :height="winHeight">
  13 + <el-table-column prop="name" label="名称" align="center">
  14 + </el-table-column>
  15 + <el-table-column prop="deviceId" label="设备编号" width="180" align="center">
  16 + </el-table-column>
  17 + <el-table-column label="地址" width="180" align="center">
  18 + <template slot-scope="scope">
  19 + <div slot="reference" class="name-wrapper">
  20 + <el-tag size="medium">{{ scope.row.hostAddress }}</el-tag>
  21 + </div>
  22 + </template>
  23 + </el-table-column>
  24 + <el-table-column prop="manufacturer" label="厂家" align="center">
  25 + </el-table-column>
  26 + <el-table-column label="流传输模式" align="center" width="120">
  27 + <template slot-scope="scope">
  28 + <el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择">
  29 + <el-option key="UDP" label="UDP" value="UDP"></el-option>
  30 + <el-option key="TCP-ACTIVE" label="TCP主动模式" :disabled="true" value="TCP-ACTIVE"></el-option>
  31 + <el-option key="TCP-PASSIVE" label="TCP被动模式" value="TCP-PASSIVE"></el-option>
  32 + </el-select>
  33 + </template>
  34 + </el-table-column>
  35 + <el-table-column prop="channelCount" label="通道数" align="center">
  36 + </el-table-column>
  37 + <el-table-column label="状态" width="120" align="center">
  38 + <template slot-scope="scope">
  39 + <div slot="reference" class="name-wrapper">
  40 + <el-tag size="medium" v-if="scope.row.online == 1">在线</el-tag>
  41 + <el-tag size="medium" type="info" v-if="scope.row.online == 0">离线</el-tag>
  42 + </div>
  43 + </template>
  44 + </el-table-column>
  45 + <el-table-column prop="keepaliveTime" label="最近心跳" align="center" width="140">
  46 + </el-table-column>
  47 + <el-table-column prop="registerTime" label="最近注册" align="center" width="140">
  48 + </el-table-column>
  49 + <el-table-column prop="updateTime" label="更新时间" align="center" width="140">
  50 + </el-table-column>
  51 + <el-table-column prop="createTime" label="创建时间" align="center" width="140">
  52 + </el-table-column>
57 53
58 - <el-table-column label="操作" width="450" align="center" fixed="right">  
59 - <template slot-scope="scope">  
60 - <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>  
61 - <el-button-group>  
62 - <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>  
63 - <el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary" @click="showDevicePosition(scope.row)">定位</el-button>  
64 - <el-button size="mini" icon="el-icon-edit" type="primary" @click="edit(scope.row)">编辑</el-button>  
65 - <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteDevice(scope.row)">删除</el-button>  
66 - </el-button-group>  
67 - </template>  
68 - </el-table-column>  
69 - </el-table>  
70 - <el-pagination  
71 - style="float: right"  
72 - @size-change="handleSizeChange"  
73 - @current-change="currentChange"  
74 - :current-page="currentPage"  
75 - :page-size="count"  
76 - :page-sizes="[15, 25, 35, 50]"  
77 - layout="total, sizes, prev, pager, next"  
78 - :total="total">  
79 - </el-pagination>  
80 - <deviceEdit ref="deviceEdit" ></deviceEdit>  
81 - <syncChannelProgress ref="syncChannelProgress" ></syncChannelProgress>  
82 - </el-main>  
83 - </el-container>  
84 - </div> 54 + <el-table-column label="操作" width="450" align="center" fixed="right">
  55 + <template slot-scope="scope">
  56 + <el-button size="mini" v-if="scope.row.online!=0" icon="el-icon-refresh" @click="refDevice(scope.row)"
  57 + @mouseover="getTooltipContent(scope.row.deviceId)">刷新
  58 + </el-button>
  59 + <el-button-group>
  60 + <el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0"
  61 + type="primary" @click="showChannelList(scope.row)">通道
  62 + </el-button>
  63 + <el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary"
  64 + @click="showDevicePosition(scope.row)">定位
  65 + </el-button>
  66 + <el-button size="mini" icon="el-icon-edit" type="primary" @click="edit(scope.row)">编辑</el-button>
  67 + <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteDevice(scope.row)">删除</el-button>
  68 + </el-button-group>
  69 + </template>
  70 + </el-table-column>
  71 + </el-table>
  72 + <el-pagination
  73 + style="float: right"
  74 + @size-change="handleSizeChange"
  75 + @current-change="currentChange"
  76 + :current-page="currentPage"
  77 + :page-size="count"
  78 + :page-sizes="[15, 25, 35, 50]"
  79 + layout="total, sizes, prev, pager, next"
  80 + :total="total">
  81 + </el-pagination>
  82 + <deviceEdit ref="deviceEdit"></deviceEdit>
  83 + <syncChannelProgress ref="syncChannelProgress"></syncChannelProgress>
  84 + </div>
85 </template> 85 </template>
86 86
87 <script> 87 <script>
88 - import uiHeader from './UiHeader.vue'  
89 - import deviceEdit from './dialog/deviceEdit.vue'  
90 - import syncChannelProgress from './dialog/SyncChannelProgress.vue'  
91 - export default {  
92 - name: 'app',  
93 - components: {  
94 - uiHeader,  
95 - deviceEdit,  
96 - syncChannelProgress,  
97 - },  
98 - data() {  
99 - return {  
100 - deviceList: [], //设备列表  
101 - currentDevice: {}, //当前操作设备对象 88 +import uiHeader from '../layout/UiHeader.vue'
  89 +import deviceEdit from './dialog/deviceEdit.vue'
  90 +import syncChannelProgress from './dialog/SyncChannelProgress.vue'
102 91
103 - videoComponentList: [],  
104 - updateLooper: 0, //数据刷新轮训标志  
105 - currentDeviceChannelsLenth:0,  
106 - winHeight: window.innerHeight - 200,  
107 - currentPage:1,  
108 - count:15,  
109 - total:0,  
110 - getDeviceListLoading: false,  
111 - };  
112 - },  
113 - computed: {  
114 - getcurrentDeviceChannels: function() {  
115 - let data = this.currentDevice['channelMap'];  
116 - let channels = null;  
117 - if (data) {  
118 - channels = Object.keys(data).map(key => {  
119 - return data[key];  
120 - });  
121 - this.currentDeviceChannelsLenth = channels.length;  
122 - }  
123 - return channels;  
124 - }  
125 - },  
126 - mounted() {  
127 - this.initData();  
128 - this.updateLooper = setInterval(this.initData, 10000);  
129 - },  
130 - destroyed() {  
131 - this.$destroy('videojs');  
132 - clearTimeout(this.updateLooper);  
133 - },  
134 - methods: {  
135 - initData: function() {  
136 - this.getDeviceList();  
137 - },  
138 - currentChange: function(val){  
139 - this.currentPage = val;  
140 - this.getDeviceList();  
141 - },  
142 - handleSizeChange: function(val){  
143 - this.count = val;  
144 - this.getDeviceList();  
145 - },  
146 - getDeviceList: function() {  
147 - let that = this;  
148 - this.getDeviceListLoading = true;  
149 - this.$axios({  
150 - method: 'get',  
151 - url:`/api/device/query/devices`,  
152 - params: {  
153 - page: that.currentPage,  
154 - count: that.count  
155 - }  
156 - }).then(function (res) {  
157 - that.total = res.data.total;  
158 - that.deviceList = res.data.list;  
159 - that.getDeviceListLoading = false;  
160 - }).catch(function (error) {  
161 - console.error(error);  
162 - that.getDeviceListLoading = false;  
163 - }); 92 +export default {
  93 + name: 'app',
  94 + components: {
  95 + uiHeader,
  96 + deviceEdit,
  97 + syncChannelProgress,
  98 + },
  99 + data() {
  100 + return {
  101 + deviceList: [], //设备列表
  102 + currentDevice: {}, //当前操作设备对象
164 103
165 - },  
166 - deleteDevice: function(row) {  
167 - let msg = "确定删除此设备?"  
168 - if (row.online !== 0) {  
169 - msg = "在线设备删除后仍可通过注册再次上线。<br/>如需彻底删除请先将设备离线。<br/><strong>确定删除此设备?</strong>" 104 + videoComponentList: [],
  105 + updateLooper: 0, //数据刷新轮训标志
  106 + currentDeviceChannelsLenth: 0,
  107 + winHeight: window.innerHeight - 200,
  108 + currentPage: 1,
  109 + count: 15,
  110 + total: 0,
  111 + getDeviceListLoading: false,
  112 + };
  113 + },
  114 + computed: {
  115 + getcurrentDeviceChannels: function () {
  116 + let data = this.currentDevice['channelMap'];
  117 + let channels = null;
  118 + if (data) {
  119 + channels = Object.keys(data).map(key => {
  120 + return data[key];
  121 + });
  122 + this.currentDeviceChannelsLenth = channels.length;
  123 + }
  124 + return channels;
  125 + }
  126 + },
  127 + mounted() {
  128 + this.initData();
  129 + this.updateLooper = setInterval(this.initData, 10000);
  130 + },
  131 + destroyed() {
  132 + this.$destroy('videojs');
  133 + clearTimeout(this.updateLooper);
  134 + },
  135 + methods: {
  136 + initData: function () {
  137 + this.getDeviceList();
  138 + },
  139 + currentChange: function (val) {
  140 + this.currentPage = val;
  141 + this.getDeviceList();
  142 + },
  143 + handleSizeChange: function (val) {
  144 + this.count = val;
  145 + this.getDeviceList();
  146 + },
  147 + getDeviceList: function () {
  148 + let that = this;
  149 + this.getDeviceListLoading = true;
  150 + this.$axios({
  151 + method: 'get',
  152 + url: `/api/device/query/devices`,
  153 + params: {
  154 + page: that.currentPage,
  155 + count: that.count
170 } 156 }
171 - this.$confirm(msg, '提示', {  
172 - dangerouslyUseHTMLString : true,  
173 - confirmButtonText: '确定',  
174 - cancelButtonText: '取消',  
175 - center: true,  
176 - type: 'warning'  
177 - }).then(() => {  
178 - this.$axios({  
179 - method: 'delete',  
180 - url:`/api/device/query/devices/${row.deviceId}/delete`  
181 - }).then((res)=>{  
182 - this.getDeviceList();  
183 - }).catch((error) =>{  
184 - console.error(error);  
185 - });  
186 - }).catch(() => { 157 + }).then(function (res) {
  158 + that.total = res.data.total;
  159 + that.deviceList = res.data.list;
  160 + that.getDeviceListLoading = false;
  161 + }).catch(function (error) {
  162 + console.error(error);
  163 + that.getDeviceListLoading = false;
  164 + });
187 165
  166 + },
  167 + deleteDevice: function (row) {
  168 + let msg = "确定删除此设备?"
  169 + if (row.online !== 0) {
  170 + msg = "在线设备删除后仍可通过注册再次上线。<br/>如需彻底删除请先将设备离线。<br/><strong>确定删除此设备?</strong>"
  171 + }
  172 + this.$confirm(msg, '提示', {
  173 + dangerouslyUseHTMLString: true,
  174 + confirmButtonText: '确定',
  175 + cancelButtonText: '取消',
  176 + center: true,
  177 + type: 'warning'
  178 + }).then(() => {
  179 + this.$axios({
  180 + method: 'delete',
  181 + url: `/api/device/query/devices/${row.deviceId}/delete`
  182 + }).then((res) => {
  183 + this.getDeviceList();
  184 + }).catch((error) => {
  185 + console.error(error);
188 }); 186 });
  187 + }).catch(() => {
  188 +
  189 + });
189 190
190 191
191 - },  
192 - showChannelList: function(row) {  
193 - this.$router.push(`/channelList/${row.deviceId}/0/15/1`);  
194 - },  
195 - showDevicePosition: function(row) {  
196 - this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`);  
197 - }, 192 + },
  193 + showChannelList: function (row) {
  194 + this.$router.push(`/channelList/${row.deviceId}/0/15/1`);
  195 + },
  196 + showDevicePosition: function (row) {
  197 + this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`);
  198 + },
198 199
199 - //gb28181平台对接  
200 - //刷新设备信息  
201 - refDevice: function(itemData) {  
202 - console.log("刷新对应设备:" + itemData.deviceId);  
203 - let that = this;  
204 - this.$axios({  
205 - method: 'post',  
206 - url: '/api/device/query/devices/' + itemData.deviceId + '/sync'  
207 - }).then((res) => {  
208 - console.log("刷新设备结果:"+JSON.stringify(res));  
209 - if (res.data.code !==0) {  
210 - that.$message({  
211 - showClose: true,  
212 - message: res.data.msg,  
213 - type: 'error'  
214 - });  
215 - }else{  
216 - // that.$message({  
217 - // showClose: true,  
218 - // message: res.data.msg,  
219 - // type: 'success'  
220 - // });  
221 - this.$refs.syncChannelProgress.openDialog(itemData.deviceId)  
222 - }  
223 - that.initData()  
224 - }).catch((e) => {  
225 - console.error(e) 200 + //gb28181平台对接
  201 + //刷新设备信息
  202 + refDevice: function (itemData) {
  203 + console.log("刷新对应设备:" + itemData.deviceId);
  204 + let that = this;
  205 + this.$axios({
  206 + method: 'post',
  207 + url: '/api/device/query/devices/' + itemData.deviceId + '/sync'
  208 + }).then((res) => {
  209 + console.log("刷新设备结果:" + JSON.stringify(res));
  210 + if (res.data.code !== 0) {
226 that.$message({ 211 that.$message({
227 showClose: true, 212 showClose: true,
228 - message: e, 213 + message: res.data.msg,
229 type: 'error' 214 type: 'error'
230 }); 215 });
231 - }); 216 + } else {
  217 + // that.$message({
  218 + // showClose: true,
  219 + // message: res.data.msg,
  220 + // type: 'success'
  221 + // });
  222 + this.$refs.syncChannelProgress.openDialog(itemData.deviceId)
  223 + }
  224 + that.initData()
  225 + }).catch((e) => {
  226 + console.error(e)
  227 + that.$message({
  228 + showClose: true,
  229 + message: e,
  230 + type: 'error'
  231 + });
  232 + });
232 233
233 - }, 234 + },
234 235
235 - getTooltipContent: async function (deviceId){  
236 - let result = "";  
237 - await this.$axios({  
238 - method: 'get',  
239 - async: false,  
240 - url:`/api/device/query/${deviceId}/sync_status/`,  
241 - }).then((res) => {  
242 - if (res.data.code == 0) {  
243 - if (res.data.data.errorMsg !== null) {  
244 - result = res.data.data.errorMsg  
245 - } else if (res.data.msg !== null) {  
246 - result = res.data.msg  
247 - } else {  
248 - result = `同步中...[${res.data.data.current}/${res.data.data.total}]`;  
249 - }  
250 - }  
251 - })  
252 - return result;  
253 - },  
254 - //通知设备上传媒体流  
255 - sendDevicePush: function(itemData) {  
256 - // let deviceId = this.currentDevice.deviceId;  
257 - // let channelId = itemData.channelId;  
258 - // console.log("通知设备推流1:" + deviceId + " : " + channelId);  
259 - // let that = this;  
260 - // this.$axios({  
261 - // method: 'get',  
262 - // url: '/api/play/' + deviceId + '/' + channelId  
263 - // }).then(function(res) {  
264 - // let ssrc = res.data.ssrc;  
265 - // that.$refs.devicePlayer.play(ssrc,deviceId,channelId);  
266 - // }).catch(function(e) {  
267 - // });  
268 - },  
269 - transportChange: function (row) {  
270 - console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `);  
271 - let that = this;  
272 - this.$axios({  
273 - method: 'post',  
274 - url: '/api/device/query/transport/' + row.deviceId + '/' + row.streamMode  
275 - }).then(function(res) { 236 + getTooltipContent: async function (deviceId) {
  237 + let result = "";
  238 + await this.$axios({
  239 + method: 'get',
  240 + async: false,
  241 + url: `/api/device/query/${deviceId}/sync_status/`,
  242 + }).then((res) => {
  243 + if (res.data.code == 0) {
  244 + if (res.data.data.errorMsg !== null) {
  245 + result = res.data.data.errorMsg
  246 + } else if (res.data.msg !== null) {
  247 + result = res.data.msg
  248 + } else {
  249 + result = `同步中...[${res.data.data.current}/${res.data.data.total}]`;
  250 + }
  251 + }
  252 + })
  253 + return result;
  254 + },
  255 + //通知设备上传媒体流
  256 + sendDevicePush: function (itemData) {
  257 + // let deviceId = this.currentDevice.deviceId;
  258 + // let channelId = itemData.channelId;
  259 + // console.log("通知设备推流1:" + deviceId + " : " + channelId);
  260 + // let that = this;
  261 + // this.$axios({
  262 + // method: 'get',
  263 + // url: '/api/play/' + deviceId + '/' + channelId
  264 + // }).then(function(res) {
  265 + // let ssrc = res.data.ssrc;
  266 + // that.$refs.devicePlayer.play(ssrc,deviceId,channelId);
  267 + // }).catch(function(e) {
  268 + // });
  269 + },
  270 + transportChange: function (row) {
  271 + console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `);
  272 + let that = this;
  273 + this.$axios({
  274 + method: 'post',
  275 + url: '/api/device/query/transport/' + row.deviceId + '/' + row.streamMode
  276 + }).then(function (res) {
276 277
277 - }).catch(function(e) { 278 + }).catch(function (e) {
  279 + });
  280 + },
  281 + edit: function (row) {
  282 + this.$refs.deviceEdit.openDialog(row, () => {
  283 + this.$refs.deviceEdit.close();
  284 + this.$message({
  285 + showClose: true,
  286 + message: "设备修改成功,通道字符集将在下次更新生效",
  287 + type: "success",
278 }); 288 });
279 - },  
280 - edit: function (row) {  
281 - this.$refs.deviceEdit.openDialog(row, ()=>{  
282 - this.$refs.deviceEdit.close();  
283 - this.$message({  
284 - showClose: true,  
285 - message: "设备修改成功,通道字符集将在下次更新生效",  
286 - type: "success",  
287 - });  
288 - setTimeout(this.getDeviceList, 200) 289 + setTimeout(this.getDeviceList, 200)
289 290
290 - })  
291 - } 291 + })
  292 + }
292 293
293 - }  
294 - }; 294 + }
  295 +};
295 </script> 296 </script>
296 297
297 <style> 298 <style>
298 - .videoList {  
299 - display: flex;  
300 - flex-wrap: wrap;  
301 - align-content: flex-start;  
302 - } 299 +.videoList {
  300 + display: flex;
  301 + flex-wrap: wrap;
  302 + align-content: flex-start;
  303 +}
303 304
304 - .video-item {  
305 - position: relative;  
306 - width: 15rem;  
307 - height: 10rem;  
308 - margin-right: 1rem;  
309 - background-color: #000000;  
310 - } 305 +.video-item {
  306 + position: relative;
  307 + width: 15rem;
  308 + height: 10rem;
  309 + margin-right: 1rem;
  310 + background-color: #000000;
  311 +}
311 312
312 - .video-item-img {  
313 - position: absolute;  
314 - top: 0;  
315 - bottom: 0;  
316 - left: 0;  
317 - right: 0;  
318 - margin: auto;  
319 - width: 100%;  
320 - height: 100%;  
321 - } 313 +.video-item-img {
  314 + position: absolute;
  315 + top: 0;
  316 + bottom: 0;
  317 + left: 0;
  318 + right: 0;
  319 + margin: auto;
  320 + width: 100%;
  321 + height: 100%;
  322 +}
322 323
323 - .video-item-img:after {  
324 - content: "";  
325 - display: inline-block;  
326 - position: absolute;  
327 - z-index: 2;  
328 - top: 0;  
329 - bottom: 0;  
330 - left: 0;  
331 - right: 0;  
332 - margin: auto;  
333 - width: 3rem;  
334 - height: 3rem;  
335 - background-image: url("../assets/loading.png");  
336 - background-size: cover;  
337 - background-color: #000000;  
338 - } 324 +.video-item-img:after {
  325 + content: "";
  326 + display: inline-block;
  327 + position: absolute;
  328 + z-index: 2;
  329 + top: 0;
  330 + bottom: 0;
  331 + left: 0;
  332 + right: 0;
  333 + margin: auto;
  334 + width: 3rem;
  335 + height: 3rem;
  336 + background-image: url("../assets/loading.png");
  337 + background-size: cover;
  338 + background-color: #000000;
  339 +}
339 340
340 - .video-item-title {  
341 - position: absolute;  
342 - bottom: 0;  
343 - color: #000000;  
344 - background-color: #ffffff;  
345 - line-height: 1.5rem;  
346 - padding: 0.3rem;  
347 - width: 14.4rem;  
348 - } 341 +.video-item-title {
  342 + position: absolute;
  343 + bottom: 0;
  344 + color: #000000;
  345 + background-color: #ffffff;
  346 + line-height: 1.5rem;
  347 + padding: 0.3rem;
  348 + width: 14.4rem;
  349 +}
349 </style> 350 </style>
web_src/src/components/MediaServerManger.vue
1 <template> 1 <template>
2 - <div id="mediaServerManger">  
3 - <el-container>  
4 - <el-header>  
5 - <uiHeader></uiHeader>  
6 - </el-header>  
7 - <el-main id="msMain">  
8 - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">  
9 - <span style="font-size: 1rem; font-weight: bold;">节点列表</span>  
10 - </div>  
11 - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">  
12 - <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="add">添加节点</el-button>  
13 - </div> 2 + <div id="mediaServerManger" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">节点列表</div>
  5 + <div class="page-header-btn">
  6 + <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="add">添加节点</el-button>
  7 + </div>
  8 + </div>
14 9
15 - <el-row :gutter="12">  
16 - <el-col :span="num" v-for="item in mediaServerList" :key="item.id">  
17 - <el-card shadow="hover" :body-style="{ padding: '0px'}" class="server-card">  
18 - <div class="card-img-zlm"></div>  
19 - <div style="padding: 14px;text-align: left">  
20 - <span style="font-size: 16px">{{item.id}}</span>  
21 - <el-button v-if="!item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">编辑</el-button>  
22 - <el-button v-if="item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">查看</el-button>  
23 - <el-button icon="el-icon-delete" style="margin-right: 10px;padding: 0;float: right;" type="text" @click="del(item)">移除</el-button>  
24 - <div style="margin-top: 13px; line-height: 12px; ">  
25 - <span style="font-size: 14px; color: #999; margin-top: 5px; ">{{item.ip}}</span>  
26 - <span style="font-size: 14px; color: #999; margin-top: 5px; float: right;">{{item.createTime}}</span>  
27 - </div>  
28 - </div>  
29 - <i v-if="item.status" class="iconfont icon-online server-card-status-online" title="在线"></i>  
30 - <i v-if="!item.status" class="iconfont icon-online server-card-status-offline" title="离线"></i>  
31 - <i v-if="item.defaultServer" class="server-card-default" >默认</i>  
32 - </el-card>  
33 - </el-col>  
34 - </el-row>  
35 - <mediaServerEdit ref="mediaServerEdit" ></mediaServerEdit>  
36 - </el-main>  
37 - </el-container> 10 + <el-row :gutter="12">
  11 + <el-col :span="num" v-for="item in mediaServerList" :key="item.id">
  12 + <el-card shadow="hover" :body-style="{ padding: '0px'}" class="server-card">
  13 + <div class="card-img-zlm"></div>
  14 + <div style="padding: 14px;text-align: left">
  15 + <span style="font-size: 16px">{{item.id}}</span>
  16 + <el-button v-if="!item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">编辑</el-button>
  17 + <el-button v-if="item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">查看</el-button>
  18 + <el-button icon="el-icon-delete" style="margin-right: 10px;padding: 0;float: right;" type="text" @click="del(item)">移除</el-button>
  19 + <div style="margin-top: 13px; line-height: 12px; ">
  20 + <span style="font-size: 14px; color: #999; margin-top: 5px; ">{{item.ip}}</span>
  21 + <span style="font-size: 14px; color: #999; margin-top: 5px; float: right;">{{item.createTime}}</span>
  22 + </div>
  23 + </div>
  24 + <i v-if="item.status" class="iconfont icon-online server-card-status-online" title="在线"></i>
  25 + <i v-if="!item.status" class="iconfont icon-online server-card-status-offline" title="离线"></i>
  26 + <i v-if="item.defaultServer" class="server-card-default" >默认</i>
  27 + </el-card>
  28 + </el-col>
  29 + </el-row>
  30 + <mediaServerEdit ref="mediaServerEdit" ></mediaServerEdit>
38 </div> 31 </div>
39 </template> 32 </template>
40 33
41 <script> 34 <script>
42 - import uiHeader from './UiHeader.vue' 35 + import uiHeader from '../layout/UiHeader.vue'
43 import MediaServer from './service/MediaServer' 36 import MediaServer from './service/MediaServer'
44 import mediaServerEdit from './dialog/MediaServerEdit' 37 import mediaServerEdit from './dialog/MediaServerEdit'
45 export default { 38 export default {
web_src/src/components/ParentPlatformList.vue
1 <template> 1 <template>
2 - <div id="app">  
3 - <el-container>  
4 - <el-header>  
5 - <uiHeader></uiHeader>  
6 - </el-header>  
7 - <el-main>  
8 - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">  
9 - <span style="font-size: 1rem; font-weight: bold;">上级平台列表</span>  
10 - </div>  
11 - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">  
12 - <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addParentPlatform">添加</el-button>  
13 - </div>  
14 - <!--设备列表-->  
15 - <el-table :data="platformList" border style="width: 100%" :height="winHeight">  
16 - <el-table-column prop="name" label="名称" align="center"></el-table-column>  
17 - <el-table-column prop="serverGBId" label="平台编号" width="180" align="center"></el-table-column>  
18 - <el-table-column label="是否启用" width="120" align="center">  
19 - <template slot-scope="scope">  
20 - <div slot="reference" class="name-wrapper">  
21 - <el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>  
22 - <el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>  
23 - </div>  
24 - </template>  
25 - </el-table-column>  
26 - <el-table-column label="状态" width="120" align="center">  
27 - <template slot-scope="scope">  
28 - <div slot="reference" class="name-wrapper">  
29 - <el-tag size="medium" v-if="scope.row.status">在线</el-tag>  
30 - <el-tag size="medium" type="info" v-if="!scope.row.status">离线</el-tag>  
31 - </div>  
32 - </template>  
33 - </el-table-column>  
34 - <el-table-column label="地址" width="180" align="center">  
35 - <template slot-scope="scope">  
36 - <div slot="reference" class="name-wrapper">  
37 - <el-tag size="medium">{{ scope.row.serverIP}}:{{scope.row.serverPort }}</el-tag>  
38 - </div>  
39 - </template>  
40 - </el-table-column>  
41 - <el-table-column prop="deviceGBId" label="设备国标编号" width="200" align="center"></el-table-column>  
42 - <el-table-column prop="transport" label="信令传输模式" width="120" align="center"></el-table-column>  
43 - <el-table-column prop="channelCount" label="通道数" width="120" align="center"></el-table-column>  
44 - <el-table-column label="订阅信息" width="240" align="center" fixed="right">  
45 - <template slot-scope="scope">  
46 - <i v-if="scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅" class="iconfont icon-gbaojings subscribe-on " ></i>  
47 - <i v-if="!scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅" class="iconfont icon-gbaojings subscribe-off " ></i>  
48 - <i v-if="scope.row.catalogSubscribe" title="目录订阅" class="iconfont icon-gjichus subscribe-on" ></i>  
49 - <i v-if="!scope.row.catalogSubscribe" title="目录订阅" class="iconfont icon-gjichus subscribe-off" ></i>  
50 - <i v-if="scope.row.mobilePositionSubscribe" title="位置订阅" class="iconfont icon-gxunjians subscribe-on" ></i>  
51 - <i v-if="!scope.row.mobilePositionSubscribe" title="位置订阅" class="iconfont icon-gxunjians subscribe-off" ></i>  
52 - </template>  
53 - </el-table-column> 2 + <div id="app" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">上级平台列表</div>
  5 + <div class="page-header-btn">
  6 + <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addParentPlatform">添加</el-button>
  7 + </div>
  8 + </div>
54 9
55 - <el-table-column label="操作" width="300" align="center" fixed="right">  
56 - <template slot-scope="scope">  
57 - <el-button size="mini" icon="el-icon-edit" @click="editPlatform(scope.row)">编辑</el-button>  
58 - <el-button size="mini" icon="el-icon-share" type="primary" @click="chooseChannel(scope.row)">选择通道</el-button>  
59 - <el-button size="mini" icon="el-icon-delete" type="danger" @click="deletePlatform(scope.row)">删除</el-button>  
60 - </template>  
61 - </el-table-column>  
62 - </el-table>  
63 - <el-pagination  
64 - style="float: right"  
65 - @size-change="handleSizeChange"  
66 - @current-change="currentChange"  
67 - :current-page="currentPage"  
68 - :page-size="count"  
69 - :page-sizes="[15, 25, 35, 50]"  
70 - layout="total, sizes, prev, pager, next"  
71 - :total="total">  
72 - </el-pagination>  
73 - <platformEdit ref="platformEdit" ></platformEdit>  
74 - <chooseChannelDialog ref="chooseChannelDialog" ></chooseChannelDialog>  
75 - </el-main>  
76 - </el-container> 10 + <!--设备列表-->
  11 + <el-table :data="platformList" border style="width: 100%" :height="winHeight">
  12 + <el-table-column prop="name" label="名称" align="center"></el-table-column>
  13 + <el-table-column prop="serverGBId" label="平台编号" align="center"></el-table-column>
  14 + <el-table-column label="是否启用" width="120" align="center">
  15 + <template slot-scope="scope">
  16 + <div slot="reference" class="name-wrapper">
  17 + <el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>
  18 + <el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
  19 + </div>
  20 + </template>
  21 + </el-table-column>
  22 + <el-table-column label="状态" width="120" align="center">
  23 + <template slot-scope="scope">
  24 + <div slot="reference" class="name-wrapper">
  25 + <el-tag size="medium" v-if="scope.row.status">在线</el-tag>
  26 + <el-tag size="medium" type="info" v-if="!scope.row.status">离线</el-tag>
  27 + </div>
  28 + </template>
  29 + </el-table-column>
  30 + <el-table-column label="地址" width="180" align="center">
  31 + <template slot-scope="scope">
  32 + <div slot="reference" class="name-wrapper">
  33 + <el-tag size="medium">{{ scope.row.serverIP}}:{{scope.row.serverPort }}</el-tag>
  34 + </div>
  35 + </template>
  36 + </el-table-column>
  37 + <el-table-column prop="deviceGBId" label="设备国标编号" width="200" align="center"></el-table-column>
  38 + <el-table-column prop="transport" label="信令传输模式" width="120" align="center"></el-table-column>
  39 + <el-table-column prop="channelCount" label="通道数" width="120" align="center"></el-table-column>
  40 + <el-table-column label="订阅信息" width="240" align="center" fixed="right">
  41 + <template slot-scope="scope">
  42 + <i v-if="scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅" class="iconfont icon-gbaojings subscribe-on " ></i>
  43 + <i v-if="!scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅" class="iconfont icon-gbaojings subscribe-off " ></i>
  44 + <i v-if="scope.row.catalogSubscribe" title="目录订阅" class="iconfont icon-gjichus subscribe-on" ></i>
  45 + <i v-if="!scope.row.catalogSubscribe" title="目录订阅" class="iconfont icon-gjichus subscribe-off" ></i>
  46 + <i v-if="scope.row.mobilePositionSubscribe" title="位置订阅" class="iconfont icon-gxunjians subscribe-on" ></i>
  47 + <i v-if="!scope.row.mobilePositionSubscribe" title="位置订阅" class="iconfont icon-gxunjians subscribe-off" ></i>
  48 + </template>
  49 + </el-table-column>
  50 +
  51 + <el-table-column label="操作" width="300" align="center" fixed="right">
  52 + <template slot-scope="scope">
  53 + <el-button size="mini" icon="el-icon-edit" @click="editPlatform(scope.row)">编辑</el-button>
  54 + <el-button size="mini" icon="el-icon-share" type="primary" @click="chooseChannel(scope.row)">选择通道</el-button>
  55 + <el-button size="mini" icon="el-icon-delete" type="danger" @click="deletePlatform(scope.row)">删除</el-button>
  56 + </template>
  57 + </el-table-column>
  58 + </el-table>
  59 + <el-pagination
  60 + style="float: right"
  61 + @size-change="handleSizeChange"
  62 + @current-change="currentChange"
  63 + :current-page="currentPage"
  64 + :page-size="count"
  65 + :page-sizes="[15, 25, 35, 50]"
  66 + layout="total, sizes, prev, pager, next"
  67 + :total="total">
  68 + </el-pagination>
  69 + <platformEdit ref="platformEdit" ></platformEdit>
  70 + <chooseChannelDialog ref="chooseChannelDialog" ></chooseChannelDialog>
77 </div> 71 </div>
78 </template> 72 </template>
79 73
80 <script> 74 <script>
81 import platformEdit from './dialog/platformEdit.vue' 75 import platformEdit from './dialog/platformEdit.vue'
82 -import uiHeader from './UiHeader.vue' 76 +import uiHeader from '../layout/UiHeader.vue'
83 import chooseChannelDialog from './dialog/chooseChannel.vue' 77 import chooseChannelDialog from './dialog/chooseChannel.vue'
84 export default { 78 export default {
85 name: 'app', 79 name: 'app',
web_src/src/components/PushVideoList.vue
1 <template> 1 <template>
2 - <div id="pushVideoList">  
3 - <el-container>  
4 - <el-header>  
5 - <uiHeader></uiHeader>  
6 - </el-header>  
7 - <el-main>  
8 - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">  
9 - <span style="font-size: 1rem; font-weight: bold;">推流列表</span>  
10 - </div>  
11 - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">  
12 -  
13 - 搜索: <el-input @input="getPushList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字" prefix-icon="el-icon-search" v-model="searchSrt" clearable> </el-input>  
14 -  
15 - 流媒体: <el-select size="mini" @change="getPushList" style="margin-right: 1rem;" v-model="mediaServerId" placeholder="请选择" default-first-option> 2 + <div id="pushVideoList" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">推流列表</div>
  5 + <div class="page-header-btn">
  6 + 搜索:
  7 + <el-input @input="getPushList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
  8 + prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
  9 + 流媒体:
  10 + <el-select size="mini" @change="getPushList" style="margin-right: 1rem;" v-model="mediaServerId"
  11 + placeholder="请选择" default-first-option>
16 <el-option label="全部" value=""></el-option> 12 <el-option label="全部" value=""></el-option>
17 <el-option 13 <el-option
18 v-for="item in mediaServerList" 14 v-for="item in mediaServerList"
@@ -21,309 +17,327 @@ @@ -21,309 +17,327 @@
21 :value="item.id"> 17 :value="item.id">
22 </el-option> 18 </el-option>
23 </el-select> 19 </el-select>
24 - 推流状态: <el-select size="mini" style="margin-right: 1rem;" @change="getPushList" v-model="pushing" placeholder="请选择" default-first-option> 20 + 推流状态:
  21 + <el-select size="mini" style="margin-right: 1rem;" @change="getPushList" v-model="pushing" placeholder="请选择"
  22 + default-first-option>
25 <el-option label="全部" value=""></el-option> 23 <el-option label="全部" value=""></el-option>
26 <el-option label="推流进行中" value="true"></el-option> 24 <el-option label="推流进行中" value="true"></el-option>
27 <el-option label="推流未进行" value="false"></el-option> 25 <el-option label="推流未进行" value="false"></el-option>
28 </el-select> 26 </el-select>
29 - <el-button icon="el-icon-upload2" size="mini" style="margin-right: 1rem;" type="primary" @click="importChannel">通道导入</el-button>  
30 - <el-button icon="el-icon-download" size="mini" style="margin-right: 1rem;" type="primary" >  
31 - <a style="color: #FFFFFF; text-align: center; text-decoration: none" href="/static/file/推流通道导入.zip" download='推流通道导入.zip' >下载模板</a>  
32 - </el-button>  
33 - <el-button icon="el-icon-delete" size="mini" style="margin-right: 1rem;" :disabled="multipleSelection.length === 0" type="danger" @click="batchDel">批量移除</el-button>  
34 - </div>  
35 - <devicePlayer ref="devicePlayer"></devicePlayer>  
36 - <addStreamTOGB ref="addStreamTOGB"></addStreamTOGB>  
37 - <el-table ref="pushListTable" :data="pushList" border style="width: 100%" :height="winHeight" @selection-change="handleSelectionChange" :row-key="(row)=> row.app + row.stream">  
38 - <el-table-column align="center" type="selection" :reserve-selection="true" width="55">  
39 - </el-table-column>  
40 - <el-table-column prop="name" label="名称" align="center">  
41 - </el-table-column>  
42 - <el-table-column prop="app" label="APP" align="center">  
43 - </el-table-column>  
44 - <el-table-column prop="stream" label="流ID" align="center">  
45 - </el-table-column>  
46 - <el-table-column prop="gbId" label="国标编码" width="200" align="center">  
47 - </el-table-column>  
48 - <el-table-column prop="mediaServerId" label="流媒体" width="200" align="center">  
49 - </el-table-column>  
50 - <el-table-column label="开始时间" align="center" width="200">  
51 - <template slot-scope="scope">  
52 - <el-button-group>  
53 - {{dateFormat(parseInt(scope.row.createStamp))}}  
54 - </el-button-group>  
55 - </template>  
56 - </el-table-column>  
57 - <el-table-column label="正在推流" align="center" width="100">  
58 - <template slot-scope="scope">  
59 - {{(scope.row.status == false && scope.row.gbId == null) || scope.row.status ?'是':'否'}}  
60 - </template>  
61 - </el-table-column> 27 + <el-button icon="el-icon-upload2" size="mini" style="margin-right: 1rem;" type="primary" @click="importChannel">
  28 + 通道导入
  29 + </el-button>
  30 + <el-button icon="el-icon-download" size="mini" style="margin-right: 1rem;" type="primary">
  31 + <a style="color: #FFFFFF; text-align: center; text-decoration: none" href="/static/file/推流通道导入.zip"
  32 + download='推流通道导入.zip'>下载模板</a>
  33 + </el-button>
  34 + <el-button icon="el-icon-delete" size="mini" style="margin-right: 1rem;"
  35 + :disabled="multipleSelection.length === 0" type="danger" @click="batchDel">批量移除
  36 + </el-button>
  37 + </div>
  38 + </div>
  39 + <devicePlayer ref="devicePlayer"></devicePlayer>
  40 + <addStreamTOGB ref="addStreamTOGB"></addStreamTOGB>
  41 + <el-table ref="pushListTable" :data="pushList" border style="width: 100%" :height="winHeight"
  42 + @selection-change="handleSelectionChange" :row-key="(row)=> row.app + row.stream">
  43 + <el-table-column align="center" type="selection" :reserve-selection="true" width="55">
  44 + </el-table-column>
  45 + <el-table-column prop="name" label="名称" align="center">
  46 + </el-table-column>
  47 + <el-table-column prop="app" label="APP" align="center">
  48 + </el-table-column>
  49 + <el-table-column prop="stream" label="流ID" align="center">
  50 + </el-table-column>
  51 + <el-table-column prop="gbId" label="国标编码" width="200" align="center">
  52 + </el-table-column>
  53 + <el-table-column prop="mediaServerId" label="流媒体" width="200" align="center">
  54 + </el-table-column>
  55 + <el-table-column label="开始时间" align="center" width="200">
  56 + <template slot-scope="scope">
  57 + <el-button-group>
  58 + {{ dateFormat(parseInt(scope.row.createStamp)) }}
  59 + </el-button-group>
  60 + </template>
  61 + </el-table-column>
  62 + <el-table-column label="正在推流" align="center" width="100">
  63 + <template slot-scope="scope">
  64 + {{ (scope.row.status == false && scope.row.gbId == null) || scope.row.status ? '是' : '否' }}
  65 + </template>
  66 + </el-table-column>
62 67
63 - <el-table-column label="操作" width="360" align="center" fixed="right">  
64 - <template slot-scope="scope">  
65 - <el-button-group>  
66 - <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>  
67 - <el-button size="mini" icon="el-icon-delete" type="danger" @click="stopPush(scope.row)">移除</el-button>  
68 - <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!!scope.row.gbId" @click="addToGB(scope.row)">加入国标</el-button>  
69 - <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!scope.row.gbId" @click="removeFromGB(scope.row)">移出国标</el-button>  
70 - </el-button-group>  
71 - </template>  
72 - </el-table-column>  
73 - </el-table>  
74 - <el-pagination  
75 - style="float: right"  
76 - @size-change="handleSizeChange"  
77 - @current-change="currentChange"  
78 - :current-page="currentPage"  
79 - :page-size="count"  
80 - :page-sizes="[15, 25, 35, 50]"  
81 - layout="total, sizes, prev, pager, next"  
82 - :total="total">  
83 - </el-pagination>  
84 - <streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit>  
85 - <importChannel ref="importChannel" ></importChannel>  
86 - </el-main>  
87 - </el-container>  
88 - </div> 68 + <el-table-column label="操作" width="360" align="center" fixed="right">
  69 + <template slot-scope="scope">
  70 + <el-button-group>
  71 + <el-button size="mini" icon="el-icon-video-play"
  72 + v-if="(scope.row.status == false && scope.row.gbId == null) || scope.row.status"
  73 + @click="playPush(scope.row)">播放
  74 + </el-button>
  75 + <el-button size="mini" icon="el-icon-delete" type="danger" @click="stopPush(scope.row)">移除</el-button>
  76 + <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!!scope.row.gbId"
  77 + @click="addToGB(scope.row)">加入国标
  78 + </el-button>
  79 + <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!scope.row.gbId"
  80 + @click="removeFromGB(scope.row)">移出国标
  81 + </el-button>
  82 + </el-button-group>
  83 + </template>
  84 + </el-table-column>
  85 + </el-table>
  86 + <el-pagination
  87 + style="float: right"
  88 + @size-change="handleSizeChange"
  89 + @current-change="currentChange"
  90 + :current-page="currentPage"
  91 + :page-size="count"
  92 + :page-sizes="[15, 25, 35, 50]"
  93 + layout="total, sizes, prev, pager, next"
  94 + :total="total">
  95 + </el-pagination>
  96 + <streamProxyEdit ref="streamProxyEdit"></streamProxyEdit>
  97 + <importChannel ref="importChannel"></importChannel>
  98 + </div>
89 </template> 99 </template>
90 100
91 <script> 101 <script>
92 - import streamProxyEdit from './dialog/StreamProxyEdit.vue'  
93 - import devicePlayer from './dialog/devicePlayer.vue'  
94 - import addStreamTOGB from './dialog/addStreamTOGB.vue'  
95 - import uiHeader from './UiHeader.vue'  
96 - import importChannel from './dialog/importChannel.vue'  
97 - import MediaServer from './service/MediaServer'  
98 - export default {  
99 - name: 'pushVideoList',  
100 - components: {  
101 - devicePlayer,  
102 - addStreamTOGB,  
103 - streamProxyEdit,  
104 - uiHeader,  
105 - importChannel,  
106 - },  
107 - data() {  
108 - return {  
109 - pushList: [], //设备列表  
110 - currentPusher: {}, //当前操作设备对象  
111 - updateLooper: 0, //数据刷新轮训标志  
112 - currentDeviceChannelsLenth:0,  
113 - winHeight: window.innerHeight - 250,  
114 - mediaServerObj : new MediaServer(),  
115 - currentPage:1,  
116 - count:15,  
117 - total:0,  
118 - searchSrt: "",  
119 - pushing: "",  
120 - mediaServerId: "",  
121 - mediaServerList: [],  
122 - multipleSelection: [],  
123 - getDeviceListLoading: false  
124 - };  
125 - },  
126 - computed: {  
127 - },  
128 - mounted() {  
129 - this.initData();  
130 - this.updateLooper = setInterval(this.getPushList, 2000);  
131 - },  
132 - destroyed() {  
133 - clearTimeout(this.updateLooper);  
134 - },  
135 - methods: {  
136 - initData: function() {  
137 - this.mediaServerObj.getOnlineMediaServerList((data)=>{  
138 - this.mediaServerList = data.data;  
139 - })  
140 - this.getPushList();  
141 - },  
142 - currentChange: function(val){  
143 - this.currentPage = val;  
144 - this.getPushList();  
145 - },  
146 - handleSizeChange: function(val){  
147 - this.count = val;  
148 - this.getPushList();  
149 - },  
150 - getPushList: function() {  
151 - let that = this;  
152 - this.getDeviceListLoading = true;  
153 - this.$axios({  
154 - method: 'get',  
155 - url:`/api/push/list`,  
156 - params: {  
157 - page: that.currentPage,  
158 - count: that.count,  
159 - query: that.searchSrt,  
160 - pushing: that.pushing,  
161 - mediaServerId: that.mediaServerId,  
162 - }  
163 - }).then(function (res) {  
164 - that.total = res.data.total;  
165 - that.pushList = res.data.list;  
166 - that.getDeviceListLoading = false;  
167 - }).catch(function (error) {  
168 - console.error(error);  
169 - that.getDeviceListLoading = false;  
170 - });  
171 - }, 102 +import streamProxyEdit from './dialog/StreamProxyEdit.vue'
  103 +import devicePlayer from './dialog/devicePlayer.vue'
  104 +import addStreamTOGB from './dialog/addStreamTOGB.vue'
  105 +import uiHeader from '../layout/UiHeader.vue'
  106 +import importChannel from './dialog/importChannel.vue'
  107 +import MediaServer from './service/MediaServer'
  108 +
  109 +export default {
  110 + name: 'pushVideoList',
  111 + components: {
  112 + devicePlayer,
  113 + addStreamTOGB,
  114 + streamProxyEdit,
  115 + uiHeader,
  116 + importChannel,
  117 + },
  118 + data() {
  119 + return {
  120 + pushList: [], //设备列表
  121 + currentPusher: {}, //当前操作设备对象
  122 + updateLooper: 0, //数据刷新轮训标志
  123 + currentDeviceChannelsLenth: 0,
  124 + winHeight: window.innerHeight - 250,
  125 + mediaServerObj: new MediaServer(),
  126 + currentPage: 1,
  127 + count: 15,
  128 + total: 0,
  129 + searchSrt: "",
  130 + pushing: "",
  131 + mediaServerId: "",
  132 + mediaServerList: [],
  133 + multipleSelection: [],
  134 + getDeviceListLoading: false
  135 + };
  136 + },
  137 + computed: {},
  138 + mounted() {
  139 + this.initData();
  140 + this.updateLooper = setInterval(this.getPushList, 2000);
  141 + },
  142 + destroyed() {
  143 + clearTimeout(this.updateLooper);
  144 + },
  145 + methods: {
  146 + initData: function () {
  147 + this.mediaServerObj.getOnlineMediaServerList((data) => {
  148 + this.mediaServerList = data.data;
  149 + })
  150 + this.getPushList();
  151 + },
  152 + currentChange: function (val) {
  153 + this.currentPage = val;
  154 + this.getPushList();
  155 + },
  156 + handleSizeChange: function (val) {
  157 + this.count = val;
  158 + this.getPushList();
  159 + },
  160 + getPushList: function () {
  161 + let that = this;
  162 + this.getDeviceListLoading = true;
  163 + this.$axios({
  164 + method: 'get',
  165 + url: `/api/push/list`,
  166 + params: {
  167 + page: that.currentPage,
  168 + count: that.count,
  169 + query: that.searchSrt,
  170 + pushing: that.pushing,
  171 + mediaServerId: that.mediaServerId,
  172 + }
  173 + }).then(function (res) {
  174 + that.total = res.data.total;
  175 + that.pushList = res.data.list;
  176 + that.getDeviceListLoading = false;
  177 + }).catch(function (error) {
  178 + console.error(error);
  179 + that.getDeviceListLoading = false;
  180 + });
  181 + },
172 182
173 - playPush: function(row){  
174 - let that = this;  
175 - this.getListLoading = true;  
176 - this.$axios({  
177 - method: 'get',  
178 - url: '/api/media/stream_info_by_app_and_stream',  
179 - params: {  
180 - app: row.app,  
181 - stream: row.stream,  
182 - mediaServerId: row.mediaServerId  
183 - }  
184 - }).then(function (res) {  
185 - that.getListLoading = false;  
186 - that.$refs.devicePlayer.openDialog("streamPlay", null, null, {  
187 - streamInfo: res.data.data,  
188 - hasAudio: true  
189 - });  
190 - }).catch(function (error) {  
191 - console.error(error);  
192 - that.getListLoading = false;  
193 - });  
194 - },  
195 - stopPush: function(row){ 183 + playPush: function (row) {
  184 + let that = this;
  185 + this.getListLoading = true;
  186 + this.$axios({
  187 + method: 'get',
  188 + url: '/api/media/stream_info_by_app_and_stream',
  189 + params: {
  190 + app: row.app,
  191 + stream: row.stream,
  192 + mediaServerId: row.mediaServerId
  193 + }
  194 + }).then(function (res) {
  195 + that.getListLoading = false;
  196 + that.$refs.devicePlayer.openDialog("streamPlay", null, null, {
  197 + streamInfo: res.data.data,
  198 + hasAudio: true
  199 + });
  200 + }).catch(function (error) {
  201 + console.error(error);
  202 + that.getListLoading = false;
  203 + });
  204 + },
  205 + stopPush: function (row) {
  206 + let that = this;
  207 + that.$axios({
  208 + method: "post",
  209 + url: "/api/push/stop",
  210 + params: {
  211 + app: row.app,
  212 + streamId: row.stream
  213 + }
  214 + }).then((res) => {
  215 + if (res.data == "success") {
  216 + that.initData()
  217 + }
  218 + }).catch(function (error) {
  219 + console.error(error);
  220 + });
  221 + },
  222 + addToGB: function (row) {
  223 + this.$refs.addStreamTOGB.openDialog({
  224 + app: row.app,
  225 + stream: row.stream,
  226 + mediaServerId: row.mediaServerId
  227 + }, this.initData);
  228 + },
  229 + removeFromGB: function (row) {
  230 + let that = this;
  231 + that.$axios({
  232 + method: "delete",
  233 + url: "/api/push/remove_form_gb",
  234 + data: row
  235 + }).then((res) => {
  236 + if (res.data == "success") {
  237 + that.initData()
  238 + }
  239 + }).catch(function (error) {
  240 + console.error(error);
  241 + });
  242 + },
  243 + dateFormat: function (/** timestamp=0 **/) {
  244 + let ts = arguments[0] || 0;
  245 + let t, y, m, d, h, i, s;
  246 + t = ts ? new Date(ts) : new Date();
  247 + y = t.getFullYear();
  248 + m = t.getMonth() + 1;
  249 + d = t.getDate();
  250 + h = t.getHours();
  251 + i = t.getMinutes();
  252 + s = t.getSeconds();
  253 + // 可根据需要在这里定义时间格式
  254 + 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);
  255 + },
  256 + importChannel: function () {
  257 + this.$refs.importChannel.openDialog(() => {
  258 +
  259 + })
  260 + },
  261 + batchDel: function () {
  262 + this.$confirm(`确定删除选中的${this.multipleSelection.length}个通道?`, '提示', {
  263 + confirmButtonText: '确定',
  264 + cancelButtonText: '取消',
  265 + type: 'warning'
  266 + }).then(() => {
196 let that = this; 267 let that = this;
197 that.$axios({ 268 that.$axios({
198 - method:"post",  
199 - url:"/api/push/stop",  
200 - params: {  
201 - app: row.app,  
202 - streamId: row.stream  
203 - }  
204 - }).then((res)=>{  
205 - if (res.data == "success") {  
206 - that.initData() 269 + method: "delete",
  270 + url: "/api/push/batchStop",
  271 + data: {
  272 + gbStreams: this.multipleSelection
207 } 273 }
  274 + }).then((res) => {
  275 + this.initData();
  276 + this.$refs.pushListTable.clearSelection();
208 }).catch(function (error) { 277 }).catch(function (error) {
209 console.error(error); 278 console.error(error);
210 }); 279 });
211 - },  
212 - addToGB: function(row){  
213 - this.$refs.addStreamTOGB.openDialog({app: row.app, stream: row.stream, mediaServerId: row.mediaServerId}, this.initData);  
214 - },  
215 - removeFromGB: function(row){  
216 - let that = this;  
217 - that.$axios({  
218 - method:"delete",  
219 - url:"/api/push/remove_form_gb",  
220 - data:row  
221 - }).then((res)=>{  
222 - if (res.data == "success") {  
223 - that.initData()  
224 - }  
225 - }).catch(function (error) {  
226 - console.error(error);  
227 - });  
228 - },  
229 - dateFormat: function(/** timestamp=0 **/) {  
230 - let ts = arguments[0] || 0;  
231 - let t,y,m,d,h,i,s;  
232 - t = ts ? new Date(ts) : new Date();  
233 - y = t.getFullYear();  
234 - m = t.getMonth()+1;  
235 - d = t.getDate();  
236 - h = t.getHours();  
237 - i = t.getMinutes();  
238 - s = t.getSeconds();  
239 - // 可根据需要在这里定义时间格式  
240 - 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);  
241 - },  
242 - importChannel: function () {  
243 - this.$refs.importChannel.openDialog(()=>{ 280 + }).catch(() => {
244 281
245 - })  
246 - },  
247 - batchDel: function () {  
248 - this.$confirm(`确定删除选中的${this.multipleSelection.length}个通道?`, '提示', {  
249 - confirmButtonText: '确定',  
250 - cancelButtonText: '取消',  
251 - type: 'warning'  
252 - }).then(() => {  
253 - let that = this;  
254 - that.$axios({  
255 - method:"delete",  
256 - url:"/api/push/batchStop",  
257 - data: {  
258 - gbStreams: this.multipleSelection  
259 - }  
260 - }).then((res)=>{  
261 - this.initData();  
262 - this.$refs.pushListTable.clearSelection();  
263 - }).catch(function (error) {  
264 - console.error(error);  
265 - });  
266 - }).catch(() => {  
267 -  
268 - });  
269 - },  
270 - handleSelectionChange: function (val) {  
271 - this.multipleSelection = val;  
272 - },  
273 - }  
274 - }; 282 + });
  283 + },
  284 + handleSelectionChange: function (val) {
  285 + this.multipleSelection = val;
  286 + },
  287 + }
  288 +};
275 </script> 289 </script>
276 290
277 <style> 291 <style>
278 - .videoList {  
279 - display: flex;  
280 - flex-wrap: wrap;  
281 - align-content: flex-start;  
282 - } 292 +.videoList {
  293 + display: flex;
  294 + flex-wrap: wrap;
  295 + align-content: flex-start;
  296 +}
283 297
284 - .video-item {  
285 - position: relative;  
286 - width: 15rem;  
287 - height: 10rem;  
288 - margin-right: 1rem;  
289 - background-color: #000000;  
290 - } 298 +.video-item {
  299 + position: relative;
  300 + width: 15rem;
  301 + height: 10rem;
  302 + margin-right: 1rem;
  303 + background-color: #000000;
  304 +}
291 305
292 - .video-item-img {  
293 - position: absolute;  
294 - top: 0;  
295 - bottom: 0;  
296 - left: 0;  
297 - right: 0;  
298 - margin: auto;  
299 - width: 100%;  
300 - height: 100%;  
301 - } 306 +.video-item-img {
  307 + position: absolute;
  308 + top: 0;
  309 + bottom: 0;
  310 + left: 0;
  311 + right: 0;
  312 + margin: auto;
  313 + width: 100%;
  314 + height: 100%;
  315 +}
302 316
303 - .video-item-img:after {  
304 - content: "";  
305 - display: inline-block;  
306 - position: absolute;  
307 - z-index: 2;  
308 - top: 0;  
309 - bottom: 0;  
310 - left: 0;  
311 - right: 0;  
312 - margin: auto;  
313 - width: 3rem;  
314 - height: 3rem;  
315 - background-image: url("../assets/loading.png");  
316 - background-size: cover;  
317 - background-color: #000000;  
318 - } 317 +.video-item-img:after {
  318 + content: "";
  319 + display: inline-block;
  320 + position: absolute;
  321 + z-index: 2;
  322 + top: 0;
  323 + bottom: 0;
  324 + left: 0;
  325 + right: 0;
  326 + margin: auto;
  327 + width: 3rem;
  328 + height: 3rem;
  329 + background-image: url("../assets/loading.png");
  330 + background-size: cover;
  331 + background-color: #000000;
  332 +}
319 333
320 - .video-item-title {  
321 - position: absolute;  
322 - bottom: 0;  
323 - color: #000000;  
324 - background-color: #ffffff;  
325 - line-height: 1.5rem;  
326 - padding: 0.3rem;  
327 - width: 14.4rem;  
328 - } 334 +.video-item-title {
  335 + position: absolute;
  336 + bottom: 0;
  337 + color: #000000;
  338 + background-color: #ffffff;
  339 + line-height: 1.5rem;
  340 + padding: 0.3rem;
  341 + width: 14.4rem;
  342 +}
329 </style> 343 </style>
web_src/src/components/StreamProxyList.vue
1 <template> 1 <template>
2 - <div id="streamProxyList">  
3 - <el-container>  
4 - <el-header>  
5 - <uiHeader></uiHeader>  
6 - </el-header>  
7 - <el-main>  
8 - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">  
9 - <span style="font-size: 1rem; font-weight: bold;">拉流代理列表</span>  
10 - </div>  
11 - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">  
12 - <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">添加代理</el-button>  
13 - <el-button v-if="false" icon="el-icon-search" size="mini" style="margin-right: 1rem;" type="primary" @click="addOnvif">搜索ONVIF</el-button>  
14 - </div>  
15 - <devicePlayer ref="devicePlayer"></devicePlayer>  
16 - <el-table :data="streamProxyList" border style="width: 100%" :height="winHeight">  
17 - <el-table-column prop="name" label="名称" align="center" show-overflow-tooltip/>  
18 - <el-table-column prop="app" label="流应用名" align="center" show-overflow-tooltip/>  
19 - <el-table-column prop="stream" label="流ID" align="center" show-overflow-tooltip/>  
20 - <el-table-column label="流地址" width="400" align="center" show-overflow-tooltip >  
21 - <template slot-scope="scope">  
22 - <div slot="reference" class="name-wrapper"> 2 + <div id="streamProxyList" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">拉流代理列表</div>
  5 + <div class="page-header-btn">
  6 + <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">添加代理</el-button>
  7 + <el-button v-if="false" icon="el-icon-search" size="mini" style="margin-right: 1rem;" type="primary" @click="addOnvif">搜索ONVIF</el-button>
  8 + </div>
  9 + </div>
  10 + <devicePlayer ref="devicePlayer"></devicePlayer>
  11 + <el-table :data="streamProxyList" border style="width: 100%" :height="winHeight">
  12 + <el-table-column prop="name" label="名称" align="center" show-overflow-tooltip/>
  13 + <el-table-column prop="app" label="流应用名" align="center" show-overflow-tooltip/>
  14 + <el-table-column prop="stream" label="流ID" align="center" show-overflow-tooltip/>
  15 + <el-table-column label="流地址" width="400" align="center" show-overflow-tooltip >
  16 + <template slot-scope="scope">
  17 + <div slot="reference" class="name-wrapper">
23 18
24 - <el-tag size="medium" v-if="scope.row.type == 'default'">  
25 - <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>  
26 - {{scope.row.url}}  
27 - </el-tag>  
28 - <el-tag size="medium" v-if="scope.row.type != 'default'">  
29 - <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.src_url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>  
30 - {{scope.row.src_url}}  
31 - </el-tag>  
32 - </div>  
33 - </template>  
34 - </el-table-column>  
35 - <el-table-column prop="mediaServerId" label="流媒体" width="150" align="center"></el-table-column>  
36 - <el-table-column label="类型" width="100" align="center">  
37 - <template slot-scope="scope">  
38 - <div slot="reference" class="name-wrapper">  
39 - <el-tag size="medium">{{scope.row.type}}</el-tag>  
40 - </div>  
41 - </template>  
42 - </el-table-column> 19 + <el-tag size="medium" v-if="scope.row.type == 'default'">
  20 + <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
  21 + {{scope.row.url}}
  22 + </el-tag>
  23 + <el-tag size="medium" v-if="scope.row.type != 'default'">
  24 + <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.src_url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
  25 + {{scope.row.src_url}}
  26 + </el-tag>
  27 + </div>
  28 + </template>
  29 + </el-table-column>
  30 + <el-table-column prop="mediaServerId" label="流媒体" width="150" align="center"></el-table-column>
  31 + <el-table-column label="类型" width="100" align="center">
  32 + <template slot-scope="scope">
  33 + <div slot="reference" class="name-wrapper">
  34 + <el-tag size="medium">{{scope.row.type}}</el-tag>
  35 + </div>
  36 + </template>
  37 + </el-table-column>
43 38
44 - <el-table-column prop="gbId" label="国标编码" width="180" align="center" show-overflow-tooltip/>  
45 - <el-table-column label="状态" width="120" align="center">  
46 - <template slot-scope="scope">  
47 - <div slot="reference" class="name-wrapper">  
48 - <el-tag size="medium" v-if="scope.row.status">在线</el-tag>  
49 - <el-tag size="medium" type="info" v-if="!scope.row.status">离线</el-tag>  
50 - </div>  
51 - </template>  
52 - </el-table-column>  
53 - <el-table-column label="启用" width="120" align="center">  
54 - <template slot-scope="scope">  
55 - <div slot="reference" class="name-wrapper">  
56 - <el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>  
57 - <el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>  
58 - </div>  
59 - </template>  
60 - </el-table-column>  
61 - <el-table-column prop="createTime" label="创建时间" align="center" width="150" show-overflow-tooltip/>  
62 - <el-table-column label="转HLS" width="120" align="center">  
63 - <template slot-scope="scope">  
64 - <div slot="reference" class="name-wrapper">  
65 - <el-tag size="medium" v-if="scope.row.enable_hls">已启用</el-tag>  
66 - <el-tag size="medium" type="info" v-if="!scope.row.enable_hls">未启用</el-tag>  
67 - </div>  
68 - </template>  
69 - </el-table-column>  
70 - <el-table-column label="MP4录制" width="120" align="center">  
71 - <template slot-scope="scope">  
72 - <div slot="reference" class="name-wrapper">  
73 - <el-tag size="medium" v-if="scope.row.enable_mp4">已启用</el-tag>  
74 - <el-tag size="medium" type="info" v-if="!scope.row.enable_mp4">未启用</el-tag>  
75 - </div>  
76 - </template>  
77 - </el-table-column>  
78 - <el-table-column label="无人观看自动删除" width="160" align="center">  
79 - <template slot-scope="scope">  
80 - <div slot="reference" class="name-wrapper">  
81 - <el-tag size="medium" v-if="scope.row.enable_remove_none_reader">已启用</el-tag>  
82 - <el-tag size="medium" type="info" v-if="!scope.row.enable_remove_none_reader">未启用</el-tag>  
83 - </div>  
84 - </template>  
85 - </el-table-column> 39 + <el-table-column prop="gbId" label="国标编码" width="180" align="center" show-overflow-tooltip/>
  40 + <el-table-column label="状态" width="120" align="center">
  41 + <template slot-scope="scope">
  42 + <div slot="reference" class="name-wrapper">
  43 + <el-tag size="medium" v-if="scope.row.status">在线</el-tag>
  44 + <el-tag size="medium" type="info" v-if="!scope.row.status">离线</el-tag>
  45 + </div>
  46 + </template>
  47 + </el-table-column>
  48 + <el-table-column label="启用" width="120" align="center">
  49 + <template slot-scope="scope">
  50 + <div slot="reference" class="name-wrapper">
  51 + <el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>
  52 + <el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
  53 + </div>
  54 + </template>
  55 + </el-table-column>
  56 + <el-table-column prop="createTime" label="创建时间" align="center" width="150" show-overflow-tooltip/>
  57 + <el-table-column label="转HLS" width="120" align="center">
  58 + <template slot-scope="scope">
  59 + <div slot="reference" class="name-wrapper">
  60 + <el-tag size="medium" v-if="scope.row.enable_hls">已启用</el-tag>
  61 + <el-tag size="medium" type="info" v-if="!scope.row.enable_hls">未启用</el-tag>
  62 + </div>
  63 + </template>
  64 + </el-table-column>
  65 + <el-table-column label="MP4录制" width="120" align="center">
  66 + <template slot-scope="scope">
  67 + <div slot="reference" class="name-wrapper">
  68 + <el-tag size="medium" v-if="scope.row.enable_mp4">已启用</el-tag>
  69 + <el-tag size="medium" type="info" v-if="!scope.row.enable_mp4">未启用</el-tag>
  70 + </div>
  71 + </template>
  72 + </el-table-column>
  73 + <el-table-column label="无人观看自动删除" width="160" align="center">
  74 + <template slot-scope="scope">
  75 + <div slot="reference" class="name-wrapper">
  76 + <el-tag size="medium" v-if="scope.row.enable_remove_none_reader">已启用</el-tag>
  77 + <el-tag size="medium" type="info" v-if="!scope.row.enable_remove_none_reader">未启用</el-tag>
  78 + </div>
  79 + </template>
  80 + </el-table-column>
86 81
87 82
88 - <el-table-column label="操作" width="360" align="center" fixed="right">  
89 - <template slot-scope="scope">  
90 - <el-button-group>  
91 - <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.enable" @click="play(scope.row)">播放</el-button>  
92 - <el-button size="mini" icon="el-icon-close" type="success" v-if="scope.row.enable" @click="stop(scope.row)">停用</el-button>  
93 - <el-button size="mini" icon="el-icon-check" type="primary" :loading="startBtnLaoding" v-if="!scope.row.enable" @click="start(scope.row)">启用</el-button>  
94 - <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteStreamProxy(scope.row)">删除</el-button>  
95 - </el-button-group>  
96 - </template>  
97 - </el-table-column>  
98 - </el-table>  
99 - <el-pagination  
100 - style="float: right"  
101 - @size-change="handleSizeChange"  
102 - @current-change="currentChange"  
103 - :current-page="currentPage"  
104 - :page-size="count"  
105 - :page-sizes="[15, 25, 35, 50]"  
106 - layout="total, sizes, prev, pager, next"  
107 - :total="total">  
108 - </el-pagination>  
109 - <streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit>  
110 - <onvifEdit ref="onvifEdit" ></onvifEdit>  
111 - </el-main>  
112 - </el-container> 83 + <el-table-column label="操作" width="360" align="center" fixed="right">
  84 + <template slot-scope="scope">
  85 + <el-button-group>
  86 + <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.enable" @click="play(scope.row)">播放</el-button>
  87 + <el-button size="mini" icon="el-icon-close" type="success" v-if="scope.row.enable" @click="stop(scope.row)">停用</el-button>
  88 + <el-button size="mini" icon="el-icon-check" type="primary" :loading="startBtnLaoding" v-if="!scope.row.enable" @click="start(scope.row)">启用</el-button>
  89 + <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteStreamProxy(scope.row)">删除</el-button>
  90 + </el-button-group>
  91 + </template>
  92 + </el-table-column>
  93 + </el-table>
  94 + <el-pagination
  95 + style="float: right"
  96 + @size-change="handleSizeChange"
  97 + @current-change="currentChange"
  98 + :current-page="currentPage"
  99 + :page-size="count"
  100 + :page-sizes="[15, 25, 35, 50]"
  101 + layout="total, sizes, prev, pager, next"
  102 + :total="total">
  103 + </el-pagination>
  104 + <streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit>
  105 + <onvifEdit ref="onvifEdit" ></onvifEdit>
113 </div> 106 </div>
114 </template> 107 </template>
115 108
@@ -117,7 +110,7 @@ @@ -117,7 +110,7 @@
117 import streamProxyEdit from './dialog/StreamProxyEdit.vue' 110 import streamProxyEdit from './dialog/StreamProxyEdit.vue'
118 import onvifEdit from './dialog/onvifEdit.vue' 111 import onvifEdit from './dialog/onvifEdit.vue'
119 import devicePlayer from './dialog/devicePlayer.vue' 112 import devicePlayer from './dialog/devicePlayer.vue'
120 - import uiHeader from './UiHeader.vue' 113 + import uiHeader from '../layout/UiHeader.vue'
121 export default { 114 export default {
122 name: 'streamProxyList', 115 name: 'streamProxyList',
123 components: { 116 components: {
web_src/src/components/channelList.vue
1 <template> 1 <template>
2 -<div id="channelList">  
3 - <el-container>  
4 - <el-header>  
5 - <uiHeader></uiHeader>  
6 - </el-header>  
7 - <el-main>  
8 - <div style="background-color: #FFFFFF; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center;">  
9 - <span style="font-size: 1rem; font-weight: 500; ">通道列表({{parentChannelId ==0 ? deviceId:parentChannelId}})</span> 2 + <div id="channelList">
  3 + <div style="background-color: #FFFFFF; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center;">
  4 + <span
  5 + style="font-size: 1rem; font-weight: 500; ">通道列表({{ parentChannelId == 0 ? deviceId : parentChannelId }})</span>
10 6
11 - </div>  
12 - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">  
13 - <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem;" type="primary" @click="showDevice">返回</el-button>  
14 - 搜索: <el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字" prefix-icon="el-icon-search" v-model="searchSrt" clearable> </el-input> 7 + </div>
  8 + <div
  9 + style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">
  10 + <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem;" type="primary" @click="showDevice">
  11 + 返回
  12 + </el-button>
  13 + 搜索:
  14 + <el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
  15 + prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
15 16
16 - 通道类型: <el-select size="mini" @change="search" style="margin-right: 1rem;" v-model="channelType" placeholder="请选择" default-first-option>  
17 - <el-option label="全部" value=""></el-option>  
18 - <el-option label="设备" value="false"></el-option>  
19 - <el-option label="子目录" value="true"></el-option>  
20 - </el-select>  
21 - 在线状态: <el-select size="mini" style="margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择" default-first-option>  
22 - <el-option label="全部" value=""></el-option>  
23 - <el-option label="在线" value="true"></el-option>  
24 - <el-option label="离线" value="false"></el-option>  
25 - </el-select>  
26 - <el-checkbox size="mini" style="margin-right: 1rem; float: right;" v-model="autoList" @change="autoListChange">自动刷新</el-checkbox>  
27 - </div>  
28 - <devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer>  
29 - <!--设备列表-->  
30 - <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" border style="width: 100%">  
31 - <el-table-column prop="channelId" label="通道编号" width="200">  
32 - </el-table-column>  
33 - <el-table-column prop="name" label="通道名称">  
34 - </el-table-column>  
35 - <el-table-column label="快照" width="80" align="center">  
36 - <template slot-scope="scope">  
37 - <img style="max-height: 3rem;max-width: 4rem;"  
38 - :id="scope.row.deviceId + '_' + scope.row.channelId"  
39 - :src="getSnap(scope.row)"  
40 - @error="getSnapErrorEvent($event.target.id)"  
41 - alt="">  
42 -<!-- <el-image-->  
43 -<!-- :id="'snapImg_' + scope.row.deviceId + '_' + scope.row.channelId"-->  
44 -<!-- :src="getSnap(scope.row)"-->  
45 -<!-- @error="getSnapErrorEvent($event, scope.row)"-->  
46 -<!-- :fit="'contain'">-->  
47 -<!-- <div slot="error" class="image-slot">-->  
48 -<!-- <i class="el-icon-picture-outline"></i>-->  
49 -<!-- </div>-->  
50 -<!-- </el-image>-->  
51 - </template>  
52 - </el-table-column>  
53 - <el-table-column prop="subCount" label="子节点数">  
54 - </el-table-column>  
55 - <el-table-column prop="manufacture" label="厂家">  
56 - </el-table-column>  
57 - <el-table-column label="位置信息" align="center">  
58 - <template slot-scope="scope">  
59 - <span>{{scope.row.longitude}},{{scope.row.latitude}}</span>  
60 - </template>  
61 - </el-table-column>  
62 - <el-table-column prop="ptztypeText" label="云台类型"/>  
63 - <el-table-column label="开启音频" align="center">  
64 - <template slot-scope="scope">  
65 - <el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">  
66 - </el-switch>  
67 - </template>  
68 - </el-table-column>  
69 - <el-table-column label="状态" width="180" align="center">  
70 - <template slot-scope="scope">  
71 - <div slot="reference" class="name-wrapper">  
72 - <el-tag size="medium" v-if="scope.row.status == 1">开启</el-tag>  
73 - <el-tag size="medium" type="info" v-if="scope.row.status == 0">关闭</el-tag>  
74 - </div>  
75 - </template>  
76 - </el-table-column> 17 + 通道类型:
  18 + <el-select size="mini" @change="search" style="margin-right: 1rem;" v-model="channelType" placeholder="请选择"
  19 + default-first-option>
  20 + <el-option label="全部" value=""></el-option>
  21 + <el-option label="设备" value="false"></el-option>
  22 + <el-option label="子目录" value="true"></el-option>
  23 + </el-select>
  24 + 在线状态:
  25 + <el-select size="mini" style="margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
  26 + default-first-option>
  27 + <el-option label="全部" value=""></el-option>
  28 + <el-option label="在线" value="true"></el-option>
  29 + <el-option label="离线" value="false"></el-option>
  30 + </el-select>
  31 + <el-checkbox size="mini" style="margin-right: 1rem; float: right;" v-model="autoList" @change="autoListChange">
  32 + 自动刷新
  33 + </el-checkbox>
  34 + </div>
  35 + <devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer>
  36 + <!--设备列表-->
  37 + <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" border style="width: 100%">
  38 + <el-table-column prop="channelId" label="通道编号" width="200">
  39 + </el-table-column>
  40 + <el-table-column prop="name" label="通道名称">
  41 + </el-table-column>
  42 + <el-table-column label="快照" width="80" align="center">
  43 + <template slot-scope="scope">
  44 + <img style="max-height: 3rem;max-width: 4rem;"
  45 + :id="scope.row.deviceId + '_' + scope.row.channelId"
  46 + :src="getSnap(scope.row)"
  47 + @error="getSnapErrorEvent($event.target.id)"
  48 + alt="">
  49 + <!-- <el-image-->
  50 + <!-- :id="'snapImg_' + scope.row.deviceId + '_' + scope.row.channelId"-->
  51 + <!-- :src="getSnap(scope.row)"-->
  52 + <!-- @error="getSnapErrorEvent($event, scope.row)"-->
  53 + <!-- :fit="'contain'">-->
  54 + <!-- <div slot="error" class="image-slot">-->
  55 + <!-- <i class="el-icon-picture-outline"></i>-->
  56 + <!-- </div>-->
  57 + <!-- </el-image>-->
  58 + </template>
  59 + </el-table-column>
  60 + <el-table-column prop="subCount" label="子节点数">
  61 + </el-table-column>
  62 + <el-table-column prop="manufacture" label="厂家">
  63 + </el-table-column>
  64 + <el-table-column label="位置信息" align="center">
  65 + <template slot-scope="scope">
  66 + <span>{{ scope.row.longitude }},{{ scope.row.latitude }}</span>
  67 + </template>
  68 + </el-table-column>
  69 + <el-table-column prop="ptztypeText" label="云台类型"/>
  70 + <el-table-column label="开启音频" align="center">
  71 + <template slot-scope="scope">
  72 + <el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">
  73 + </el-switch>
  74 + </template>
  75 + </el-table-column>
  76 + <el-table-column label="状态" width="180" align="center">
  77 + <template slot-scope="scope">
  78 + <div slot="reference" class="name-wrapper">
  79 + <el-tag size="medium" v-if="scope.row.status == 1">开启</el-tag>
  80 + <el-tag size="medium" type="info" v-if="scope.row.status == 0">关闭</el-tag>
  81 + </div>
  82 + </template>
  83 + </el-table-column>
77 84
78 85
79 - <el-table-column label="操作" width="280" align="center" fixed="right">  
80 - <template slot-scope="scope">  
81 - <el-button-group>  
82 - <!-- <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">播放</el-button> -->  
83 - <el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">播放</el-button>  
84 - <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" @click="stopDevicePush(scope.row)">停止</el-button>  
85 - <el-button size="mini" icon="el-icon-s-open" type="primary" v-if="scope.row.subCount > 0" @click="changeSubchannel(scope.row)">查看</el-button>  
86 - <el-button size="mini" icon="el-icon-video-camera" type="primary" @click="queryRecords(scope.row)">设备录象</el-button>  
87 - <!-- <el-button size="mini" @click="sendDevicePush(scope.row)">录像查询</el-button> -->  
88 - </el-button-group>  
89 - </template>  
90 - </el-table-column>  
91 - </el-table>  
92 - <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">  
93 - </el-pagination>  
94 -  
95 - </el-main>  
96 - </el-container>  
97 -</div> 86 + <el-table-column label="操作" width="280" align="center" fixed="right">
  87 + <template slot-scope="scope">
  88 + <el-button-group>
  89 + <!-- <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">播放</el-button> -->
  90 + <el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">播放</el-button>
  91 + <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId"
  92 + @click="stopDevicePush(scope.row)">停止
  93 + </el-button>
  94 + <el-button size="mini" icon="el-icon-s-open" type="primary" v-if="scope.row.subCount > 0"
  95 + @click="changeSubchannel(scope.row)">查看
  96 + </el-button>
  97 + <el-button size="mini" icon="el-icon-video-camera" type="primary" @click="queryRecords(scope.row)">设备录象
  98 + </el-button>
  99 + <!-- <el-button size="mini" @click="sendDevicePush(scope.row)">录像查询</el-button> -->
  100 + </el-button-group>
  101 + </template>
  102 + </el-table-column>
  103 + </el-table>
  104 + <el-pagination style="float: right" @size-change="handleSizeChange" @current-change="currentChange"
  105 + :current-page="currentPage" :page-size="count" :page-sizes="[15, 20, 30, 50]"
  106 + layout="total, sizes, prev, pager, next" :total="total">
  107 + </el-pagination>
  108 + </div>
98 </template> 109 </template>
99 110
100 <script> 111 <script>
101 import devicePlayer from './dialog/devicePlayer.vue' 112 import devicePlayer from './dialog/devicePlayer.vue'
102 -import uiHeader from './UiHeader.vue' 113 +import uiHeader from '../layout/UiHeader.vue'
103 import moment from "moment"; 114 import moment from "moment";
  115 +
104 export default { 116 export default {
105 - name: 'channelList',  
106 - components: {  
107 - devicePlayer,  
108 - uiHeader  
109 - },  
110 - data() {  
111 - return {  
112 - deviceId: this.$route.params.deviceId,  
113 - parentChannelId: this.$route.params.parentChannelId,  
114 - deviceChannelList: [],  
115 - videoComponentList: [],  
116 - currentPlayerInfo: {}, //当前播放对象  
117 - updateLooper: 0, //数据刷新轮训标志  
118 - searchSrt: "",  
119 - channelType: "",  
120 - online: "",  
121 - winHeight: window.innerHeight - 250,  
122 - currentPage: parseInt(this.$route.params.page),  
123 - count: parseInt(this.$route.params.count),  
124 - total: 0,  
125 - beforeUrl: "/deviceList",  
126 - isLoging: false,  
127 - autoList: true,  
128 - loadSnap:{}  
129 - }; 117 + name: 'channelList',
  118 + components: {
  119 + devicePlayer,
  120 + uiHeader
  121 + },
  122 + data() {
  123 + return {
  124 + deviceId: this.$route.params.deviceId,
  125 + parentChannelId: this.$route.params.parentChannelId,
  126 + deviceChannelList: [],
  127 + videoComponentList: [],
  128 + currentPlayerInfo: {}, //当前播放对象
  129 + updateLooper: 0, //数据刷新轮训标志
  130 + searchSrt: "",
  131 + channelType: "",
  132 + online: "",
  133 + winHeight: window.innerHeight - 250,
  134 + currentPage: parseInt(this.$route.params.page),
  135 + count: parseInt(this.$route.params.count),
  136 + total: 0,
  137 + beforeUrl: "/deviceList",
  138 + isLoging: false,
  139 + autoList: true,
  140 + loadSnap: {}
  141 + };
  142 + },
  143 +
  144 + mounted() {
  145 + this.initData();
  146 + if (this.autoList) {
  147 + this.updateLooper = setInterval(this.initData, 5000);
  148 + }
  149 +
  150 + },
  151 + destroyed() {
  152 + this.$destroy('videojs');
  153 + clearTimeout(this.updateLooper);
  154 + },
  155 + methods: {
  156 + initData: function () {
  157 + if (typeof (this.parentChannelId) == "undefined" || this.parentChannelId == 0) {
  158 + this.getDeviceChannelList();
  159 + } else {
  160 + this.showSubchannels();
  161 + }
130 }, 162 },
  163 + initParam: function () {
  164 + this.deviceId = this.$route.params.deviceId;
  165 + this.parentChannelId = this.$route.params.parentChannelId;
  166 + this.currentPage = parseInt(this.$route.params.page);
  167 + this.count = parseInt(this.$route.params.count);
  168 + if (this.parentChannelId == "" || this.parentChannelId == 0) {
  169 + this.beforeUrl = "/deviceList"
  170 + }
131 171
132 - mounted() { 172 + },
  173 + currentChange: function (val) {
  174 + var url = `/${this.$router.currentRoute.name}/${this.deviceId}/${this.parentChannelId}/${this.count}/${val}`
  175 + this.$router.push(url).then(() => {
  176 + this.initParam();
133 this.initData(); 177 this.initData();
134 - if (this.autoList) {  
135 - this.updateLooper = setInterval(this.initData, 5000);  
136 - } 178 + })
  179 + },
  180 + handleSizeChange: function (val) {
  181 + var url = `/${this.$router.currentRoute.name}/${this.$router.params.deviceId}/${this.$router.params.parentChannelId}/${val}/1`
  182 + this.$router.push(url).then(() => {
  183 + this.initParam();
  184 + this.initData();
  185 + })
137 186
138 }, 187 },
139 - destroyed() {  
140 - this.$destroy('videojs');  
141 - clearTimeout(this.updateLooper); 188 + getDeviceChannelList: function () {
  189 + let that = this;
  190 + if (typeof (this.$route.params.deviceId) == "undefined") return;
  191 + this.$axios({
  192 + method: 'get',
  193 + url: `/api/device/query/devices/${this.$route.params.deviceId}/channels`,
  194 + params: {
  195 + page: that.currentPage,
  196 + count: that.count,
  197 + query: that.searchSrt,
  198 + online: that.online,
  199 + channelType: that.channelType
  200 + }
  201 + }).then(function (res) {
  202 + that.total = res.data.total;
  203 + that.deviceChannelList = res.data.list;
  204 + // 防止出现表格错位
  205 + that.$nextTick(() => {
  206 + that.$refs.channelListTable.doLayout();
  207 + })
  208 + }).catch(function (error) {
  209 + console.log(error);
  210 + });
142 }, 211 },
143 - methods: {  
144 - initData: function () {  
145 - if (typeof (this.parentChannelId) == "undefined" || this.parentChannelId == 0) {  
146 - this.getDeviceChannelList();  
147 - } else {  
148 - this.showSubchannels();  
149 - }  
150 - },  
151 - initParam: function () {  
152 - this.deviceId = this.$route.params.deviceId;  
153 - this.parentChannelId = this.$route.params.parentChannelId;  
154 - this.currentPage = parseInt(this.$route.params.page);  
155 - this.count = parseInt(this.$route.params.count);  
156 - if (this.parentChannelId == "" || this.parentChannelId == 0) {  
157 - this.beforeUrl = "/deviceList"  
158 - }  
159 -  
160 - },  
161 - currentChange: function (val) {  
162 - var url = `/${this.$router.currentRoute.name}/${this.deviceId}/${this.parentChannelId}/${this.count}/${val}`  
163 - this.$router.push(url).then(() => {  
164 - this.initParam();  
165 - this.initData();  
166 - })  
167 - },  
168 - handleSizeChange: function (val) {  
169 - var url = `/${this.$router.currentRoute.name}/${this.$router.params.deviceId}/${this.$router.params.parentChannelId}/${val}/1`  
170 - this.$router.push(url).then(() => {  
171 - this.initParam();  
172 - this.initData();  
173 - })  
174 212
175 - },  
176 - getDeviceChannelList: function () {  
177 - let that = this;  
178 - if (typeof (this.$route.params.deviceId) == "undefined") return;  
179 - this.$axios({  
180 - method: 'get',  
181 - url: `/api/device/query/devices/${this.$route.params.deviceId}/channels`,  
182 - params:{  
183 - page: that.currentPage,  
184 - count: that.count,  
185 - query: that.searchSrt,  
186 - online: that.online,  
187 - channelType: that.channelType  
188 - }  
189 - }).then(function (res) {  
190 - that.total = res.data.total;  
191 - that.deviceChannelList = res.data.list;  
192 - // 防止出现表格错位  
193 - that.$nextTick(() => {  
194 - that.$refs.channelListTable.doLayout();  
195 - })  
196 - }).catch(function (error) {  
197 - console.log(error);  
198 - });  
199 - }, 213 + //通知设备上传媒体流
  214 + sendDevicePush: function (itemData) {
  215 + let deviceId = this.deviceId;
  216 + this.isLoging = true;
  217 + let channelId = itemData.channelId;
  218 + console.log("通知设备推流1:" + deviceId + " : " + channelId);
  219 + let that = this;
  220 + this.$axios({
  221 + method: 'get',
  222 + url: '/api/play/start/' + deviceId + '/' + channelId
  223 + }).then(function (res) {
  224 + that.isLoging = false;
  225 + if (res.data.code === 0) {
200 226
201 - //通知设备上传媒体流  
202 - sendDevicePush: function (itemData) {  
203 - let deviceId = this.deviceId;  
204 - this.isLoging = true;  
205 - let channelId = itemData.channelId;  
206 - console.log("通知设备推流1:" + deviceId + " : " + channelId );  
207 - let that = this;  
208 - this.$axios({  
209 - method: 'get',  
210 - url: '/api/play/start/' + deviceId + '/' + channelId  
211 - }).then(function (res) {  
212 - that.isLoging = false;  
213 - if (res.data.code === 0) { 227 + setTimeout(() => {
214 228
215 - setTimeout(()=>{ 229 + let snapId = deviceId + "_" + channelId;
  230 + that.loadSnap[snapId] = 0;
  231 + that.getSnapErrorEvent(snapId)
  232 + }, 5000)
  233 + that.$refs.devicePlayer.openDialog("media", deviceId, channelId, {
  234 + streamInfo: res.data.data,
  235 + hasAudio: itemData.hasAudio
  236 + });
  237 + setTimeout(() => {
  238 + that.initData();
  239 + }, 1000)
216 240
217 - let snapId = deviceId + "_" + channelId;  
218 - that.loadSnap[snapId] = 0;  
219 - that.getSnapErrorEvent(snapId)  
220 - },5000)  
221 - that.$refs.devicePlayer.openDialog("media", deviceId, channelId, {  
222 - streamInfo: res.data.data,  
223 - hasAudio: itemData.hasAudio  
224 - });  
225 - setTimeout(()=>{  
226 - that.initData();  
227 - },1000)  
228 -  
229 - }else {  
230 - that.$message.error(res.data.msg);  
231 - }  
232 - }).catch(function (e) {});  
233 - },  
234 - queryRecords: function (itemData) {  
235 - var format = moment().format("YYYY-M-D");  
236 - let deviceId = this.deviceId;  
237 - let channelId = itemData.channelId;  
238 - this.$refs.devicePlayer.openDialog("record", deviceId, channelId, {date: format})  
239 - },  
240 - stopDevicePush: function (itemData) {  
241 - var that = this;  
242 - this.$axios({  
243 - method: 'get',  
244 - url: '/api/play/stop/' + this.deviceId + "/" + itemData.channelId  
245 - }).then(function (res) {  
246 - that.initData();  
247 - }).catch(function (error) {  
248 - if (error.response.status === 402) { // 已经停止过  
249 - that.initData();  
250 - }else {  
251 - console.log(error)  
252 - }  
253 - });  
254 - },  
255 - getSnap: function (row){  
256 - return '/static/snap/' + row.deviceId + '_' + row.channelId + '.jpg'  
257 - },  
258 - getSnapErrorEvent: function (id){ 241 + } else {
  242 + that.$message.error(res.data.msg);
  243 + }
  244 + }).catch(function (e) {
  245 + });
  246 + },
  247 + queryRecords: function (itemData) {
  248 + var format = moment().format("YYYY-M-D");
  249 + let deviceId = this.deviceId;
  250 + let channelId = itemData.channelId;
  251 + this.$refs.devicePlayer.openDialog("record", deviceId, channelId, {date: format})
  252 + },
  253 + stopDevicePush: function (itemData) {
  254 + var that = this;
  255 + this.$axios({
  256 + method: 'get',
  257 + url: '/api/play/stop/' + this.deviceId + "/" + itemData.channelId
  258 + }).then(function (res) {
  259 + that.initData();
  260 + }).catch(function (error) {
  261 + if (error.response.status === 402) { // 已经停止过
  262 + that.initData();
  263 + } else {
  264 + console.log(error)
  265 + }
  266 + });
  267 + },
  268 + getSnap: function (row) {
  269 + return '/static/snap/' + row.deviceId + '_' + row.channelId + '.jpg'
  270 + },
  271 + getSnapErrorEvent: function (id) {
259 272
260 - if (typeof (this.loadSnap[id]) != "undefined") {  
261 - console.log("下载截图" + this.loadSnap[id])  
262 - if (this.loadSnap[id] > 5) {  
263 - delete this.loadSnap[id];  
264 - return;  
265 - }  
266 - setTimeout(()=>{  
267 - this.loadSnap[id] ++  
268 - document.getElementById(id).setAttribute("src", '/static/snap/' + id + '.jpg?' + new Date().getTime())  
269 - },1000) 273 + if (typeof (this.loadSnap[id]) != "undefined") {
  274 + console.log("下载截图" + this.loadSnap[id])
  275 + if (this.loadSnap[id] > 5) {
  276 + delete this.loadSnap[id];
  277 + return;
  278 + }
  279 + setTimeout(() => {
  280 + this.loadSnap[id]++
  281 + document.getElementById(id).setAttribute("src", '/static/snap/' + id + '.jpg?' + new Date().getTime())
  282 + }, 1000)
270 283
271 - }  
272 - },  
273 - showDevice: function () {  
274 - this.$router.push(this.beforeUrl).then(() => {  
275 - this.initParam();  
276 - this.initData();  
277 - })  
278 - },  
279 - changeSubchannel(itemData) {  
280 - this.beforeUrl = this.$router.currentRoute.path; 284 + }
  285 + },
  286 + showDevice: function () {
  287 + this.$router.push(this.beforeUrl).then(() => {
  288 + this.initParam();
  289 + this.initData();
  290 + })
  291 + },
  292 + changeSubchannel(itemData) {
  293 + this.beforeUrl = this.$router.currentRoute.path;
281 294
282 - var url = `/${this.$router.currentRoute.name}/${this.$router.currentRoute.params.deviceId}/${itemData.channelId}/${this.$router.currentRoute.params.count}/1`  
283 - this.$router.push(url).then(() => {  
284 - this.searchSrt = "";  
285 - this.channelType = "";  
286 - this.online = "";  
287 - this.initParam();  
288 - this.initData();  
289 - })  
290 - },  
291 - showSubchannels: function (channelId) {  
292 - let that = this; 295 + var url = `/${this.$router.currentRoute.name}/${this.$router.currentRoute.params.deviceId}/${itemData.channelId}/${this.$router.currentRoute.params.count}/1`
  296 + this.$router.push(url).then(() => {
  297 + this.searchSrt = "";
  298 + this.channelType = "";
  299 + this.online = "";
  300 + this.initParam();
  301 + this.initData();
  302 + })
  303 + },
  304 + showSubchannels: function (channelId) {
  305 + let that = this;
293 306
294 - this.$axios({  
295 - method: 'get',  
296 - url:`/api/device/query/sub_channels/${this.deviceId}/${this.parentChannelId}/channels`,  
297 - params: {  
298 - page: that.currentPage,  
299 - count: that.count,  
300 - query: that.searchSrt,  
301 - online: that.online,  
302 - channelType: that.channelType  
303 - }  
304 - }).then(function (res) {  
305 - that.total = res.data.total;  
306 - that.deviceChannelList = res.data.list;  
307 - // 防止出现表格错位  
308 - that.$nextTick(() => {  
309 - that.$refs.channelListTable.doLayout();  
310 - })  
311 - }).catch(function (error) {  
312 - console.log(error);  
313 - });  
314 - },  
315 - search: function () {  
316 - this.currentPage = 1;  
317 - this.total = 0;  
318 - this.initData();  
319 - },  
320 - updateChannel: function (row) {  
321 - this.$axios({  
322 - method: 'post',  
323 - url: `/api/device/query/channel/update/${this.deviceId}`,  
324 - params: row  
325 - }).then(function (res) {  
326 - console.log(JSON.stringify(res));  
327 - });  
328 - },  
329 - autoListChange: function () {  
330 - if (this.autoList) {  
331 - this.updateLooper = setInterval(this.initData, 1500);  
332 - }else{  
333 - window.clearInterval(this.updateLooper);  
334 - } 307 + this.$axios({
  308 + method: 'get',
  309 + url: `/api/device/query/sub_channels/${this.deviceId}/${this.parentChannelId}/channels`,
  310 + params: {
  311 + page: that.currentPage,
  312 + count: that.count,
  313 + query: that.searchSrt,
  314 + online: that.online,
  315 + channelType: that.channelType
335 } 316 }
336 - 317 + }).then(function (res) {
  318 + that.total = res.data.total;
  319 + that.deviceChannelList = res.data.list;
  320 + // 防止出现表格错位
  321 + that.$nextTick(() => {
  322 + that.$refs.channelListTable.doLayout();
  323 + })
  324 + }).catch(function (error) {
  325 + console.log(error);
  326 + });
  327 + },
  328 + search: function () {
  329 + this.currentPage = 1;
  330 + this.total = 0;
  331 + this.initData();
  332 + },
  333 + updateChannel: function (row) {
  334 + this.$axios({
  335 + method: 'post',
  336 + url: `/api/device/query/channel/update/${this.deviceId}`,
  337 + params: row
  338 + }).then(function (res) {
  339 + console.log(JSON.stringify(res));
  340 + });
  341 + },
  342 + autoListChange: function () {
  343 + if (this.autoList) {
  344 + this.updateLooper = setInterval(this.initData, 1500);
  345 + } else {
  346 + window.clearInterval(this.updateLooper);
  347 + }
337 } 348 }
  349 +
  350 + }
338 }; 351 };
339 </script> 352 </script>
340 353
341 <style> 354 <style>
342 .videoList { 355 .videoList {
343 - display: flex;  
344 - flex-wrap: wrap;  
345 - align-content: flex-start; 356 + display: flex;
  357 + flex-wrap: wrap;
  358 + align-content: flex-start;
346 } 359 }
347 360
348 .video-item { 361 .video-item {
349 - position: relative;  
350 - width: 15rem;  
351 - height: 10rem;  
352 - margin-right: 1rem;  
353 - background-color: #000000; 362 + position: relative;
  363 + width: 15rem;
  364 + height: 10rem;
  365 + margin-right: 1rem;
  366 + background-color: #000000;
354 } 367 }
355 368
356 .video-item-img { 369 .video-item-img {
357 - position: absolute;  
358 - top: 0;  
359 - bottom: 0;  
360 - left: 0;  
361 - right: 0;  
362 - margin: auto;  
363 - width: 100%;  
364 - height: 100%; 370 + position: absolute;
  371 + top: 0;
  372 + bottom: 0;
  373 + left: 0;
  374 + right: 0;
  375 + margin: auto;
  376 + width: 100%;
  377 + height: 100%;
365 } 378 }
366 379
367 .video-item-img:after { 380 .video-item-img:after {
368 - content: "";  
369 - display: inline-block;  
370 - position: absolute;  
371 - z-index: 2;  
372 - top: 0;  
373 - bottom: 0;  
374 - left: 0;  
375 - right: 0;  
376 - margin: auto;  
377 - width: 3rem;  
378 - height: 3rem;  
379 - background-image: url("../assets/loading.png");  
380 - background-size: cover;  
381 - background-color: #000000; 381 + content: "";
  382 + display: inline-block;
  383 + position: absolute;
  384 + z-index: 2;
  385 + top: 0;
  386 + bottom: 0;
  387 + left: 0;
  388 + right: 0;
  389 + margin: auto;
  390 + width: 3rem;
  391 + height: 3rem;
  392 + background-image: url("../assets/loading.png");
  393 + background-size: cover;
  394 + background-color: #000000;
382 } 395 }
383 396
384 .video-item-title { 397 .video-item-title {
385 - position: absolute;  
386 - bottom: 0;  
387 - color: #000000;  
388 - background-color: #ffffff;  
389 - line-height: 1.5rem;  
390 - padding: 0.3rem;  
391 - width: 14.4rem; 398 + position: absolute;
  399 + bottom: 0;
  400 + color: #000000;
  401 + background-color: #ffffff;
  402 + line-height: 1.5rem;
  403 + padding: 0.3rem;
  404 + width: 14.4rem;
392 } 405 }
393 </style> 406 </style>
web_src/src/components/control.vue
1 <template> 1 <template>
2 -<div id="app">  
3 - <el-container>  
4 - <el-header>  
5 - <uiHeader></uiHeader>  
6 - </el-header>  
7 - <el-main>  
8 - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">  
9 - <span style="font-size: 1rem; font-weight: bold;">控制台</span>  
10 - <div style="position: absolute; right: 17rem; top: 0.3rem;">  
11 - 节点选择: <el-select size="mini" @change="chooseMediaChange" style="width: 18rem; margin-right: 8rem;" v-model="mediaServerChoose" placeholder="请选择" default-first-option>  
12 - <el-option  
13 - v-for="item in mediaServerList"  
14 - :key="item.id"  
15 - :label="item.id + '( ' + item.streamIp + ' )'"  
16 - :value="item.id">  
17 - </el-option>  
18 - </el-select>  
19 - <span >{{loadCount}}</span>  
20 - </div>  
21 - <div style="position: absolute; right: 1rem; top: 0.3rem;">  
22 - <el-popover placement="bottom" width="900" height="300" trigger="click">  
23 - <div style="height: 600px; overflow:auto; padding: 20px">  
24 - <el-descriptions v-for="(value, key, index) in serverConfig" :key="key" border :column="1" style="margin-bottom: 1rem">  
25 - <template slot="title">  
26 - {{key}}  
27 - </template>  
28 - <el-descriptions-item v-for="(value1, key1, index1) in serverConfig[key]" :key="key1">  
29 - <template slot="label" >  
30 - {{ getMediaKeyNameFromKey(key1) }}  
31 - </template>  
32 - {{ value1 }}  
33 - </el-descriptions-item>  
34 - </el-descriptions>  
35 - </div>  
36 - <el-button type="primary" slot="reference" size="mini" @click="getServerConfig()">媒体服务器配置</el-button>  
37 - </el-popover>  
38 - <el-popover placement="bottom" width="900" height="300" trigger="click">  
39 - <div style="height: 600px;overflow:auto; padding: 20px">  
40 - <el-descriptions title="国标配置" border :column="1">  
41 - <template slot="extra">  
42 - <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>  
43 - </template>  
44 - <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.sip" :key="key">  
45 - <template slot="label">  
46 - {{ getNameFromKey(key) }}  
47 - </template>  
48 - {{ value }}  
49 - </el-descriptions-item>  
50 - </el-descriptions> 2 + <div id="app" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">控制台</div>
  5 + <div class="page-header-btn">
  6 + 节点选择:
  7 + <el-select size="mini" @change="chooseMediaChange" style="width: 18rem; margin-right: 8rem;"
  8 + v-model="mediaServerChoose" placeholder="请选择" default-first-option>
  9 + <el-option
  10 + v-for="item in mediaServerList"
  11 + :key="item.id"
  12 + :label="item.id + '( ' + item.streamIp + ' )'"
  13 + :value="item.id">
  14 + </el-option>
  15 + </el-select>
  16 + <span>{{ loadCount }}</span>
  17 + </div>
  18 + <div class="page-header-btn">
  19 + <el-popover placement="bottom" width="900" height="300" trigger="click">
  20 + <div style="height: 600px; overflow:auto; padding: 20px">
  21 + <el-descriptions v-for="(value, key, index) in serverConfig" :key="key" border :column="1"
  22 + style="margin-bottom: 1rem">
  23 + <template slot="title">
  24 + {{ key }}
  25 + </template>
  26 + <el-descriptions-item v-for="(value1, key1, index1) in serverConfig[key]" :key="key1">
  27 + <template slot="label">
  28 + {{ getMediaKeyNameFromKey(key1) }}
  29 + </template>
  30 + {{ value1 }}
  31 + </el-descriptions-item>
  32 + </el-descriptions>
  33 + </div>
  34 + <el-button type="primary" slot="reference" size="mini" @click="getServerConfig()">媒体服务器配置</el-button>
  35 + </el-popover>
  36 + <el-popover placement="bottom" width="900" height="300" trigger="click">
  37 + <div style="height: 600px;overflow:auto; padding: 20px">
  38 + <el-descriptions title="国标配置" border :column="1">
  39 + <template slot="extra">
  40 + <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝"
  41 + v-clipboard="JSON.stringify(wvpServerConfig.sip)|| ''"
  42 + @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
  43 + </template>
  44 + <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.sip" :key="key">
  45 + <template slot="label">
  46 + {{ getNameFromKey(key) }}
  47 + </template>
  48 + {{ value }}
  49 + </el-descriptions-item>
  50 + </el-descriptions>
51 51
52 - <div style="margin-top: 1rem">  
53 - <el-descriptions title="基础配置" border :column="1">  
54 - <template slot="extra">  
55 - <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>  
56 - </template>  
57 - <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.base" :key="key">  
58 - <template slot="label" >  
59 - {{ getNameFromKey(key) }}  
60 - </template>  
61 - <div v-if="key === 'interfaceAuthenticationExcludes'">  
62 - <el-dropdown> 52 + <div style="margin-top: 1rem">
  53 + <el-descriptions title="基础配置" border :column="1">
  54 + <template slot="extra">
  55 + <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝"
  56 + v-clipboard="JSON.stringify(wvpServerConfig.base)|| ''"
  57 + @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
  58 + </template>
  59 + <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.base" :key="key">
  60 + <template slot="label">
  61 + {{ getNameFromKey(key) }}
  62 + </template>
  63 + <div v-if="key === 'interfaceAuthenticationExcludes'">
  64 + <el-dropdown>
63 <span class="el-dropdown-link"> 65 <span class="el-dropdown-link">
64 查看<i class="el-icon-arrow-down el-icon--right"></i> 66 查看<i class="el-icon-arrow-down el-icon--right"></i>
65 </span> 67 </span>
66 - <el-dropdown-menu slot="dropdown">  
67 - <el-dropdown-item v-for="(value, key, index) in wvpServerConfig.base.interfaceAuthenticationExcludes" :key="key">{{value}}</el-dropdown-item>  
68 - </el-dropdown-menu>  
69 - </el-dropdown>  
70 - </div>  
71 - <div v-if="key !== 'interfaceAuthenticationExcludes'">  
72 - <div v-if="value === true">  
73 - 已启用  
74 - </div>  
75 - <div v-if="value === false">  
76 - 未启用  
77 - </div>  
78 - <div v-if="value !== true && value !== false">  
79 - {{ value }}  
80 - </div>  
81 - </div> 68 + <el-dropdown-menu slot="dropdown">
  69 + <el-dropdown-item
  70 + v-for="(value, key, index) in wvpServerConfig.base.interfaceAuthenticationExcludes"
  71 + :key="key">{{ value }}
  72 + </el-dropdown-item>
  73 + </el-dropdown-menu>
  74 + </el-dropdown>
  75 + </div>
  76 + <div v-if="key !== 'interfaceAuthenticationExcludes'">
  77 + <div v-if="value === true">
  78 + 已启用
  79 + </div>
  80 + <div v-if="value === false">
  81 + 未启用
  82 + </div>
  83 + <div v-if="value !== true && value !== false">
  84 + {{ value }}
  85 + </div>
  86 + </div>
82 87
83 - </el-descriptions-item>  
84 - </el-descriptions>  
85 - </div>  
86 - <div style="margin-top: 1rem">  
87 - <el-descriptions title="版本信息" border :column="1">  
88 - <template slot="extra">  
89 - <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>  
90 - </template>  
91 - <el-descriptions-item v-for="(value, key, index) in wvpServerVersion" :key="key">  
92 - <template slot="label">  
93 - {{ getNameFromKey(key) }}  
94 - </template>  
95 - {{ value }}  
96 - </el-descriptions-item>  
97 - </el-descriptions> 88 + </el-descriptions-item>
  89 + </el-descriptions>
  90 + </div>
  91 + <div style="margin-top: 1rem">
  92 + <el-descriptions title="版本信息" border :column="1">
  93 + <template slot="extra">
  94 + <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝"
  95 + v-clipboard="JSON.stringify(wvpServerVersion) || ''"
  96 + @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
  97 + </template>
  98 + <el-descriptions-item v-for="(value, key, index) in wvpServerVersion" :key="key">
  99 + <template slot="label">
  100 + {{ getNameFromKey(key) }}
  101 + </template>
  102 + {{ value }}
  103 + </el-descriptions-item>
  104 + </el-descriptions>
98 105
99 106
100 - </div>  
101 - </div>  
102 - <el-button type="primary" slot="reference" size="mini" @click="getWVPServerConfig()">信令服务器配置</el-button>  
103 - </el-popover>  
104 - <el-button style="margin-left: 1rem;" type="danger" size="mini" @click="reStartServer()">重启媒体服务器</el-button>  
105 - </div>  
106 </div> 107 </div>
107 - <el-row :gutter="30">  
108 - <el-col :span="12">  
109 - <div class="control-table" id="ThreadsLoad">table1</div>  
110 - </el-col>  
111 - <el-col :span="12">  
112 - <div class="control-table" id="WorkThreadsLoad">table2</div>  
113 - </el-col>  
114 - </el-row>  
115 - <el-table :data="allSessionData" style="margin-top: 1rem;">  
116 - <el-table-column prop="peer_ip" label="远端"></el-table-column>  
117 - <el-table-column prop="local_ip" label="本地"></el-table-column>  
118 - <el-table-column prop="typeid" label="类型"></el-table-column>  
119 - <el-table-column align="right">  
120 - <template slot="header" slot-scope="scope">  
121 - <el-button icon="el-icon-refresh-right" circle @click="getAllSession()"></el-button>  
122 - </template>  
123 - <template slot-scope="scope">  
124 - <el-button @click.native.prevent="deleteRow(scope.$index, allSessionData)" type="text" size="small">移除</el-button>  
125 - </template>  
126 - </el-table-column>  
127 - </el-table> 108 + </div>
  109 + <el-button type="primary" slot="reference" size="mini" @click="getWVPServerConfig()">信令服务器配置</el-button>
  110 + </el-popover>
  111 + <el-button style="margin-left: 1rem;" type="danger" size="mini" @click="reStartServer()">重启媒体服务器</el-button>
  112 + </div>
  113 + </div>
  114 + <!-- <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">-->
  115 + <!-- <span style="font-size: 1rem; font-weight: bold;">控制台</span>-->
  116 + <!-- <div style="position: absolute; right: 17rem; top: 0.3rem;">-->
  117 + <!-- 节点选择:-->
  118 + <!-- <el-select size="mini" @change="chooseMediaChange" style="width: 18rem; margin-right: 8rem;"-->
  119 + <!-- v-model="mediaServerChoose" placeholder="请选择" default-first-option>-->
  120 + <!-- <el-option-->
  121 + <!-- v-for="item in mediaServerList"-->
  122 + <!-- :key="item.id"-->
  123 + <!-- :label="item.id + '( ' + item.streamIp + ' )'"-->
  124 + <!-- :value="item.id">-->
  125 + <!-- </el-option>-->
  126 + <!-- </el-select>-->
  127 + <!-- <span>{{ loadCount }}</span>-->
  128 + <!-- </div>-->
  129 + <!-- <div style="position: absolute; right: 1rem; top: 0.3rem;">-->
  130 + <!-- <el-popover placement="bottom" width="900" height="300" trigger="click">-->
  131 + <!-- <div style="height: 600px; overflow:auto; padding: 20px">-->
  132 + <!-- <el-descriptions v-for="(value, key, index) in serverConfig" :key="key" border :column="1"-->
  133 + <!-- style="margin-bottom: 1rem">-->
  134 + <!-- <template slot="title">-->
  135 + <!-- {{ key }}-->
  136 + <!-- </template>-->
  137 + <!-- <el-descriptions-item v-for="(value1, key1, index1) in serverConfig[key]" :key="key1">-->
  138 + <!-- <template slot="label">-->
  139 + <!-- {{ getMediaKeyNameFromKey(key1) }}-->
  140 + <!-- </template>-->
  141 + <!-- {{ value1 }}-->
  142 + <!-- </el-descriptions-item>-->
  143 + <!-- </el-descriptions>-->
  144 + <!-- </div>-->
  145 + <!-- <el-button type="primary" slot="reference" size="mini" @click="getServerConfig()">媒体服务器配置</el-button>-->
  146 + <!-- </el-popover>-->
  147 + <!-- <el-popover placement="bottom" width="900" height="300" trigger="click">-->
  148 + <!-- <div style="height: 600px;overflow:auto; padding: 20px">-->
  149 + <!-- <el-descriptions title="国标配置" border :column="1">-->
  150 + <!-- <template slot="extra">-->
  151 + <!-- <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝"-->
  152 + <!-- v-clipboard="JSON.stringify(wvpServerConfig.sip)|| ''"-->
  153 + <!-- @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>-->
  154 + <!-- </template>-->
  155 + <!-- <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.sip" :key="key">-->
  156 + <!-- <template slot="label">-->
  157 + <!-- {{ getNameFromKey(key) }}-->
  158 + <!-- </template>-->
  159 + <!-- {{ value }}-->
  160 + <!-- </el-descriptions-item>-->
  161 + <!-- </el-descriptions>-->
  162 +
  163 + <!-- <div style="margin-top: 1rem">-->
  164 + <!-- <el-descriptions title="基础配置" border :column="1">-->
  165 + <!-- <template slot="extra">-->
  166 + <!-- <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝"-->
  167 + <!-- v-clipboard="JSON.stringify(wvpServerConfig.base)|| ''"-->
  168 + <!-- @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>-->
  169 + <!-- </template>-->
  170 + <!-- <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.base" :key="key">-->
  171 + <!-- <template slot="label">-->
  172 + <!-- {{ getNameFromKey(key) }}-->
  173 + <!-- </template>-->
  174 + <!-- <div v-if="key === 'interfaceAuthenticationExcludes'">-->
  175 + <!-- <el-dropdown>-->
  176 + <!-- <span class="el-dropdown-link">-->
  177 + <!-- 查看<i class="el-icon-arrow-down el-icon&#45;&#45;right"></i>-->
  178 + <!-- </span>-->
  179 + <!-- <el-dropdown-menu slot="dropdown">-->
  180 + <!-- <el-dropdown-item-->
  181 + <!-- v-for="(value, key, index) in wvpServerConfig.base.interfaceAuthenticationExcludes"-->
  182 + <!-- :key="key">{{ value }}-->
  183 + <!-- </el-dropdown-item>-->
  184 + <!-- </el-dropdown-menu>-->
  185 + <!-- </el-dropdown>-->
  186 + <!-- </div>-->
  187 + <!-- <div v-if="key !== 'interfaceAuthenticationExcludes'">-->
  188 + <!-- <div v-if="value === true">-->
  189 + <!-- 已启用-->
  190 + <!-- </div>-->
  191 + <!-- <div v-if="value === false">-->
  192 + <!-- 未启用-->
  193 + <!-- </div>-->
  194 + <!-- <div v-if="value !== true && value !== false">-->
  195 + <!-- {{ value }}-->
  196 + <!-- </div>-->
  197 + <!-- </div>-->
128 198
129 - </el-main>  
130 - <!-- <el-footer style="position: absolute; bottom: 0; width: 100%;">ZLMediaKit-VUE_UI v1</el-footer> -->  
131 - </el-container> 199 + <!-- </el-descriptions-item>-->
  200 + <!-- </el-descriptions>-->
  201 + <!-- </div>-->
  202 + <!-- <div style="margin-top: 1rem">-->
  203 + <!-- <el-descriptions title="版本信息" border :column="1">-->
  204 + <!-- <template slot="extra">-->
  205 + <!-- <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝"-->
  206 + <!-- v-clipboard="JSON.stringify(wvpServerVersion) || ''"-->
  207 + <!-- @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>-->
  208 + <!-- </template>-->
  209 + <!-- <el-descriptions-item v-for="(value, key, index) in wvpServerVersion" :key="key">-->
  210 + <!-- <template slot="label">-->
  211 + <!-- {{ getNameFromKey(key) }}-->
  212 + <!-- </template>-->
  213 + <!-- {{ value }}-->
  214 + <!-- </el-descriptions-item>-->
  215 + <!-- </el-descriptions>-->
132 216
133 -</div> 217 +
  218 + <!-- </div>-->
  219 + <!-- </div>-->
  220 + <!-- <el-button type="primary" slot="reference" size="mini" @click="getWVPServerConfig()">信令服务器配置</el-button>-->
  221 + <!-- </el-popover>-->
  222 + <!-- <el-button style="margin-left: 1rem;" type="danger" size="mini" @click="reStartServer()">重启媒体服务器</el-button>-->
  223 + <!-- </div>-->
  224 + <!-- </div>-->
  225 + <el-row style="width: 100%">
  226 + <el-col :span="12">
  227 + <div class="control-table" id="ThreadsLoad" style="margin-right:10px;">table1</div>
  228 + </el-col>
  229 + <el-col :span="12">
  230 + <div class="control-table" id="WorkThreadsLoad" style="margin-left:10px;">table2</div>
  231 + </el-col>
  232 + </el-row>
  233 + <el-table :data="allSessionData" style="margin-top: 1rem;">
  234 + <el-table-column prop="peer_ip" label="远端"></el-table-column>
  235 + <el-table-column prop="local_ip" label="本地"></el-table-column>
  236 + <el-table-column prop="typeid" label="类型"></el-table-column>
  237 + <el-table-column align="right">
  238 + <template slot="header" slot-scope="scope">
  239 + <el-button icon="el-icon-refresh-right" circle @click="getAllSession()"></el-button>
  240 + </template>
  241 + <template slot-scope="scope">
  242 + <el-button @click.native.prevent="deleteRow(scope.$index, allSessionData)" type="text" size="small">移除
  243 + </el-button>
  244 + </template>
  245 + </el-table-column>
  246 + </el-table>
  247 + </div>
134 </template> 248 </template>
135 249
136 <script> 250 <script>
137 -import uiHeader from './UiHeader.vue' 251 +import uiHeader from '../layout/UiHeader.vue'
138 import MediaServer from './service/MediaServer' 252 import MediaServer from './service/MediaServer'
139 253
140 import echarts from 'echarts'; 254 import echarts from 'echarts';
141 -export default {  
142 - name: 'app',  
143 - components: {  
144 - echarts,  
145 - uiHeader  
146 - },  
147 - data() {  
148 - return {  
149 - tableOption: {  
150 - // legend: {},  
151 - xAxis: {},  
152 - yAxis: {},  
153 - label: {},  
154 - tooltip: {},  
155 - dataZoom: [],  
156 - series: []  
157 - },  
158 - table1Option: {  
159 - // legend: {},  
160 - xAxis: {},  
161 - yAxis: {},  
162 - label: {},  
163 - tooltip: {},  
164 - series: []  
165 - },  
166 - mChart: null,  
167 - mChart1: null,  
168 - charZoomStart: 0,  
169 - charZoomEnd: 100,  
170 - chartInterval: 0, //更新图表统计图定时任务标识  
171 - allSessionData: [],  
172 - visible: false,  
173 - wvpVisible: false,  
174 - serverConfig: {},  
175 - wvpServerConfig: {},  
176 - wvpServerVersion: {},  
177 - mediaServer : new MediaServer(),  
178 - mediaServerChoose : null,  
179 - loadCount : 0,  
180 - mediaServerList : []  
181 - };  
182 - },  
183 - mounted() {  
184 255
185 - this.initTable();  
186 - this.chartInterval = setInterval(this.updateData, 3000);  
187 - this.mediaServer.getOnlineMediaServerList((data)=>{  
188 - this.mediaServerList = data.data;  
189 - if (this.mediaServerList && this.mediaServerList.length > 0) {  
190 - this.mediaServerChoose = this.mediaServerList[0].id  
191 - this.loadCount = this.mediaServerList[0].count;  
192 - this.updateData();  
193 - }  
194 - }) 256 +export default {
  257 + name: 'app',
  258 + components: {
  259 + echarts,
  260 + uiHeader
  261 + },
  262 + data() {
  263 + return {
  264 + tableOption: {
  265 + // legend: {},
  266 + xAxis: {},
  267 + yAxis: {},
  268 + label: {},
  269 + tooltip: {},
  270 + dataZoom: [],
  271 + series: []
  272 + },
  273 + table1Option: {
  274 + // legend: {},
  275 + xAxis: {},
  276 + yAxis: {},
  277 + label: {},
  278 + tooltip: {},
  279 + series: []
  280 + },
  281 + mChart: null,
  282 + mChart1: null,
  283 + charZoomStart: 0,
  284 + charZoomEnd: 100,
  285 + chartInterval: 0, //更新图表统计图定时任务标识
  286 + allSessionData: [],
  287 + visible: false,
  288 + wvpVisible: false,
  289 + serverConfig: {},
  290 + wvpServerConfig: {},
  291 + wvpServerVersion: {},
  292 + mediaServer: new MediaServer(),
  293 + mediaServerChoose: null,
  294 + loadCount: 0,
  295 + mediaServerList: []
  296 + };
  297 + },
  298 + mounted() {
  299 + this.initTable()
  300 + this.chartInterval = setInterval(this.updateData, 3000);
  301 + this.mediaServer.getOnlineMediaServerList((data) => {
  302 + this.mediaServerList = data.data;
  303 + if (this.mediaServerList && this.mediaServerList.length > 0) {
  304 + this.mediaServerChoose = this.mediaServerList[0].id
  305 + this.loadCount = this.mediaServerList[0].count;
  306 + this.updateData();
  307 + }
  308 + })
  309 + },
  310 + destroyed() {
  311 + clearInterval(this.chartInterval); //释放定时任务
  312 + },
  313 + methods: {
  314 + chooseMediaChange: function (val) {
  315 + this.loadCount = 0
  316 + this.initTable()
  317 + this.updateData();
195 }, 318 },
196 - destroyed() {  
197 - clearInterval(this.chartInterval); //释放定时任务 319 + updateData: function () {
  320 + this.getThreadsLoad();
  321 + this.getLoadCount();
  322 + this.getAllSession();
198 }, 323 },
199 - methods: {  
200 - chooseMediaChange: function (val) {  
201 - this.loadCount = 0  
202 - this.initTable()  
203 - this.updateData();  
204 - },  
205 - updateData: function () {  
206 - this.getThreadsLoad();  
207 - this.getLoadCount();  
208 - this.getAllSession();  
209 - },  
210 - /**  
211 - * 获取线程状态  
212 - */  
213 - getThreadsLoad: function () {  
214 - let that = this;  
215 - if (that.mediaServerChoose != null) {  
216 - this.$axios({  
217 - method: 'get',  
218 - url: '/zlm/' + that.mediaServerChoose +'/index/api/getThreadsLoad'  
219 - }).then(function (res) {  
220 - if (res.data.code == 0) {  
221 - that.tableOption.xAxis.data.push(new Date().toLocaleTimeString('chinese', {  
222 - hour12: false  
223 - }));  
224 - that.table1Option.xAxis.data.push(new Date().toLocaleTimeString('chinese', {  
225 - hour12: false  
226 - })); 324 + /**
  325 + * 获取线程状态
  326 + */
  327 + getThreadsLoad: function () {
  328 + let that = this;
  329 + if (that.mediaServerChoose != null) {
  330 + this.$axios({
  331 + method: 'get',
  332 + url: '/zlm/' + that.mediaServerChoose + '/index/api/getThreadsLoad'
  333 + }).then(function (res) {
  334 + if (res.data.code == 0) {
  335 + that.tableOption.xAxis.data.push(new Date().toLocaleTimeString('chinese', {
  336 + hour12: false
  337 + }));
  338 + that.table1Option.xAxis.data.push(new Date().toLocaleTimeString('chinese', {
  339 + hour12: false
  340 + }));
227 341
228 - for (var i = 0; i < res.data.data.length; i++) {  
229 - if (that.tableOption.series[i] === undefined) {  
230 - let data = {  
231 - data: [],  
232 - type: 'line'  
233 - };  
234 - let data1 = {  
235 - data: [],  
236 - type: 'line'  
237 - };  
238 - data.data.push(res.data.data[i].delay);  
239 - data1.data.push(res.data.data[i].load);  
240 - that.tableOption.series.push(data);  
241 - that.table1Option.series.push(data1);  
242 - } else {  
243 - that.tableOption.series[i].data.push(res.data.data[i].delay);  
244 - that.table1Option.series[i].data.push(res.data.data[i].load);  
245 - }  
246 - }  
247 - that.tableOption.dataZoom[0].start = that.charZoomStart;  
248 - that.tableOption.dataZoom[0].end = that.charZoomEnd;  
249 - that.table1Option.dataZoom[0].start = that.charZoomStart;  
250 - that.table1Option.dataZoom[0].end = that.charZoomEnd;  
251 - //that.myChart = echarts.init(document.getElementById('ThreadsLoad'));  
252 - that.myChart.setOption(that.tableOption, true);  
253 - // that.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad'));  
254 - that.myChart1.setOption(that.table1Option, true);  
255 - }  
256 - });  
257 - }  
258 -  
259 - },  
260 - getLoadCount: function (){  
261 - let that = this;  
262 - if (that.mediaServerChoose != null) {  
263 - that.mediaServer.getMediaServer(that.mediaServerChoose, (data)=>{  
264 - if (data.code == 0) {  
265 - that.loadCount = data.data.count 342 + for (var i = 0; i < res.data.data.length; i++) {
  343 + if (that.tableOption.series[i] === undefined) {
  344 + let data = {
  345 + data: [],
  346 + type: 'line'
  347 + };
  348 + let data1 = {
  349 + data: [],
  350 + type: 'line'
  351 + };
  352 + data.data.push(res.data.data[i].delay);
  353 + data1.data.push(res.data.data[i].load);
  354 + that.tableOption.series.push(data);
  355 + that.table1Option.series.push(data1);
  356 + } else {
  357 + that.tableOption.series[i].data.push(res.data.data[i].delay);
  358 + that.table1Option.series[i].data.push(res.data.data[i].load);
266 } 359 }
  360 + }
  361 + that.tableOption.dataZoom[0].start = that.charZoomStart;
  362 + that.tableOption.dataZoom[0].end = that.charZoomEnd;
  363 + that.table1Option.dataZoom[0].start = that.charZoomStart;
  364 + that.table1Option.dataZoom[0].end = that.charZoomEnd;
  365 + //that.myChart = echarts.init(document.getElementById('ThreadsLoad'));
  366 + that.myChart.setOption(that.tableOption, true);
  367 + // that.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad'));
  368 + that.myChart1.setOption(that.table1Option, true);
  369 + that.$nextTick(() => {
  370 + that.myChart.resize()
  371 + that.myChart1.resize()
267 }) 372 })
268 } 373 }
269 - },  
270 - initTable: function () {  
271 - let that = this;  
272 - this.tableOption.xAxis = {  
273 - type: 'category',  
274 - data: [], // x轴数据  
275 - name: '时间', // x轴名称  
276 - // x轴名称样式  
277 - nameTextStyle: {  
278 - fontWeight: 300,  
279 - fontSize: 15  
280 - }  
281 - };  
282 - this.tableOption.yAxis = {  
283 - type: 'value',  
284 - name: '延迟率', // y轴名称  
285 - boundaryGap: [0, '100%'],  
286 - max: 100,  
287 - axisLabel: {  
288 - show: true,  
289 - interval: 'auto',  
290 - formatter: '{value} %'  
291 - },  
292 - // y轴名称样式  
293 - nameTextStyle: {  
294 - fontWeight: 300,  
295 - fontSize: 15  
296 - }  
297 - };  
298 - this.tableOption.dataZoom = [{  
299 - show: true,  
300 - start: this.charZoomStart,  
301 - end: this.charZoomEnd  
302 - }];  
303 - this.myChart = echarts.init(document.getElementById('ThreadsLoad'));  
304 - this.myChart.setOption(this.tableOption);  
305 - this.myChart.on('dataZoom', function (event) {  
306 - if (event.batch) {  
307 - that.charZoomStart = event.batch[0].start;  
308 - that.charZoomEnd = event.batch[0].end;  
309 - } else {  
310 - that.charZoomStart = event.start;  
311 - that.charZoomEnd = event.end;  
312 - }  
313 - }); 374 + });
  375 + }
314 376
315 - this.table1Option.xAxis = {  
316 - type: 'category',  
317 - data: [], // x轴数据  
318 - name: '时间', // x轴名称  
319 - // x轴名称样式  
320 - nameTextStyle: {  
321 - fontWeight: 300,  
322 - fontSize: 15  
323 - }  
324 - };  
325 - this.table1Option.yAxis = {  
326 - type: 'value',  
327 - name: '负载率', // y轴名称  
328 - boundaryGap: [0, '100%'],  
329 - max: 100,  
330 - axisLabel: {  
331 - show: true,  
332 - interval: 'auto',  
333 - formatter: '{value} %'  
334 - },  
335 - // y轴名称样式  
336 - nameTextStyle: {  
337 - fontWeight: 300,  
338 - fontSize: 15  
339 - }  
340 - };  
341 - this.table1Option.dataZoom = [{  
342 - show: true,  
343 - start: this.charZoomStart,  
344 - end: this.charZoomEnd  
345 - }];  
346 - this.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad'));  
347 - this.myChart1.setOption(this.table1Option);  
348 - this.myChart1.on('dataZoom', function (event) {  
349 - if (event.batch) {  
350 - that.charZoomStart = event.batch[0].start;  
351 - that.charZoomEnd = event.batch[0].end;  
352 - } else {  
353 - that.charZoomStart = event.start;  
354 - that.charZoomEnd = event.end;  
355 - }  
356 - }); 377 + },
  378 + getLoadCount: function () {
  379 + let that = this;
  380 + if (that.mediaServerChoose != null) {
  381 + that.mediaServer.getMediaServer(that.mediaServerChoose, (data) => {
  382 + if (data.code == 0) {
  383 + that.loadCount = data.data.count
  384 + }
  385 + })
  386 + }
  387 + },
  388 + initTable: function () {
  389 + let that = this;
  390 + this.tableOption.xAxis = {
  391 + type: 'category',
  392 + data: [], // x轴数据
  393 + name: '时间', // x轴名称
  394 + // x轴名称样式
  395 + nameTextStyle: {
  396 + fontWeight: 300,
  397 + fontSize: 15
  398 + }
  399 + };
  400 + this.tableOption.yAxis = {
  401 + type: 'value',
  402 + name: '延迟率', // y轴名称
  403 + boundaryGap: [0, '100%'],
  404 + max: 100,
  405 + axisLabel: {
  406 + show: true,
  407 + interval: 'auto',
  408 + formatter: '{value} %'
357 }, 409 },
  410 + // y轴名称样式
  411 + nameTextStyle: {
  412 + fontWeight: 300,
  413 + fontSize: 15
  414 + }
  415 + };
  416 + this.tableOption.dataZoom = [{
  417 + show: true,
  418 + start: this.charZoomStart,
  419 + end: this.charZoomEnd
  420 + }];
  421 + this.myChart = echarts.init(document.getElementById('ThreadsLoad'));
  422 + this.myChart.setOption(this.tableOption);
  423 + this.myChart.on('dataZoom', function (event) {
  424 + if (event.batch) {
  425 + that.charZoomStart = event.batch[0].start;
  426 + that.charZoomEnd = event.batch[0].end;
  427 + } else {
  428 + that.charZoomStart = event.start;
  429 + that.charZoomEnd = event.end;
  430 + }
  431 + });
358 432
359 - getAllSession: function () {  
360 - let that = this;  
361 - that.allSessionData = [];  
362 - this.$axios({  
363 - method: 'get',  
364 - url: '/zlm/' + that.mediaServerChoose +'/index/api/getAllSession'  
365 - }).then(function (res) {  
366 - res.data.data.forEach(item => {  
367 - let data = {  
368 - peer_ip: item.peer_ip,  
369 - local_ip: item.local_ip,  
370 - typeid: item.typeid,  
371 - id: item.id  
372 - };  
373 - that.allSessionData.push(data);  
374 - });  
375 - }); 433 + this.table1Option.xAxis = {
  434 + type: 'category',
  435 + data: [], // x轴数据
  436 + name: '时间', // x轴名称
  437 + // x轴名称样式
  438 + nameTextStyle: {
  439 + fontWeight: 300,
  440 + fontSize: 15
  441 + }
  442 + };
  443 + this.table1Option.yAxis = {
  444 + type: 'value',
  445 + name: '负载率', // y轴名称
  446 + boundaryGap: [0, '100%'],
  447 + max: 100,
  448 + axisLabel: {
  449 + show: true,
  450 + interval: 'auto',
  451 + formatter: '{value} %'
376 }, 452 },
377 - getServerConfig: function () {  
378 - let that = this;  
379 - this.$axios({  
380 - method: 'get',  
381 - url: '/zlm/' + that.mediaServerChoose +'/index/api/getServerConfig'  
382 - }).then(function (res) {  
383 - let info = res.data.data[0];  
384 - let serverInfo = {}  
385 - for (let i = 0; i < Object.keys(info).length; i++) {  
386 - let key = Object.keys(info)[i];  
387 - let group = key.substring(0, key.indexOf("."))  
388 - let itemKey = key.substring(key.indexOf(".") + 1)  
389 - if (!serverInfo[group]) serverInfo[group] = {}  
390 - serverInfo[group][itemKey] = info[key]  
391 - } 453 + // y轴名称样式
  454 + nameTextStyle: {
  455 + fontWeight: 300,
  456 + fontSize: 15
  457 + }
  458 + };
  459 + this.table1Option.dataZoom = [{
  460 + show: true,
  461 + start: this.charZoomStart,
  462 + end: this.charZoomEnd
  463 + }];
  464 + this.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad'));
  465 + this.myChart1.setOption(this.table1Option);
  466 + this.myChart1.on('dataZoom', function (event) {
  467 + if (event.batch) {
  468 + that.charZoomStart = event.batch[0].start;
  469 + that.charZoomEnd = event.batch[0].end;
  470 + } else {
  471 + that.charZoomStart = event.start;
  472 + that.charZoomEnd = event.end;
  473 + }
  474 + });
  475 + },
392 476
393 - that.serverConfig = serverInfo;  
394 - that.visible = true;  
395 - });  
396 - },  
397 - getWVPServerConfig: function () {  
398 - let that = this;  
399 - this.$axios({  
400 - method: 'get',  
401 - url: '/api/server/config'  
402 - }).then(function (res) {  
403 - console.log(res)  
404 - that.wvpServerConfig = res.data.data;  
405 - that.wvpVisible = true;  
406 - });  
407 - this.$axios({  
408 - method: 'get',  
409 - url: '/api/server/version'  
410 - }).then(function (res) {  
411 - console.log(res)  
412 - that.wvpServerVersion = res.data.data;  
413 - that.wvpVisible = true;  
414 - });  
415 - },  
416 - reStartServer: function () {  
417 - let that = this;  
418 - this.$confirm('此操作将重启媒体服务器, 是否继续?', '提示', {  
419 - confirmButtonText: '确定',  
420 - cancelButtonText: '取消',  
421 - type: 'warning'  
422 - }).then(() => {  
423 - let that = this;  
424 - this.$axios({  
425 - method: 'get',  
426 - url: '/zlm/' + that.mediaServerChoose +'/index/api/restartServer'  
427 - }).then(function (res) {  
428 - that.getAllSession();  
429 - if (res.data.code == 0) {  
430 - that.$message({  
431 - type: 'success',  
432 - message: '操作完成'  
433 - });  
434 - }  
435 - });  
436 - });  
437 - },  
438 - deleteRow: function (index, tabledata) {  
439 - let that = this;  
440 - this.$confirm('此操作将断开该通信链路, 是否继续?', '提示', {  
441 - confirmButtonText: '确定',  
442 - cancelButtonText: '取消',  
443 - type: 'warning'  
444 - })  
445 - .then(() => {  
446 - that.deleteSession(tabledata[index].id);  
447 - })  
448 - .catch(() => {  
449 - console.log('id:' + JSON.stringify(tabledata[index]));  
450 - this.$message({  
451 - type: 'info',  
452 - message: '已取消删除'  
453 - });  
454 - });  
455 - console.log(JSON.stringify(tabledata[index]));  
456 - },  
457 - deleteSession: function (id) {  
458 - let that = this;  
459 - this.$axios({  
460 - method: 'get',  
461 - url: '/zlm/' + that.mediaServerChoose +'/index/api/kick_session&id=' + id  
462 - }).then(function (res) {  
463 - that.getAllSession();  
464 - that.$message({  
465 - type: 'success',  
466 - message: '删除成功!'  
467 - });  
468 - });  
469 - },  
470 - getNameFromKey: function(key) {  
471 - let nameData = {  
472 - "waitTrack": "等待编码信息",  
473 - "interfaceAuthenticationExcludes": "不进行鉴权的接口",  
474 - "playTimeout": "点播超时时间",  
475 - "autoApplyPlay": "自动点播",  
476 - "recordPushLive": "推流录像",  
477 - "redisConfig": "自动配置redis",  
478 - "thirdPartyGBIdReg": "stream信息正则",  
479 - "savePositionHistory": "保存轨迹信息",  
480 - "interfaceAuthentication": "接口鉴权",  
481 - "serverId": "服务ID",  
482 - "logInDatebase": "日志存储进数据库",  
483 - "seniorSdp": "扩展SDP",  
484 - "password": "密码",  
485 - "port": "端口号",  
486 - "keepaliveTimeOut": "心跳超时",  
487 - "domain": "国标域",  
488 - "ip": "IP地址",  
489 - "monitorIp": "监听IP",  
490 - "alarm": "存储报警信息",  
491 - "ptzSpeed": "云台控制速度",  
492 - "id": "国标ID",  
493 - "registerTimeInterval": "注册间隔",  
494 - "artifactId": "模块名称",  
495 - "version": "版本",  
496 - "project": "工程",  
497 - "git_Revision": "GIT修订版本",  
498 - "git_BRANCH": "GIT分支",  
499 - "git_URL": "GIT地址",  
500 - "build_DATE": "构建时间",  
501 - "create_By": "作者",  
502 - "git_Revision_SHORT": "GIT修订版本(短)",  
503 - "build_Jdk": "构建用JDK", 477 + getAllSession: function () {
  478 + let that = this;
  479 + that.allSessionData = [];
  480 + this.$axios({
  481 + method: 'get',
  482 + url: '/zlm/' + that.mediaServerChoose + '/index/api/getAllSession'
  483 + }).then(function (res) {
  484 + res.data.data.forEach(item => {
  485 + let data = {
  486 + peer_ip: item.peer_ip,
  487 + local_ip: item.local_ip,
  488 + typeid: item.typeid,
  489 + id: item.id
504 }; 490 };
505 - console.log(key + ": " + nameData[key]) 491 + that.allSessionData.push(data);
  492 + });
  493 + });
  494 + },
  495 + getServerConfig: function () {
  496 + let that = this;
  497 + this.$axios({
  498 + method: 'get',
  499 + url: '/zlm/' + that.mediaServerChoose + '/index/api/getServerConfig'
  500 + }).then(function (res) {
  501 + let info = res.data.data[0];
  502 + let serverInfo = {}
  503 + for (let i = 0; i < Object.keys(info).length; i++) {
  504 + let key = Object.keys(info)[i];
  505 + let group = key.substring(0, key.indexOf("."))
  506 + let itemKey = key.substring(key.indexOf(".") + 1)
  507 + if (!serverInfo[group]) serverInfo[group] = {}
  508 + serverInfo[group][itemKey] = info[key]
  509 + }
506 510
507 - if (nameData[key]) {  
508 - return nameData[key]  
509 - }else {  
510 - return key; 511 + that.serverConfig = serverInfo;
  512 + that.visible = true;
  513 + });
  514 + },
  515 + getWVPServerConfig: function () {
  516 + let that = this;
  517 + this.$axios({
  518 + method: 'get',
  519 + url: '/api/server/config'
  520 + }).then(function (res) {
  521 + console.log(res)
  522 + that.wvpServerConfig = res.data.data;
  523 + that.wvpVisible = true;
  524 + });
  525 + this.$axios({
  526 + method: 'get',
  527 + url: '/api/server/version'
  528 + }).then(function (res) {
  529 + console.log(res)
  530 + that.wvpServerVersion = res.data.data;
  531 + that.wvpVisible = true;
  532 + });
  533 + },
  534 + reStartServer: function () {
  535 + let that = this;
  536 + this.$confirm('此操作将重启媒体服务器, 是否继续?', '提示', {
  537 + confirmButtonText: '确定',
  538 + cancelButtonText: '取消',
  539 + type: 'warning'
  540 + }).then(() => {
  541 + let that = this;
  542 + this.$axios({
  543 + method: 'get',
  544 + url: '/zlm/' + that.mediaServerChoose + '/index/api/restartServer'
  545 + }).then(function (res) {
  546 + that.getAllSession();
  547 + if (res.data.code == 0) {
  548 + that.$message({
  549 + type: 'success',
  550 + message: '操作完成'
  551 + });
511 } 552 }
512 - },  
513 - getMediaKeyNameFromKey: function(key) {  
514 - let nameData = {  
515 - "waitTrack": "等待编码信息",  
516 - "interfaceAuthenticationExcludes": "不进行鉴权的接口",  
517 - "playTimeout": "点播超时时间",  
518 - "autoApplyPlay": "自动点播",  
519 - "recordPushLive": "推流录像",  
520 - "redisConfig": "自动配置redis",  
521 - "thirdPartyGBIdReg": "stream信息正则",  
522 - "savePositionHistory": "保存轨迹信息",  
523 - "interfaceAuthentication": "接口鉴权",  
524 - "serverId": "服务ID",  
525 - "logInDatebase": "日志存储进数据库",  
526 - "seniorSdp": "扩展SDP",  
527 - "password": "密码",  
528 - "port": "端口号",  
529 - "keepaliveTimeOut": "心跳超时",  
530 - "domain": "国标域",  
531 - "ip": "IP地址",  
532 - "monitorIp": "监听IP",  
533 - "alarm": "存储报警信息",  
534 - "ptzSpeed": "云台控制速度",  
535 - "id": "国标ID",  
536 - "registerTimeInterval": "注册间隔",  
537 - "artifactId": "模块名称",  
538 - "version": "版本",  
539 - "project": "工程",  
540 - "git_Revision": "GIT修订版本",  
541 - "git_BRANCH": "GIT分支",  
542 - "git_URL": "GIT地址",  
543 - "build_DATE": "构建时间",  
544 - "create_By": "作者",  
545 - "git_Revision_SHORT": "GIT修订版本(短)",  
546 - "build_Jdk": "构建用JDK",  
547 - };  
548 - console.log(key + ": " + nameData[key]) 553 + });
  554 + });
  555 + },
  556 + deleteRow: function (index, tabledata) {
  557 + let that = this;
  558 + this.$confirm('此操作将断开该通信链路, 是否继续?', '提示', {
  559 + confirmButtonText: '确定',
  560 + cancelButtonText: '取消',
  561 + type: 'warning'
  562 + })
  563 + .then(() => {
  564 + that.deleteSession(tabledata[index].id);
  565 + })
  566 + .catch(() => {
  567 + console.log('id:' + JSON.stringify(tabledata[index]));
  568 + this.$message({
  569 + type: 'info',
  570 + message: '已取消删除'
  571 + });
  572 + });
  573 + console.log(JSON.stringify(tabledata[index]));
  574 + },
  575 + deleteSession: function (id) {
  576 + let that = this;
  577 + this.$axios({
  578 + method: 'get',
  579 + url: '/zlm/' + that.mediaServerChoose + '/index/api/kick_session&id=' + id
  580 + }).then(function (res) {
  581 + that.getAllSession();
  582 + that.$message({
  583 + type: 'success',
  584 + message: '删除成功!'
  585 + });
  586 + });
  587 + },
  588 + getNameFromKey: function (key) {
  589 + let nameData = {
  590 + "waitTrack": "等待编码信息",
  591 + "interfaceAuthenticationExcludes": "不进行鉴权的接口",
  592 + "playTimeout": "点播超时时间",
  593 + "autoApplyPlay": "自动点播",
  594 + "recordPushLive": "推流录像",
  595 + "redisConfig": "自动配置redis",
  596 + "thirdPartyGBIdReg": "stream信息正则",
  597 + "savePositionHistory": "保存轨迹信息",
  598 + "interfaceAuthentication": "接口鉴权",
  599 + "serverId": "服务ID",
  600 + "logInDatebase": "日志存储进数据库",
  601 + "seniorSdp": "扩展SDP",
  602 + "password": "密码",
  603 + "port": "端口号",
  604 + "keepaliveTimeOut": "心跳超时",
  605 + "domain": "国标域",
  606 + "ip": "IP地址",
  607 + "monitorIp": "监听IP",
  608 + "alarm": "存储报警信息",
  609 + "ptzSpeed": "云台控制速度",
  610 + "id": "国标ID",
  611 + "registerTimeInterval": "注册间隔",
  612 + "artifactId": "模块名称",
  613 + "version": "版本",
  614 + "project": "工程",
  615 + "git_Revision": "GIT修订版本",
  616 + "git_BRANCH": "GIT分支",
  617 + "git_URL": "GIT地址",
  618 + "build_DATE": "构建时间",
  619 + "create_By": "作者",
  620 + "git_Revision_SHORT": "GIT修订版本(短)",
  621 + "build_Jdk": "构建用JDK",
  622 + };
  623 + console.log(key + ": " + nameData[key])
549 624
550 - if (nameData[key]) {  
551 - return nameData[key]  
552 - }else {  
553 - return key;  
554 - }  
555 - } 625 + if (nameData[key]) {
  626 + return nameData[key]
  627 + } else {
  628 + return key;
  629 + }
  630 + },
  631 + getMediaKeyNameFromKey: function (key) {
  632 + let nameData = {
  633 + "waitTrack": "等待编码信息",
  634 + "interfaceAuthenticationExcludes": "不进行鉴权的接口",
  635 + "playTimeout": "点播超时时间",
  636 + "autoApplyPlay": "自动点播",
  637 + "recordPushLive": "推流录像",
  638 + "redisConfig": "自动配置redis",
  639 + "thirdPartyGBIdReg": "stream信息正则",
  640 + "savePositionHistory": "保存轨迹信息",
  641 + "interfaceAuthentication": "接口鉴权",
  642 + "serverId": "服务ID",
  643 + "logInDatebase": "日志存储进数据库",
  644 + "seniorSdp": "扩展SDP",
  645 + "password": "密码",
  646 + "port": "端口号",
  647 + "keepaliveTimeOut": "心跳超时",
  648 + "domain": "国标域",
  649 + "ip": "IP地址",
  650 + "monitorIp": "监听IP",
  651 + "alarm": "存储报警信息",
  652 + "ptzSpeed": "云台控制速度",
  653 + "id": "国标ID",
  654 + "registerTimeInterval": "注册间隔",
  655 + "artifactId": "模块名称",
  656 + "version": "版本",
  657 + "project": "工程",
  658 + "git_Revision": "GIT修订版本",
  659 + "git_BRANCH": "GIT分支",
  660 + "git_URL": "GIT地址",
  661 + "build_DATE": "构建时间",
  662 + "create_By": "作者",
  663 + "git_Revision_SHORT": "GIT修订版本(短)",
  664 + "build_Jdk": "构建用JDK",
  665 + };
  666 + console.log(key + ": " + nameData[key])
  667 +
  668 + if (nameData[key]) {
  669 + return nameData[key]
  670 + } else {
  671 + return key;
  672 + }
556 } 673 }
  674 + }
557 }; 675 };
558 </script> 676 </script>
559 677
560 <style> 678 <style>
561 #app { 679 #app {
562 - height: 100%; 680 + height: 100%;
563 } 681 }
564 682
565 .control-table { 683 .control-table {
566 - background-color: #ffffff;  
567 - height: 25rem; 684 + background-color: #ffffff;
  685 + height: 25rem;
568 } 686 }
569 687
570 .table-c { 688 .table-c {
571 - border-right: 1px solid #dcdcdc;  
572 - border-bottom: 1px solid #dcdcdc; 689 + border-right: 1px solid #dcdcdc;
  690 + border-bottom: 1px solid #dcdcdc;
573 } 691 }
574 692
575 .table-c td { 693 .table-c td {
576 - border-left: 1px solid #dcdcdc;  
577 - border-top: 1px solid #dcdcdc;  
578 - padding: 0.2rem; 694 + border-left: 1px solid #dcdcdc;
  695 + border-top: 1px solid #dcdcdc;
  696 + padding: 0.2rem;
579 } 697 }
580 698
581 .el-table { 699 .el-table {
582 - width: 99.9% !important; 700 + width: 99.9% !important;
583 } 701 }
584 </style> 702 </style>
web_src/src/components/devicePosition.vue
1 <template> 1 <template>
2 <div id="devicePosition" style="height: 100%"> 2 <div id="devicePosition" style="height: 100%">
3 - <el-container style="height: 100%">  
4 - <el-header>  
5 - <uiHeader></uiHeader>  
6 - </el-header>  
7 - <el-main>  
8 - <div style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center;">  
9 - <span style="font-size: 1rem; font-weight: 500">设备定位 ({{ parentChannelId == 0 ? deviceId : parentChannelId }})</span>  
10 - </div>  
11 - <div style="background-color: #ffffff; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left; font-size: 14px;">  
12 - <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem" type="primary" @click="showDevice">返回</el-button>  
13 - <!-- <span class="demonstration">从</span> -->  
14 - <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>  
15 - <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>  
16 - <el-button-group>  
17 - <el-button icon="el-icon-search" size="mini" type="primary" @click="showHistoryPath">历史轨迹</el-button>  
18 - <el-button icon="el-icon-search" size="mini" style="margin-right: 1rem" type="primary" @click="showLatestPosition">最新位置</el-button>  
19 - </el-button-group>  
20 - <el-tag style="width: 5rem; text-align: center" size="medium">过期时间</el-tag>  
21 - <el-input-number size="mini" v-model="expired" :min="300" :controls="false" style="width: 4rem;"></el-input-number>  
22 - <el-tag style="width: 5rem; text-align: center" size="medium">上报周期</el-tag>  
23 - <el-input-number size="mini" v-model="interval" :min="1" :controls="false" style="width: 4rem;"></el-input-number>  
24 - <el-button-group>  
25 - <el-button icon="el-icon-search" size="mini" type="primary" @click="subscribeMobilePosition">位置订阅</el-button>  
26 - <el-button icon="el-icon-search" size="mini" type="primary" @click="unSubscribeMobilePosition">取消订阅</el-button>  
27 - </el-button-group>  
28 - <el-checkbox size="mini" style="margin-right: 1rem; float: right" v-model="autoList" @change="autoListChange" >自动刷新</el-checkbox>  
29 - </div>  
30 - <div class="mapContainer" style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center; height: calc(100% - 10rem);">  
31 - <div class="baidumap" id="allmap"></div>  
32 - </div>  
33 - </el-main>  
34 - </el-container> 3 + <div style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center;">
  4 + <span style="font-size: 1rem; font-weight: 500">设备定位 ({{ parentChannelId == 0 ? deviceId : parentChannelId }})</span>
  5 + </div>
  6 + <div style="background-color: #ffffff; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left; font-size: 14px;">
  7 + <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem" type="primary" @click="showDevice">返回</el-button>
  8 + <!-- <span class="demonstration">从</span> -->
  9 + <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>
  10 + <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>
  11 + <el-button-group>
  12 + <el-button icon="el-icon-search" size="mini" type="primary" @click="showHistoryPath">历史轨迹</el-button>
  13 + <el-button icon="el-icon-search" size="mini" style="margin-right: 1rem" type="primary" @click="showLatestPosition">最新位置</el-button>
  14 + </el-button-group>
  15 + <el-tag style="width: 5rem; text-align: center" size="medium">过期时间</el-tag>
  16 + <el-input-number size="mini" v-model="expired" :min="300" :controls="false" style="width: 4rem;"></el-input-number>
  17 + <el-tag style="width: 5rem; text-align: center" size="medium">上报周期</el-tag>
  18 + <el-input-number size="mini" v-model="interval" :min="1" :controls="false" style="width: 4rem;"></el-input-number>
  19 + <el-button-group>
  20 + <el-button icon="el-icon-search" size="mini" type="primary" @click="subscribeMobilePosition">位置订阅</el-button>
  21 + <el-button icon="el-icon-search" size="mini" type="primary" @click="unSubscribeMobilePosition">取消订阅</el-button>
  22 + </el-button-group>
  23 + <el-checkbox size="mini" style="margin-right: 1rem; float: right" v-model="autoList" @change="autoListChange" >自动刷新</el-checkbox>
  24 + </div>
  25 + <div class="mapContainer" style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center; height: calc(100% - 10rem);">
  26 + <div class="baidumap" id="allmap"></div>
  27 + </div>
35 </div> 28 </div>
36 </template> 29 </template>
37 30
38 <script> 31 <script>
39 -import uiHeader from "./UiHeader.vue";  
40 -import moment from "moment"; 32 +import uiHeader from "../layout/UiHeader.vue";
41 import geoTools from "./GeoConvertTools.js"; 33 import geoTools from "./GeoConvertTools.js";
42 export default { 34 export default {
43 name: "devicePosition", 35 name: "devicePosition",
@@ -173,7 +165,7 @@ export default { @@ -173,7 +165,7 @@ export default {
173 let self = this; 165 let self = this;
174 this.$axios({ 166 this.$axios({
175 method: 'get', 167 method: 'get',
176 - url:`/api/position/history/${this.deviceId}`, 168 + url:`/api/position/history/${this.deviceId}`,
177 params: { 169 params: {
178 start: self.startTime, 170 start: self.startTime,
179 end: self.endTime, 171 end: self.endTime,
@@ -259,7 +251,7 @@ export default { @@ -259,7 +251,7 @@ export default {
259 }, 251 },
260 toGBString: function (dateTime) { 252 toGBString: function (dateTime) {
261 return ( 253 return (
262 - dateTime.getFullYear() + 254 + dateTime.getFullYear() +
263 "-" + this.twoDigits(dateTime.getMonth() + 1) + 255 "-" + this.twoDigits(dateTime.getMonth() + 1) +
264 "-" + this.twoDigits(dateTime.getDate()) + 256 "-" + this.twoDigits(dateTime.getDate()) +
265 "T" + this.twoDigits(dateTime.getHours()) + 257 "T" + this.twoDigits(dateTime.getHours()) +
web_src/src/components/live.vue
1 <template> 1 <template>
2 - <div id="devicePosition" style="height: 100%">  
3 - <el-container style="height: 100%">  
4 - <el-header>  
5 - <uiHeader></uiHeader>  
6 - </el-header>  
7 - <el-container v-loading="loading" element-loading-text="拼命加载中" style="margin: 0 20px;">  
8 - <el-aside width="300px" style="background-color: #ffffff">  
9 - <div style="text-align: center;padding-top: 20px;">设备列表</div>  
10 - <el-menu v-loading="loading">  
11 - <el-submenu v-for="device in deviceList" :key="device.deviceId" :index="device.deviceId" @click="sendDevicePush(item)">  
12 - <template slot="title" >  
13 - <i class="el-icon-location-outline"></i>  
14 - {{device.name}}  
15 - </template>  
16 - <ChannelTree :device="device" @sendDevicePush="sendDevicePush"></ChannelTree>  
17 - </el-submenu>  
18 - </el-menu>  
19 - </el-aside>  
20 - <el-container>  
21 - <!-- <LivePlay></LivePlay> -->  
22 - <el-header height="40px" style="text-align: left;font-size: 17px;line-height: 40px;">  
23 - 分屏:  
24 - <i class="el-icon-full-screen btn" :class="{active:spilt==1}" @click="spilt=1"/>  
25 - <i class="el-icon-menu btn" :class="{active:spilt==4}" @click="spilt=4"/>  
26 - <i class="el-icon-s-grid btn" :class="{active:spilt==9}" @click="spilt=9"/>  
27 - </el-header>  
28 - <el-main>  
29 - <div style="width: 100%;height: calc( 100vh - 110px );display: flex;flex-wrap: wrap;background-color: #000;">  
30 - <div v-for="i in spilt" :key="i" class="play-box"  
31 - :style="liveStyle" :class="{redborder:playerIdx == (i-1)}"  
32 - @click="playerIdx = (i-1)"  
33 - >  
34 - <div v-if="!videoUrl[i-1]" style="color: #ffffff;font-size: 30px;font-weight: bold;">{{i}}</div>  
35 - <player v-else :ref="'player'+i" :videoUrl="videoUrl[i-1]" fluent autoplay :height="true"  
36 - :containerId="'player'+i" @screenshot="shot" @destroy="destroy"></player>  
37 - <!-- <player v-else ref="'player'+i" :idx="'player'+i" :visible.sync="showVideoDialog" :videoUrl="videoUrl[i-1]" :height="true" :hasAudio="hasAudio" fluent autoplay live ></player> -->  
38 - </div>  
39 - </div>  
40 - </el-main>  
41 - </el-container> 2 + <div id="devicePosition" style="height: 100%;width: 100%">
  3 + <el-container v-loading="loading" element-loading-text="拼命加载中">
  4 + <el-aside width="300px" style="background-color: #ffffff">
  5 + <div style="text-align: center;padding-top: 20px;">设备列表</div>
  6 + <el-menu v-loading="loading">
  7 + <el-submenu v-for="device in deviceList" :key="device.deviceId" :index="device.deviceId" @click="sendDevicePush(item)">
  8 + <template slot="title" >
  9 + <i class="el-icon-location-outline"></i>
  10 + {{device.name}}
  11 + </template>
  12 + <ChannelTree :device="device" @sendDevicePush="sendDevicePush"></ChannelTree>
  13 + </el-submenu>
  14 + </el-menu>
  15 + </el-aside>
  16 + <el-container>
  17 + <!-- <LivePlay></LivePlay> -->
  18 + <el-header height="40px" style="text-align: left;font-size: 17px;line-height: 40px;">
  19 + 分屏:
  20 + <i class="el-icon-full-screen btn" :class="{active:spilt==1}" @click="spilt=1"/>
  21 + <i class="el-icon-menu btn" :class="{active:spilt==4}" @click="spilt=4"/>
  22 + <i class="el-icon-s-grid btn" :class="{active:spilt==9}" @click="spilt=9"/>
  23 + </el-header>
  24 + <el-main>
  25 + <div style="width: 100%;height: calc( 100vh - 150px );display: flex;flex-wrap: wrap;background-color: #000;">
  26 + <div v-for="i in spilt" :key="i" class="play-box"
  27 + :style="liveStyle" :class="{redborder:playerIdx == (i-1)}"
  28 + @click="playerIdx = (i-1)"
  29 + >
  30 + <div v-if="!videoUrl[i-1]" style="color: #ffffff;font-size: 30px;font-weight: bold;">{{i}}</div>
  31 + <player v-else :ref="'player'+i" :videoUrl="videoUrl[i-1]" fluent autoplay :height="true"
  32 + :containerId="'player'+i" @screenshot="shot" @destroy="destroy"></player>
  33 + <!-- <player v-else ref="'player'+i" :idx="'player'+i" :visible.sync="showVideoDialog" :videoUrl="videoUrl[i-1]" :height="true" :hasAudio="hasAudio" fluent autoplay live ></player> -->
  34 + </div>
  35 + </div>
  36 + </el-main>
42 </el-container> 37 </el-container>
43 </el-container> 38 </el-container>
44 </div> 39 </div>
45 </template> 40 </template>
46 41
47 <script> 42 <script>
48 - import uiHeader from "./UiHeader.vue"; 43 + import uiHeader from "../layout/UiHeader.vue";
49 import player from './dialog/jessibuca.vue' 44 import player from './dialog/jessibuca.vue'
50 import ChannelTree from './channelTree.vue' 45 import ChannelTree from './channelTree.vue'
51 46
web_src/src/components/setting/Media.vue
@@ -79,7 +79,7 @@ @@ -79,7 +79,7 @@
79 </template> 79 </template>
80 80
81 <script> 81 <script>
82 -import uiHeader from '../UiHeader.vue' 82 +import uiHeader from '../../layout/UiHeader.vue'
83 export default { 83 export default {
84 name: "SettingForMedia", 84 name: "SettingForMedia",
85 components: { 85 components: {
web_src/src/components/setting/Sip.vue
@@ -44,7 +44,7 @@ @@ -44,7 +44,7 @@
44 </template> 44 </template>
45 45
46 <script> 46 <script>
47 -import uiHeader from '../UiHeader.vue' 47 +import uiHeader from '../../layout/UiHeader.vue'
48 export default { 48 export default {
49 name: "SettingForSip", 49 name: "SettingForSip",
50 components: { 50 components: {
web_src/src/components/setting/Web.vue
@@ -49,7 +49,7 @@ @@ -49,7 +49,7 @@
49 </template> 49 </template>
50 50
51 <script> 51 <script>
52 -import uiHeader from '../UiHeader.vue' 52 +import uiHeader from '../../layout/UiHeader.vue'
53 export default { 53 export default {
54 name: "SettingForWeb", 54 name: "SettingForWeb",
55 components: { 55 components: {
web_src/src/components/UiHeader.vue renamed to web_src/src/layout/UiHeader.vue
1 <template> 1 <template>
2 - <div id="UiHeader">  
3 - <el-menu router :default-active="activeIndex" menu-trigger="click" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" mode="horizontal">  
4 - <el-menu-item index="/">控制台</el-menu-item>  
5 - <el-menu-item index="/live">实时监控</el-menu-item>  
6 - <el-menu-item index="/deviceList">国标设备</el-menu-item>  
7 - <el-menu-item index="/pushVideoList">推流列表</el-menu-item>  
8 - <el-menu-item index="/streamProxyList">拉流代理</el-menu-item>  
9 - <el-menu-item index="/cloudRecord">云端录像</el-menu-item>  
10 - <el-menu-item index="/mediaServerManger">节点管理</el-menu-item>  
11 - <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item>  
12 - <el-menu-item @click="openDoc">在线文档</el-menu-item>  
13 -<!-- <el-submenu index="/setting">-->  
14 -<!-- <template slot="title">系统设置</template>-->  
15 -<!-- <el-menu-item index="/setting/web">WEB服务</el-menu-item>-->  
16 -<!-- <el-menu-item index="/setting/sip">国标服务</el-menu-item>-->  
17 -<!-- <el-menu-item index="/setting/media">媒体服务</el-menu-item>-->  
18 -<!-- </el-submenu>-->  
19 - <el-switch v-model="alarmNotify" active-text="报警信息推送" style="display: block float: right" @change="alarmNotifyChannge"></el-switch>  
20 -<!-- <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item>-->  
21 - <el-submenu index="" style="float: right;" >  
22 - <template slot="title">欢迎,{{this.$cookies.get("session").username}}</template>  
23 - <el-menu-item @click="changePassword">修改密码</el-menu-item>  
24 - <el-menu-item @click="loginout">注销</el-menu-item>  
25 - </el-submenu>  
26 - </el-menu> 2 + <div id="UiHeader">
  3 + <el-menu router :default-active="activeIndex" menu-trigger="click" background-color="#545c64" text-color="#fff"
  4 + active-text-color="#ffd04b" mode="horizontal">
  5 + <el-menu-item index="/control">控制台</el-menu-item>
  6 + <el-menu-item index="/live">实时监控</el-menu-item>
  7 + <el-menu-item index="/deviceList">国标设备</el-menu-item>
  8 + <el-menu-item index="/pushVideoList">推流列表</el-menu-item>
  9 + <el-menu-item index="/streamProxyList">拉流代理</el-menu-item>
  10 + <el-menu-item index="/cloudRecord">云端录像</el-menu-item>
  11 + <el-menu-item index="/mediaServerManger">节点管理</el-menu-item>
  12 + <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item>
  13 + <el-menu-item @click="openDoc">在线文档</el-menu-item>
  14 + <!-- <el-submenu index="/setting">-->
  15 + <!-- <template slot="title">系统设置</template>-->
  16 + <!-- <el-menu-item index="/setting/web">WEB服务</el-menu-item>-->
  17 + <!-- <el-menu-item index="/setting/sip">国标服务</el-menu-item>-->
  18 + <!-- <el-menu-item index="/setting/media">媒体服务</el-menu-item>-->
  19 + <!-- </el-submenu>-->
  20 + <el-switch v-model="alarmNotify" active-text="报警信息推送" @change="alarmNotifyChannge"></el-switch>
  21 + <!-- <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item>-->
  22 + <el-submenu index="" style="float: right;">
  23 + <template slot="title">欢迎,{{ this.$cookies.get("session").username }}</template>
  24 + <el-menu-item @click="changePassword">修改密码</el-menu-item>
  25 + <el-menu-item @click="loginout">注销</el-menu-item>
  26 + </el-submenu>
  27 + </el-menu>
27 <changePasswordDialog ref="changePasswordDialog"></changePasswordDialog> 28 <changePasswordDialog ref="changePasswordDialog"></changePasswordDialog>
28 - </div> 29 + </div>
29 </template> 30 </template>
30 31
31 <script> 32 <script>
32 33
33 -import changePasswordDialog from './dialog/changePassword.vue' 34 +import changePasswordDialog from '../components/dialog/changePassword.vue'
  35 +
34 export default { 36 export default {
35 - name: "UiHeader",  
36 - components: { Notification, changePasswordDialog },  
37 - data() {  
38 - return {  
39 - alarmNotify: false,  
40 - sseSource: null,  
41 - activeIndex: this.$route.path,  
42 - };  
43 - },  
44 - created(){  
45 - if (this.$route.path.startsWith("/channelList")){  
46 - this.activeIndex = "/deviceList"  
47 - } 37 + name: "UiHeader",
  38 + components: {Notification, changePasswordDialog},
  39 + data() {
  40 + return {
  41 + alarmNotify: false,
  42 + sseSource: null,
  43 + activeIndex: this.$route.path,
  44 + };
  45 + },
  46 + created() {
  47 + if (this.$route.path.startsWith("/channelList")) {
  48 + this.activeIndex = "/deviceList"
  49 + }
48 50
  51 + },
  52 + mounted() {
  53 + window.addEventListener('beforeunload', e => this.beforeunloadHandler(e))
  54 + // window.addEventListener('unload', e => this.unloadHandler(e))
  55 + this.alarmNotify = this.getAlarmSwitchStatus() === "true";
  56 + this.sseControl();
  57 + },
  58 + methods: {
  59 + loginout() {
  60 + this.$axios({
  61 + method: 'get',
  62 + url: "/api/user/logout"
  63 + }).then((res) => {
  64 + // 删除cookie,回到登录页面
  65 + this.$cookies.remove("session");
  66 + this.$router.push('/login');
  67 + this.sseSource.close();
  68 + }).catch((error) => {
  69 + console.error("登出失败")
  70 + console.error(error)
  71 + });
  72 + },
  73 + changePassword() {
  74 + this.$refs.changePasswordDialog.openDialog()
49 }, 75 },
50 - mounted() {  
51 - window.addEventListener('beforeunload', e => this.beforeunloadHandler(e))  
52 - // window.addEventListener('unload', e => this.unloadHandler(e))  
53 - this.alarmNotify = this.getAlarmSwitchStatus() === "true";  
54 - this.sseControl(); 76 + openDoc() {
  77 + console.log(process.env.BASE_API)
  78 + window.open(!!process.env.BASE_API ? process.env.BASE_API + "/doc.html" : "/doc.html")
55 }, 79 },
56 - methods:{  
57 - loginout(){  
58 - this.$axios({  
59 - method: 'get',  
60 - url:"/api/user/logout"  
61 - }).then((res)=> {  
62 - // 删除cookie,回到登录页面  
63 - this.$cookies.remove("session");  
64 - this.$router.push('/login');  
65 - this.sseSource.close();  
66 - }).catch((error)=> {  
67 - console.error("登出失败")  
68 - console.error(error) 80 + beforeunloadHandler() {
  81 + this.sseSource.close();
  82 + },
  83 + alarmNotifyChannge() {
  84 + this.setAlarmSwitchStatus()
  85 + this.sseControl()
  86 + },
  87 + sseControl() {
  88 + let that = this;
  89 + if (this.alarmNotify) {
  90 + console.log("申请SSE推送API调用,浏览器ID: " + this.$browserId);
  91 + this.sseSource = new EventSource('/api/emit?browserId=' + this.$browserId);
  92 + this.sseSource.addEventListener('message', function (evt) {
  93 + that.$notify({
  94 + title: '收到报警信息',
  95 + dangerouslyUseHTMLString: true,
  96 + message: evt.data,
  97 + type: 'warning'
69 }); 98 });
70 - },  
71 - changePassword(){  
72 - this.$refs.changePasswordDialog.openDialog()  
73 - },  
74 - openDoc(){  
75 - console.log(process.env.BASE_API)  
76 - window.open( !!process.env.BASE_API? process.env.BASE_API + "/doc.html": "/doc.html")  
77 - },  
78 - beforeunloadHandler() {  
79 - this.sseSource.close();  
80 - },  
81 - alarmNotifyChannge(){  
82 - this.setAlarmSwitchStatus()  
83 - this.sseControl()  
84 - },  
85 - sseControl() {  
86 - let that = this;  
87 - if (this.alarmNotify) {  
88 - console.log("申请SSE推送API调用,浏览器ID: " + this.$browserId);  
89 - this.sseSource = new EventSource('/api/emit?browserId=' + this.$browserId);  
90 - this.sseSource.addEventListener('message', function(evt) {  
91 - that.$notify({  
92 - title: '收到报警信息',  
93 - dangerouslyUseHTMLString: true,  
94 - message: evt.data,  
95 - type: 'warning'  
96 - });  
97 - console.log("收到信息:" + evt.data);  
98 - });  
99 - this.sseSource.addEventListener('open', function(e) {  
100 - console.log("SSE连接打开.");  
101 - }, false);  
102 - this.sseSource.addEventListener('error', function(e) {  
103 - if (e.target.readyState == EventSource.CLOSED) {  
104 - console.log("SSE连接关闭");  
105 - } else {  
106 - console.log(e.target.readyState);  
107 - }  
108 - }, false);  
109 - } else {  
110 - if (this.sseSource != null) {  
111 - this.sseSource.removeEventListener('open', null);  
112 - this.sseSource.removeEventListener('message', null);  
113 - this.sseSource.removeEventListener('error', null);  
114 - this.sseSource.close();  
115 - }  
116 -  
117 - }  
118 - },  
119 - getAlarmSwitchStatus(){  
120 - if (localStorage.getItem("alarmSwitchStatus") == null) {  
121 - localStorage.setItem("alarmSwitchStatus", false); 99 + console.log("收到信息:" + evt.data);
  100 + });
  101 + this.sseSource.addEventListener('open', function (e) {
  102 + console.log("SSE连接打开.");
  103 + }, false);
  104 + this.sseSource.addEventListener('error', function (e) {
  105 + if (e.target.readyState == EventSource.CLOSED) {
  106 + console.log("SSE连接关闭");
  107 + } else {
  108 + console.log(e.target.readyState);
122 } 109 }
123 - return localStorage.getItem("alarmSwitchStatus");  
124 - },  
125 - setAlarmSwitchStatus(){  
126 - localStorage.setItem("alarmSwitchStatus", this.alarmNotify);  
127 - }  
128 - },  
129 - destroyed() {  
130 - window.removeEventListener('beforeunload', e => this.beforeunloadHandler(e)) 110 + }, false);
  111 + } else {
131 if (this.sseSource != null) { 112 if (this.sseSource != null) {
132 this.sseSource.removeEventListener('open', null); 113 this.sseSource.removeEventListener('open', null);
133 this.sseSource.removeEventListener('message', null); 114 this.sseSource.removeEventListener('message', null);
134 this.sseSource.removeEventListener('error', null); 115 this.sseSource.removeEventListener('error', null);
135 this.sseSource.close(); 116 this.sseSource.close();
136 } 117 }
  118 +
  119 + }
  120 + },
  121 + getAlarmSwitchStatus() {
  122 + if (localStorage.getItem("alarmSwitchStatus") == null) {
  123 + localStorage.setItem("alarmSwitchStatus", false);
  124 + }
  125 + return localStorage.getItem("alarmSwitchStatus");
137 }, 126 },
  127 + setAlarmSwitchStatus() {
  128 + localStorage.setItem("alarmSwitchStatus", this.alarmNotify);
  129 + }
  130 + },
  131 + destroyed() {
  132 + window.removeEventListener('beforeunload', e => this.beforeunloadHandler(e))
  133 + if (this.sseSource != null) {
  134 + this.sseSource.removeEventListener('open', null);
  135 + this.sseSource.removeEventListener('message', null);
  136 + this.sseSource.removeEventListener('error', null);
  137 + this.sseSource.close();
  138 + }
  139 + },
138 140
139 - } 141 +}
140 142
141 </script> 143 </script>
  144 +<style>
  145 +#UiHeader .el-switch__label {
  146 + color: white;
  147 +}
  148 +#UiHeader .el-switch__label.is-active{
  149 + color: #409EFF;
  150 +}
  151 +</style>
web_src/src/layout/index.vue 0 → 100644
  1 +<template>
  2 + <el-container style="height: 100%">
  3 + <el-header>
  4 + <ui-header/>
  5 + </el-header>
  6 + <el-main>
  7 + <el-container>
  8 + <transition name="fade">
  9 + <router-view></router-view>
  10 + </transition>
  11 + </el-container>
  12 + </el-main>
  13 + </el-container>
  14 +</template>
  15 +
  16 +<script>
  17 +import uiHeader from "./UiHeader.vue";
  18 +
  19 +export default {
  20 + name: "index",
  21 + components: {
  22 + uiHeader
  23 + },
  24 +}
  25 +</script>
  26 +<style>
  27 +/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
  28 +::-webkit-scrollbar {
  29 + width: 8px;
  30 + height: 8px;
  31 +}
  32 +
  33 +/*定义滚动条轨道 内阴影+圆角*/
  34 +::-webkit-scrollbar-track {
  35 + border-radius: 4px;
  36 + background-color: #F5F5F5;
  37 +}
  38 +
  39 +/*定义滑块 内阴影+圆角*/
  40 +::-webkit-scrollbar-thumb {
  41 + border-radius: 4px;
  42 + background-color: #c8c8c8;
  43 + box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
  44 + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
  45 +}
  46 +
  47 +/*定义标题栏*/
  48 +.page-header {
  49 + background-color: #FFFFFF;
  50 + margin-bottom: 1rem;
  51 + padding: 0.5rem;
  52 + display: flex;
  53 + justify-content: space-between;
  54 + align-items: center;
  55 +}
  56 +
  57 +.page-title {
  58 + font-weight: bold;
  59 + text-align: left;
  60 +}
  61 +
  62 +.page-header-btn {
  63 + text-align: right;
  64 +}
  65 +</style>
  66 +<style scoped>
  67 +.el-main {
  68 + margin: 0;
  69 +}
  70 +
  71 +.fade-enter {
  72 + visibility: hidden;
  73 + opacity: 0;
  74 +}
  75 +
  76 +.fade-leave-to {
  77 + display: none;
  78 +}
  79 +
  80 +.fade-enter-active,
  81 +.fade-leave-active {
  82 + transition: opacity .5s ease;
  83 +}
  84 +
  85 +.fade-enter-to,
  86 +.fade-leave {
  87 + visibility: visible;
  88 + opacity: 1;
  89 +}
  90 +</style>
web_src/src/router/index.js
1 import Vue from 'vue' 1 import Vue from 'vue'
2 import VueRouter from 'vue-router' 2 import VueRouter from 'vue-router'
  3 +import Layout from "../layout/index.vue"
3 4
4 import control from '../components/control.vue' 5 import control from '../components/control.vue'
5 import deviceList from '../components/DeviceList.vue' 6 import deviceList from '../components/DeviceList.vue'
@@ -32,78 +33,86 @@ export default new VueRouter({ @@ -32,78 +33,86 @@ export default new VueRouter({
32 routes: [ 33 routes: [
33 { 34 {
34 path: '/', 35 path: '/',
35 - component: control,  
36 - },  
37 - {  
38 - path: '/live',  
39 - component: live,  
40 - },  
41 - {  
42 - path: '/deviceList',  
43 - component: deviceList,  
44 - },  
45 - {  
46 - path: '/pushVideoList',  
47 - component: pushVideoList,  
48 - },  
49 - {  
50 - path: '/streamProxyList',  
51 - component: streamProxyList, 36 + name: 'home',
  37 + component: Layout,
  38 + redirect: '/control',
  39 + children: [
  40 + {
  41 + path: '/control',
  42 + component: control,
  43 + },
  44 + {
  45 + path: '/live',
  46 + component: live,
  47 + },
  48 + {
  49 + path: '/deviceList',
  50 + component: deviceList,
  51 + },
  52 + {
  53 + path: '/pushVideoList',
  54 + component: pushVideoList,
  55 + },
  56 + {
  57 + path: '/streamProxyList',
  58 + component: streamProxyList,
  59 + },
  60 + {
  61 + path: '/channelList/:deviceId/:parentChannelId/:count/:page',
  62 + name: 'channelList',
  63 + component: channelList,
  64 + },
  65 + {
  66 + path: '/parentPlatformList/:count/:page',
  67 + name: 'parentPlatformList',
  68 + component: parentPlatformList,
  69 + },
  70 + {
  71 + path: '/devicePosition/:deviceId/:parentChannelId/:count/:page',
  72 + name: 'devicePosition',
  73 + component: devicePosition,
  74 + },
  75 + {
  76 + path: '/cloudRecord',
  77 + name: 'cloudRecord',
  78 + component: cloudRecord,
  79 + },
  80 + {
  81 + path: '/mediaServerManger',
  82 + name: 'mediaServerManger',
  83 + component: mediaServerManger,
  84 + },
  85 + {
  86 + path: '/setting/web',
  87 + name: 'web',
  88 + component: web,
  89 + },
  90 + {
  91 + path: '/setting/sip',
  92 + name: 'sip',
  93 + component: sip,
  94 + },
  95 + {
  96 + path: '/setting/media',
  97 + name: 'media',
  98 + component: media,
  99 + },
  100 + {
  101 + path: '/play/wasm/:url',
  102 + name: 'wasmPlayer',
  103 + component: wasmPlayer,
  104 + },
  105 + {
  106 + path: '/play/rtc/:url',
  107 + name: 'rtcPlayer',
  108 + component: rtcPlayer,
  109 + },
  110 + ]
52 }, 111 },
53 { 112 {
54 path: '/login', 113 path: '/login',
55 name: '登录', 114 name: '登录',
56 component: login, 115 component: login,
57 }, 116 },
58 - {  
59 - path: '/channelList/:deviceId/:parentChannelId/:count/:page',  
60 - name: 'channelList',  
61 - component: channelList,  
62 - },  
63 - {  
64 - path: '/parentPlatformList/:count/:page',  
65 - name: 'parentPlatformList',  
66 - component: parentPlatformList,  
67 - },  
68 - {  
69 - path: '/devicePosition/:deviceId/:parentChannelId/:count/:page',  
70 - name: 'devicePosition',  
71 - component: devicePosition,  
72 - },  
73 - {  
74 - path: '/cloudRecord',  
75 - name: 'cloudRecord',  
76 - component: cloudRecord,  
77 - },  
78 - {  
79 - path: '/mediaServerManger',  
80 - name: 'mediaServerManger',  
81 - component: mediaServerManger,  
82 - },  
83 - {  
84 - path: '/setting/web',  
85 - name: 'web',  
86 - component: web,  
87 - },  
88 - {  
89 - path: '/setting/sip',  
90 - name: 'sip',  
91 - component: sip,  
92 - },  
93 - {  
94 - path: '/setting/media',  
95 - name: 'media',  
96 - component: media,  
97 - },  
98 - {  
99 - path: '/play/wasm/:url',  
100 - name: 'wasmPlayer',  
101 - component: wasmPlayer,  
102 - },  
103 - {  
104 - path: '/play/rtc/:url',  
105 - name: 'rtcPlayer',  
106 - component: rtcPlayer,  
107 - },  
108 ] 117 ]
109 }) 118 })