Merge branch 'master' into 重构/1078

# Conflicts:
#	pom.xml
#	src/main/java/com/genersoft/iot/vmp/conf/SpringDocConfig.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/service/impl/DeviceChannelServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
This commit is contained in:
648540858
2024-11-10 15:29:53 +08:00
170 changed files with 4812 additions and 3710 deletions

View File

@@ -10,6 +10,8 @@
"build": "node build/build.js"
},
"dependencies": {
"@babel/runtime": "^7.3.0",
"@femessage/log-viewer": "^1.5.0",
"@liveqing/liveplayer": "^2.7.10",
"@wchbrad/vue-easy-tree": "^1.0.12",
"axios": "^0.24.0",
@@ -21,6 +23,7 @@
"ol": "^6.14.1",
"postcss-pxtorem": "^5.1.1",
"screenfull": "5.1.0",
"strip-ansi": "^7.1.0",
"uuid": "^8.3.2",
"v-charts": "^1.19.0",
"vue": "^2.6.11",

View File

@@ -52,17 +52,17 @@
<el-table-column prop="stream" label="流ID" width="380">
</el-table-column>
<el-table-column label="开始时间">
<template slot-scope="scope">
<template v-slot:default="scope">
{{formatTimeStamp(scope.row.startTime)}}
</template>
</el-table-column>
<el-table-column label="结束时间">
<template slot-scope="scope">
<template v-slot:default="scope">
{{formatTimeStamp(scope.row.endTime)}}
</template>
</el-table-column>
<el-table-column label="时长">
<template slot-scope="scope">
<template v-slot:default="scope">
<el-tag>{{formatTime(scope.row.timeLen)}}</el-tag>
</template>
</el-table-column>
@@ -71,7 +71,7 @@
<el-table-column prop="mediaServerId" label="流媒体">
</el-table-column>
<el-table-column label="操作" width="200" fixed="right">
<template slot-scope="scope">
<template v-slot:default="scope">
<el-button size="medium" icon="el-icon-video-play" type="text" @click="play(scope.row)">播放
</el-button>
<el-button size="medium" icon="el-icon-download" type="text" @click="downloadFile(scope.row)">下载

View File

@@ -28,7 +28,7 @@
<el-table-column prop="deviceId" label="设备编号" min-width="200" >
</el-table-column>
<el-table-column label="地址" min-width="160" >
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag v-if="scope.row.hostAddress" size="medium">{{ scope.row.hostAddress }}</el-tag>
<el-tag v-if="!scope.row.hostAddress" size="medium">未知</el-tag>
@@ -40,7 +40,7 @@
<el-table-column prop="transport" label="信令传输模式" min-width="120" >
</el-table-column>
<el-table-column label="流传输模式" min-width="160" >
<template slot-scope="scope">
<template v-slot:default="scope">
<el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择" style="width: 120px">
<el-option key="UDP" label="UDP" value="UDP"></el-option>
<el-option key="TCP-ACTIVE" label="TCP主动模式" value="TCP-ACTIVE"></el-option>
@@ -51,7 +51,7 @@
<el-table-column prop="channelCount" label="通道数" min-width="120" >
</el-table-column>
<el-table-column label="状态" min-width="120">
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" v-if="scope.row.onLine">在线</el-tag>
<el-tag size="medium" type="info" v-if="!scope.row.onLine">离线</el-tag>
@@ -68,7 +68,7 @@
<!-- </el-table-column>-->
<el-table-column label="操作" min-width="380" fixed="right">
<template slot-scope="scope">
<template v-slot:default="scope">
<el-button type="text" size="medium" v-bind:disabled="scope.row.online==0" icon="el-icon-refresh" @click="refDevice(scope.row)"
@mouseover="getTooltipContent(scope.row.deviceId)">刷新
</el-button>
@@ -80,6 +80,18 @@
<el-button size="medium" icon="el-icon-edit" type="text" @click="edit(scope.row)">编辑</el-button>
<el-divider direction="vertical"></el-divider>
<el-button size="medium" icon="el-icon-delete" type="text" @click="deleteDevice(scope.row)" style="color: #f56c6c">删除</el-button>
<el-divider direction="vertical"></el-divider>
<el-dropdown @command="(command)=>{moreClick(command, scope.row)}">
<el-button size="medium" type="text" >
操作<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="setGuard" v-bind:disabled="!scope.row.onLine">
布防</el-dropdown-item>
<el-dropdown-item command="resetGuard" v-bind:disabled="!scope.row.onLine">
撤防</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
@@ -319,8 +331,60 @@ export default {
}
}).catch( (error)=> {
});
}
},
moreClick: function (command, itemData) {
if (command === "setGuard") {
this.setGuard(itemData)
}else if (command === "resetGuard") {
this.resetGuard(itemData)
}
},
setGuard: function (itemData) {
this.$axios({
method: 'get',
url: `/api/device/control/guard/${itemData.deviceId}/SetGuard`,
}).then( (res)=> {
if (res.data.code === 0) {
this.$message.success({
showClose: true,
message: "布防成功"
})
}else {
this.$message.error({
showClose: true,
message: res.data.msg
})
}
}).catch( (error)=> {
this.$message.error({
showClose: true,
message: error.message
})
});
},
resetGuard: function (itemData) {
this.$axios({
method: 'get',
url: `/api/device/control/guard/${itemData.deviceId}/ResetGuard`,
}).then( (res)=> {
if (res.data.code === 0) {
this.$message.success({
showClose: true,
message: "撤防成功"
})
}else {
this.$message.error({
showClose: true,
message: res.data.msg
})
}
}).catch( (error)=> {
this.$message.error({
showClose: true,
message: error.message
})
});
},
}
};

View File

@@ -30,13 +30,14 @@
</el-aside>
<el-main style="padding-bottom: 10px;">
<div class="playBox" :style="playerStyle">
<div class="playBox" :style="playerBoxStyle">
<player ref="recordVideoPlayer"
:videoUrl="videoUrl"
:error="videoError"
:message="videoError"
:hasAudio="hasAudio"
style="max-height: 100%"
:height="playerHeight"
fluent autoplay live ></player>
</div>
<div class="player-option-box">
@@ -136,10 +137,11 @@
overflow: "auto",
margin: "10px auto 10px auto"
},
playerStyle: {
playerBoxStyle: {
"margin": "0 auto 20px auto",
"height": this.winHeight + "px",
},
playerHeight: this.winHeight,
winHeight: window.innerHeight - 240,
playTime: null,
timeRange: null,
@@ -179,7 +181,7 @@
},
mounted() {
this.recordListStyle.height = this.winHeight + "px";
this.playerStyle["height"] = this.winHeight + "px";
this.playerBoxStyle["height"] = this.winHeight + "px";
this.chooseDate = moment().format('YYYY-MM-DD')
this.dateChange();
window.addEventListener('beforeunload', this.stopPlayRecord)

View File

@@ -168,7 +168,7 @@ export default {
} else {
var exit = await this.deviceGBIdExit(value);
if (exit) {
callback(new Error("设备国标编号已存在"));
callback(new Error("设备国标编号格式错误或已存在"));
} else {
callback();
}
@@ -287,6 +287,18 @@ export default {
});
}
},
deviceGBIdExit: async function (deviceGbId) {
let result = false;
await this.$axios({
method:"get",
url:`/api/platform/exit/${deviceGbId}`
}).then((res)=> {
result = res.data;
}).catch((error)=> {
console.log(error);
});
return result;
},
close: function () {
this.closeEdit()
},

View File

@@ -19,7 +19,7 @@
<el-table-column prop="name" label="名称"></el-table-column>
<el-table-column prop="serverGBId" label="平台编号" min-width="200"></el-table-column>
<el-table-column label="是否启用" min-width="80">
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>
<el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
@@ -27,7 +27,7 @@
</template>
</el-table-column>
<el-table-column label="状态" min-width="80">
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" v-if="scope.row.status">在线</el-tag>
<el-tag size="medium" type="info" v-if="!scope.row.status">离线</el-tag>
@@ -35,7 +35,7 @@
</template>
</el-table-column>
<el-table-column label="地址" min-width="160">
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium">{{ scope.row.serverIp }}:{{ scope.row.serverPort }}</el-tag>
</div>
@@ -45,7 +45,7 @@
<el-table-column prop="transport" label="信令传输模式" min-width="120"></el-table-column>
<el-table-column prop="channelCount" label="通道数" min-width="120"></el-table-column>
<el-table-column label="订阅信息" min-width="120" fixed="right">
<template slot-scope="scope">
<template v-slot:default="scope">
<i v-if="scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅"
class="iconfont icon-gbaojings subscribe-on "></i>
<i v-if="!scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅"
@@ -60,7 +60,7 @@
</el-table-column>
<el-table-column label="操作" min-width="240" fixed="right">
<template slot-scope="scope">
<template v-slot:default="scope">
<el-button size="medium" icon="el-icon-edit" type="text" @click="editPlatform(scope.row)">编辑</el-button>
<el-button size="medium" icon="el-icon-share" type="text" @click="chooseChannel(scope.row)">通道共享
</el-button>

View File

@@ -36,7 +36,7 @@
<el-table-column prop="app" label="流应用名" min-width="120" show-overflow-tooltip/>
<el-table-column prop="stream" label="流ID" min-width="120" show-overflow-tooltip/>
<el-table-column label="流地址" min-width="250" show-overflow-tooltip >
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium">
<i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.srcUrl" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
@@ -47,7 +47,7 @@
</el-table-column>
<el-table-column prop="mediaServerId" label="流媒体" min-width="180" ></el-table-column>
<el-table-column label="代理方式" width="100" >
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
{{scope.row.type === "default"? "默认":"FFMPEG代理"}}
</div>
@@ -56,7 +56,7 @@
<el-table-column prop="gbDeviceId" label="国标编码" min-width="180" show-overflow-tooltip/>
<el-table-column label="拉流状态" min-width="120" >
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" v-if="scope.row.pulling">正在拉流</el-tag>
<el-tag size="medium" type="info" v-if="!scope.row.pulling">尚未拉流</el-tag>
@@ -64,7 +64,7 @@
</template>
</el-table-column>
<el-table-column label="启用" min-width="120" >
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>
<el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
@@ -73,7 +73,7 @@
</el-table-column>
<el-table-column prop="createTime" label="创建时间" min-width="150" show-overflow-tooltip/>
<el-table-column label="操作" width="400" fixed="right">
<template slot-scope="scope">
<template v-slot:default="scope">
<el-button size="medium" icon="el-icon-video-play" type="text" @click="play(scope.row)">播放</el-button>
<el-divider direction="vertical"></el-divider>
<el-button size="medium" icon="el-icon-switch-button" style="color: #f56c6c" type="text" v-if="scope.row.pulling" @click="stopPlay(scope.row)">停止</el-button>

View File

@@ -46,22 +46,28 @@
</el-table-column>
<el-table-column prop="gbName" label="名称" min-width="200">
</el-table-column>
<el-table-column prop="app" label="应用名" min-width="200">
<el-table-column prop="app" label="应用名" min-width="100">
</el-table-column>
<el-table-column prop="stream" label="流ID" min-width="200">
</el-table-column>
<el-table-column label="推流状态" min-width="100">
<template slot-scope="scope">
<template v-slot:default="scope">
<el-tag size="medium" v-if="scope.row.pushing">推流中</el-tag>
<el-tag size="medium" type="info" v-if="!scope.row.pushing">已停止</el-tag>
</template>
</el-table-column>
<el-table-column prop="gbDeviceId" label="国标编码" min-width="200" >
</el-table-column>
<el-table-column label="位置信息" min-width="200">
<template v-slot:default="scope">
<span size="medium" v-if="scope.row.gbLongitude && scope.row.gbLatitude">{{scope.row.gbLongitude}}<br/>{{scope.row.gbLatitude}}</span>
<span size="medium" v-if="!scope.row.gbLongitude || !scope.row.gbLatitude">无</span>
</template>
</el-table-column>
<el-table-column prop="mediaServerId" label="流媒体" min-width="200" >
</el-table-column>
<el-table-column label="开始时间" min-width="200">
<template slot-scope="scope">
<template v-slot:default="scope">
<el-button-group>
{{ scope.row.pushTime == null? "-":scope.row.pushTime }}
</el-button-group>
@@ -70,7 +76,7 @@
<el-table-column label="操作" min-width="360" fixed="right">
<template slot-scope="scope">
<template v-slot:default="scope">
<el-button size="medium" icon="el-icon-video-play"@click="playPush(scope.row)" type="text">播放
</el-button>
<el-divider direction="vertical"></el-divider>
@@ -181,6 +187,12 @@ export default {
if (res.data.code === 0) {
that.total = res.data.data.total;
that.pushList = res.data.data.list;
that.pushList.forEach(e => {
that.$set(e, "location", "");
if (e.gbLongitude && e.gbLatitude) {
that.$set(e, "location", e.gbLongitude + "," + e.gbLatitude);
}
});
}
}).catch(function (error) {

View File

@@ -18,7 +18,7 @@
<el-table-column prop="pushKey" label="pushkey" min-width="160"/>
<el-table-column prop="role.name" label="类型" min-width="160"/>
<el-table-column label="操作" min-width="450" fixed="right">
<template slot-scope="scope">
<template v-slot:default="scope">
<el-button size="medium" icon="el-icon-edit" type="text" @click="edit(scope.row)">修改密码</el-button>
<el-divider direction="vertical"></el-divider>
<el-button size="medium" icon="el-icon-edit" type="text" @click="changePushKey(scope.row)">修改pushkey</el-button>

View File

@@ -68,11 +68,15 @@
</el-image>
</template>
</el-table-column>
<el-table-column prop="subCount" label="子节点数" min-width="100">
</el-table-column>
<!-- <el-table-column prop="subCount" label="子节点数" min-width="100">-->
<!-- </el-table-column>-->
<el-table-column prop="manufacturer" label="厂家" min-width="100">
</el-table-column>
<el-table-column prop="location" label="位置信息" min-width="120">
<el-table-column label="位置信息" min-width="120">
<template v-slot:default="scope">
<span size="medium" v-if="scope.row.longitude && scope.row.latitude">{{scope.row.longitude}}<br/>{{scope.row.latitude}}</span>
<span size="medium" v-if="!scope.row.longitude || !scope.row.latitude"></span>
</template>
</el-table-column>
<el-table-column prop="ptzType" label="云台类型" min-width="100">
<template v-slot:default="scope">
@@ -80,13 +84,13 @@
</template>
</el-table-column>
<el-table-column label="开启音频" min-width="100">
<template slot-scope="scope">
<template v-slot:default="scope">
<el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">
</el-switch>
</template>
</el-table-column>
<el-table-column label="码流类型" min-width="180">
<template slot-scope="scope">
<template v-slot:default="scope">
<el-select size="mini" style="margin-right: 1rem;" @change="channelSubStreamChange(scope.row)" v-model="scope.row.streamIdentification"
placeholder="请选择码流类型" default-first-option >
<el-option label="stream:0(主码流)" value="stream:0"></el-option>
@@ -101,7 +105,7 @@
</template>
</el-table-column>
<el-table-column label="状态" min-width="100">
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" v-if="scope.row.status === 'ON'">在线</el-tag>
<el-tag size="medium" type="info" v-if="scope.row.status !== 'ON'">离线</el-tag>
@@ -109,7 +113,7 @@
</template>
</el-table-column>
<el-table-column label="操作" min-width="340" fixed="right">
<template slot-scope="scope">
<template v-slot:default="scope">
<el-button size="medium" v-bind:disabled="device == null || device.online === 0" icon="el-icon-video-play"
type="text" @click="sendDevicePush(scope.row)">播放
</el-button>
@@ -129,20 +133,25 @@
</el-button>
<el-divider direction="vertical"></el-divider>
<el-button size="medium" icon="el-icon-s-open" type="text"
v-if="scope.row.subCount > 0 || scope.row.parental === 1"
v-if="scope.row.subCount > 0 || scope.row.parental === 1 || scope.row.deviceId.length <= 8"
@click="changeSubchannel(scope.row)">查看
</el-button>
<el-divider v-if="scope.row.subCount > 0 || scope.row.parental === 1" direction="vertical"></el-divider>
<el-divider v-if="scope.row.subCount > 0 || scope.row.parental === 1 || scope.row.deviceId.length <= 8" direction="vertical"></el-divider>
<el-dropdown @command="(command)=>{moreClick(command, scope.row)}">
<el-button size="medium" type="text" >
更多功能<i class="el-icon-arrow-down el-icon--right"></i>
更多<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="records" v-bind:disabled="device == null || device.online === 0">
设备录像</el-dropdown-item>
<el-dropdown-item command="cloudRecords" v-bind:disabled="device == null || device.online === 0" >
云端录像</el-dropdown-item>
<el-dropdown-item command="record" v-bind:disabled="device == null || device.online === 0" >
设备录像控制-开始</el-dropdown-item>
<el-dropdown-item command="stopRecord" v-bind:disabled="device == null || device.online === 0" >
设备录像控制-停止</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
@@ -275,10 +284,6 @@ export default {
that.deviceChannelList = res.data.data.list;
that.deviceChannelList.forEach(e => {
e.ptzType = e.ptzType + "";
that.$set(e, "location", "");
if (e.longitude && e.latitude) {
that.$set(e, "location", e.longitude + "," + e.latitude);
}
});
// 防止出现表格错位
that.$nextTick(() => {
@@ -338,6 +343,10 @@ export default {
this.queryRecords(itemData)
}else if (command === "cloudRecords") {
this.queryCloudRecords(itemData)
}else if (command === "record") {
this.startRecord(itemData)
}else if (command === "stopRecord") {
this.stopRecord(itemData)
}
},
queryRecords: function (itemData) {
@@ -352,6 +361,58 @@ export default {
this.$router.push(`/cloudRecordDetail/rtp/${deviceId}_${channelId}`)
},
startRecord: function (itemData) {
this.$axios({
method: 'get',
url: `/api/device/control/record/${this.deviceId}/Record`,
params: {
channelId: itemData.deviceId
}
}).then( (res)=> {
if (res.data.code === 0) {
this.$message.success({
showClose: true,
message: "开始录像成功"
})
}else {
this.$message.error({
showClose: true,
message: res.data.msg
})
}
}).catch( (error)=> {
this.$message.error({
showClose: true,
message: error.message
})
});
},
stopRecord: function (itemData) {
this.$axios({
method: 'get',
url: `/api/device/control/record/${this.deviceId}/StopRecord`,
params: {
channelId: itemData.deviceId
}
}).then( (res)=> {
if (res.data.code === 0) {
this.$message.success({
showClose: true,
message: "停止录像成功"
})
}else {
this.$message.error({
showClose: true,
message: res.data.msg
})
}
}).catch( (error)=> {
this.$message.error({
showClose: true,
message: error.message
})
});
},
stopDevicePush: function (itemData) {
var that = this;
this.$axios({
@@ -429,10 +490,6 @@ export default {
this.deviceChannelList = res.data.data.list;
this.deviceChannelList.forEach(e => {
e.ptzType = e.ptzType + "";
this.$set(e, "location", "");
if (e.longitude && e.latitude) {
this.$set(e, "location", e.longitude + "," + e.latitude);
}
});
// 防止出现表格错位
this.$nextTick(() => {
@@ -494,8 +551,9 @@ export default {
method: 'post',
url: `/api/device/query/channel/stream/identification/update/`,
params: {
deviceId: this.deviceId,
deviceDbId: this.device.id,
streamIdentification: this.subStream
}
}).then((res)=> {
console.log(JSON.stringify(res));
@@ -513,8 +571,8 @@ export default {
method: 'post',
url: `/api/device/query/channel/stream/identification/update/`,
params: {
deviceId: this.deviceId,
channelId: row.channelId,
deviceDbId: row.deviceDbId,
id: row.id,
streamIdentification: row.streamIdentification
}
}).then(function (res) {

View File

@@ -7,7 +7,9 @@
</el-form-item>
<el-form-item label="编码" >
<el-input v-model="form.gbDeviceId" placeholder="请输入通道编码">
<el-button slot="append" @click="buildDeviceIdCode(form.gbDeviceId)">生成</el-button>
<template v-slot:append>
<el-button @click="buildDeviceIdCode(form.gbDeviceId)">生成</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item label="设备厂商" >
@@ -18,7 +20,11 @@
</el-form-item>
<el-form-item label="行政区域" >
<el-input v-model="form.gbCivilCode" placeholder="请输入行政区域"></el-input>
<el-input v-model="form.gbCivilCode" placeholder="请输入行政区域">
<template v-slot:append>
<el-button @click="chooseCivilCode()">选择</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item label="安装地址" >
@@ -31,7 +37,11 @@
</el-select>
</el-form-item>
<el-form-item label="父节点编码" >
<el-input v-model="form.gbParentId" placeholder="请输入父节点编码"></el-input>
<el-input v-model="form.gbParentId" placeholder="请输入父节点编码或选择所属虚拟组织">
<template v-slot:append>
<el-button @click="chooseGroup()">选择</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item label="设备状态" >
<el-select v-model="form.gbStatus" style="width: 100%" placeholder="请选择设备状态">
@@ -202,16 +212,22 @@
</el-form>
<channelCode ref="channelCode"></channelCode>
<chooseCivilCode ref="chooseCivilCode"></chooseCivilCode>
<chooseGroup ref="chooseGroup"></chooseGroup>
</div>
</template>
<script>
import channelCode from './../dialog/channelCode'
import ChooseCivilCode from "../dialog/chooseCivilCode.vue";
import ChooseGroup from "../dialog/chooseGroup.vue";
export default {
name: "CommonChannelEdit",
props: [ 'id', 'dataForm', 'saveSuccess', 'cancel'],
components: {
ChooseCivilCode,
ChooseGroup,
channelCode,
},
created() {
@@ -360,6 +376,17 @@ export default {
console.log("code22===> " + code)
}, deviceId);
},
chooseCivilCode: function (){
this.$refs.chooseCivilCode.openDialog(code=>{
this.form.gbCivilCode = code;
});
},
chooseGroup: function (){
this.$refs.chooseGroup.openDialog((deviceId, businessGroupId)=>{
this.form.gbBusinessGroupId = businessGroupId;
this.form.gbParentId = deviceId;
});
},
cancelSubmit: function (){
if(this.cancel) {
this.cancel()

View File

@@ -17,8 +17,8 @@
</el-header>
<el-main style="background-color: #ffffff;">
<RegionTree v-if="showRegion" ref="regionTree" :edit="false" :showHeader="false" :clickEvent="treeNodeClickEvent" ></RegionTree>
<GroupTree v-if="!showRegion" ref="groupTree" :edit="false" :showHeader="false" :clickEvent="treeNodeClickEvent" ></GroupTree>
<RegionTree v-if="showRegion" ref="regionTree" :edit="false" :showHeader="false" :hasChannel="true" :clickEvent="treeNodeClickEvent" ></RegionTree>
<GroupTree v-if="!showRegion" ref="groupTree" :edit="false" :showHeader="false" :hasChannel="true" :clickEvent="treeNodeClickEvent" ></GroupTree>
</el-main>
</el-container>
</div>

View File

@@ -1,112 +0,0 @@
<template>
<div id="DeviceTree" style="width: 100%;height: 100%; background-color: #FFFFFF; overflow: auto">
<el-container>
<el-header>设备列表</el-header>
<el-main style="background-color: #ffffff;">
<div class="device-tree-main-box">
<tree
:nodes="nodes"
@onClick="onClick"
@onCheck="onCheck"
@onExpand="onExpand"
@onCreated="handleCreated"
/>
</div>
</el-main>
</el-container>
</div>
</template>
<script>
import DeviceService from "../service/DeviceService.js";
import tree from "vue-giant-tree";
export default {
name: 'DeviceTreeForZtree',
components: {
tree
},
data() {
return {
deviceService: new DeviceService(),
device: null,
nodes:[],
setting: {
callback: {
beforeExpand: this.beforeExpand
},
// async: {
// enable: true,
// type: "get",
// url: `/api/device/query/tree`,
// contentType: "application/json",
// // autoParam: ["pid=parentId"],
// },
check: {
enable: false,
},
edit: {
enable: false,
}
},
defaultProps: {
children: 'children',
label: 'name',
isLeaf: 'isLeaf'
}
};
},
props: ['clickEvent', 'contextMenuEvent'],
mounted() {
this.deviceService.getAllDeviceList((data)=>{
console.log(data)
for (let i = 0; i < data.length; i++) {
console.log(data[i].name)
let node = {
name: data[i].name || data[i].deviceId,
id: data[i].deviceId,
isParent: true,
}
this.nodes.push(node)
}
}, (list)=>{
console.log("设备加载完成")
})
},
methods: {
onClick(evt, treeId, treeNode) {
console.log(evt)
console.log(treeId)
console.log(treeNode)
},
onCheck(evt, treeId, treeNode) {
console.log(evt)
},
beforeExpand(treeId, treeNode) {
console.log(treeId)
console.log(treeNode)
return true;
},
onExpand(evt, treeId, treeNode) {
// console.log(evt)
// console.log(treeId)
// console.log(treeNodes)
},
handleCreated(ztreeObj) {
console.log(ztreeObj)
}
}
}
</script>
<style>
.device-tree-main-box{
text-align: left;
}
.device-online{
color: #252525;
}
.device-offline{
color: #727272;
}
</style>

View File

@@ -4,20 +4,21 @@
<div class="page-title">业务分组</div>
<div class="page-header-btn">
<div style="display: inline;">
<el-input @input="search" style="visibility:hidden; margin-right: 1rem; width: 12rem;" size="mini" placeholder="关键字"
<el-input @input="search" style="visibility:hidden; margin-right: 1rem; width: 12rem;" size="mini"
placeholder="关键字"
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
<el-checkbox v-model="showCode">显示编号</el-checkbox>
</div>
</div>
</div>
<div v-if="showHeader" style="height: 2rem; background-color: #FFFFFF" ></div>
<div v-if="showHeader" style="height: 2rem; background-color: #FFFFFF"></div>
<div>
<vue-easy-tree
class="flow-tree"
ref="veTree"
node-key="treeId"
height="78vh"
:height="treeHeight?treeHeight:'78vh'"
lazy
style="padding: 0 0 2rem 0.5rem"
:load="loadNode"
@@ -27,19 +28,21 @@
@node-contextmenu="contextmenuEventHandler"
@node-click="nodeClickHandler"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span @click.stop v-if="edit">
<el-radio v-if="node.data.type === 0 && node.level > 2" style="margin-right: 0" v-model="chooseId" @input="chooseIdChange(node.data.treeId, node.data.deviceId, node.data.businessGroup)" :label="node.data.deviceId">{{''}}</el-radio>
<template v-slot:default="{ node, data }">
<span class="custom-tree-node">
<span v-if="node.data.type === 0 && chooseId !== node.data.deviceId" style="color: #409EFF" class="iconfont icon-bianzubeifen3"></span>
<span v-if="node.data.type === 0 && chooseId === node.data.deviceId" style="color: #c60135;" class="iconfont icon-bianzubeifen3"></span>
<span v-if="node.data.type === 1 && node.data.status === 'ON'" style="color: #409EFF" class="iconfont icon-shexiangtou2"></span>
<span v-if="node.data.type === 1 && node.data.status !== 'ON'" style="color: #808181" class="iconfont icon-shexiangtou2"></span>
<span style=" padding-left: 1px" v-if="node.data.deviceId !=='' && showCode" :title="node.data.deviceId">{{ node.label }}编号{{ node.data.deviceId }}</span>
<span style=" padding-left: 1px" v-if="node.data.deviceId ==='' || !showCode" :title="node.data.deviceId">{{ node.label }}</span>
</span>
<span v-if="node.data.type === 0" style="color: #409EFF" class="iconfont icon-bianzubeifen3"></span>
<span v-if="node.data.type === 1" style="color: #409EFF" class="iconfont icon-shexiangtou2"></span>
<span style=" padding-left: 1px" v-if="node.data.deviceId !=='' && showCode" :title="node.data.deviceId">{{ node.label }}编号{{ node.data.deviceId }}</span>
<span style=" padding-left: 1px" v-if="node.data.deviceId ==='' || !showCode" :title="node.data.deviceId">{{ node.label }}</span>
</span>
</template>
</vue-easy-tree>
</div>
<groupEdit ref="groupEdit"></groupEdit>
<gbDeviceSelect ref="gbDeviceSelect"></gbDeviceSelect>
<gbChannelSelect ref="gbChannelSelect" dataType="group"></gbChannelSelect>
</div>
</template>
@@ -47,10 +50,12 @@
import VueEasyTree from "@wchbrad/vue-easy-tree";
import groupEdit from './../dialog/groupEdit'
import gbDeviceSelect from './../dialog/GbDeviceSelect'
import GbChannelSelect from "../dialog/GbChannelSelect.vue";
export default {
name: 'DeviceTree',
components: {
GbChannelSelect,
VueEasyTree, groupEdit, gbDeviceSelect
},
data() {
@@ -65,7 +70,7 @@ export default {
treeData: [],
}
},
props: ['edit', 'clickEvent', 'chooseIdChange', 'onChannelChange', 'showHeader'],
props: ['edit','enableAddChannel', 'clickEvent', 'onChannelChange', 'showHeader', 'hasChannel', 'addChannelToGroup', 'treeHeight'],
created() {
},
methods: {
@@ -91,7 +96,8 @@ export default {
url: `/api/group/tree/list`,
params: {
query: this.searchSrt,
parent: node.data.id
parent: node.data.id,
hasChannel: this.hasChannel
}
}).then((res) => {
if (res.data.code === 0) {
@@ -110,85 +116,53 @@ export default {
if (!this.edit) {
return;
}
console.log(node.level)
if (node.data.type === 1) {
data.parentId = node.parent.data.id;
this.$contextmenu({
items: [
{
label: "移除通道",
icon: "el-icon-delete",
disabled: false,
onClick: () => {
console.log(data)
this.$axios({
method: "post",
url: `/api/common/channel/group/delete`,
data: {
channelIds: [data.id]
}
}).then((res) => {
console.log("移除成功")
console.log(node)
if (this.onChannelChange) {
this.onChannelChange()
}
node.parent.loaded = false
node.parent.expand();
}).catch(function (error) {
console.log(error);
});
}
if (node.data.type === 0) {
let menuItem = [
{
label: "刷新节点",
icon: "el-icon-refresh",
disabled: false,
onClick: () => {
this.refreshNode(node);
}
],
event, // 鼠标事件信息
customClass: "custom-class", // 自定义菜单 class
zIndex: 3000, // 菜单样式 z-index
});
} else if (node.data.type === 0) {
this.$contextmenu({
items: [
{
label: "刷新节点",
icon: "el-icon-refresh",
disabled: false,
onClick: () => {
this.refreshNode(node);
}
},
{
label: "新建节点",
icon: "el-icon-plus",
disabled: false,
onClick: () => {
this.addGroup(data.id, node);
}
},
{
label: "编辑节点",
icon: "el-icon-edit",
disabled: node.level === 1,
onClick: () => {
this.editGroup(data, node);
}
},
{
label: "删除节点",
icon: "el-icon-delete",
disabled: node.level === 1,
divided: true,
onClick: () => {
this.$confirm('确定删除?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.removeGroup(data.id, node)
}).catch(() => {
},
{
label: "新建节点",
icon: "el-icon-plus",
disabled: false,
onClick: () => {
this.addGroup(data.id, node);
}
},
{
label: "编辑节点",
icon: "el-icon-edit",
disabled: node.level === 1,
onClick: () => {
this.editGroup(data, node);
}
},
{
label: "删除节点",
icon: "el-icon-delete",
disabled: node.level === 1,
divided: true,
onClick: () => {
this.$confirm('确定删除?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.removeGroup(data.id, node)
}).catch(() => {
});
}
},
});
}
},
]
if (this.enableAddChannel) {
menuItem.push(
{
label: "添加设备",
icon: "el-icon-plus",
@@ -197,35 +171,32 @@ export default {
this.addChannelFormDevice(data.id, node)
}
},
)
menuItem.push(
{
label: "移除设备",
icon: "el-icon-delete",
disabled: node.level <= 2,
divided: true,
onClick: () => {
this.removeChannelFormDevice(data.id, node)
}
},
// {
// label: "导出",
// icon: "el-icon-download",
// disabled: false,
// children: [
// {
// label: "导出到文件",
// onClick: () => {
//
// },
// },
// {
// label: "导出到其他平台",
// onClick: () => {
//
// },
// }
// ]
// },
)
menuItem.push(
{
label: "添加通道",
icon: "el-icon-plus",
disabled: node.level <= 2,
onClick: () => {
this.addChannel(data.id, node)
}
},
)
}
],
this.$contextmenu({
items: menuItem,
event, // 鼠标事件信息
customClass: "custom-class", // 自定义菜单 class
zIndex: 3000, // 菜单样式 z-index
@@ -247,15 +218,15 @@ export default {
node.parent.loaded = false
node.parent.expand();
if (this.onChannelChange) {
this.onChannelChange()
this.onChannelChange(node.data.deviceId)
}
}
}).catch(function (error) {
console.log(error);
console.log(error);
});
},
addChannelFormDevice: function (id, node) {
this.$refs.gbDeviceSelect.openDialog((rows)=>{
this.$refs.gbDeviceSelect.openDialog((rows) => {
let deviceIds = []
for (let i = 0; i < rows.length; i++) {
deviceIds.push(rows[i].id)
@@ -268,26 +239,26 @@ export default {
businessGroup: node.data.businessGroup,
deviceIds: deviceIds,
}
}).then((res)=> {
}).then((res) => {
if (res.data.code === 0) {
this.$message.success({
showClose: true,
message: "保存成功"
})
showClose: true,
message: "保存成功"
})
if (this.onChannelChange) {
this.onChannelChange()
}
console.log(node)
node.loaded = false
node.expand();
}else {
} else {
this.$message.error({
showClose: true,
message: res.data.msg
})
}
this.loading = false
}).catch((error)=> {
}).catch((error) => {
this.$message.error({
showClose: true,
message: error
@@ -297,7 +268,7 @@ export default {
})
},
removeChannelFormDevice: function (id, node) {
this.$refs.gbDeviceSelect.openDialog((rows)=>{
this.$refs.gbDeviceSelect.openDialog((rows) => {
let deviceIds = []
for (let i = 0; i < rows.length; i++) {
deviceIds.push(rows[i].id)
@@ -308,25 +279,25 @@ export default {
data: {
deviceIds: deviceIds,
}
}).then((res)=> {
}).then((res) => {
if (res.data.code === 0) {
this.$message.success({
showClose: true,
message: "保存成功"
})
showClose: true,
message: "保存成功"
})
if (this.onChannelChange) {
this.onChannelChange()
}
node.loaded = false
node.expand();
}else {
} else {
this.$message.error({
showClose: true,
message: res.data.msg
})
}
this.loading = false
}).catch((error)=> {
}).catch((error) => {
this.$message.error({
showClose: true,
message: error
@@ -335,6 +306,13 @@ export default {
});
})
},
addChannel: function (id, node) {
this.$refs.gbChannelSelect.openDialog((data) => {
console.log("选择的数据")
console.log(data)
this.addChannelToGroup(node.data.deviceId, node.data.businessGroup, data)
})
},
refreshNode: function (node) {
console.log(node)
node.loaded = false
@@ -355,10 +333,10 @@ export default {
name: "",
deviceId: "",
civilCode: "",
parentDeviceId: node.level > 2 ? node.data.deviceId:"",
parentDeviceId: node.level > 2 ? node.data.deviceId : "",
parentId: node.data.id,
businessGroup: node.level > 2 ? node.data.businessGroup: node.data.deviceId,
},form => {
businessGroup: node.level > 2 ? node.data.businessGroup : node.data.deviceId,
}, form => {
console.log(node)
node.loaded = false
node.expand();
@@ -366,13 +344,14 @@ export default {
},
editGroup: function (id, node) {
console.log(node)
this.$refs.groupEdit.openDialog(node.data,form => {
this.$refs.groupEdit.openDialog(node.data, form => {
console.log(node)
node.parent.loaded = false
node.parent.expand();
}, id);
},
nodeClickHandler: function (data, node, tree) {
this.chooseId = data.deviceId;
if (this.clickEvent) {
this.clickEvent(data)
}
@@ -401,6 +380,7 @@ export default {
.device-offline {
color: #727272;
}
.custom-tree-node .el-radio__label {
padding-left: 4px !important;
}

View File

@@ -17,7 +17,7 @@
class="flow-tree"
ref="veTree"
node-key="treeId"
height="78vh"
:height="treeHeight?treeHeight:'78vh'"
lazy
style="padding: 0 0 2rem 0.5rem"
:load="loadNode"
@@ -27,19 +27,21 @@
@node-contextmenu="contextmenuEventHandler"
@node-click="nodeClickHandler"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span @click.stop v-if="edit">
<el-radio v-if="node.data.type === 0 && node.level !== 1 " style="margin-right: 0" v-model="chooseId" @input="chooseIdChange(node.data.treeId, node.data.deviceId)" :label="node.data.deviceId">{{''}}</el-radio>
</span>
<span v-if="node.data.type === 0" style="color: #409EFF" class="iconfont icon-bianzubeifen3"></span>
<span v-if="node.data.type === 1" style="color: #409EFF" class="iconfont icon-shexiangtou2"></span>
<template class="custom-tree-node" v-slot:default="{ node, data }">
<span class="custom-tree-node" >
<span v-if="node.data.type === 0 && chooseId !== node.data.deviceId" style="color: #409EFF" class="iconfont icon-bianzubeifen3"></span>
<span v-if="node.data.type === 0 && chooseId === node.data.deviceId" style="color: #c60135;" class="iconfont icon-bianzubeifen3"></span>
<span v-if="node.data.type === 1 && node.data.status === 'ON'" style="color: #409EFF" class="iconfont icon-shexiangtou2"></span>
<span v-if="node.data.type === 1 && node.data.status !== 'ON'" style="color: #808181" class="iconfont icon-shexiangtou2"></span>
<span style=" padding-left: 1px" v-if="node.data.deviceId !=='' && showCode" :title="node.data.deviceId">{{ node.label }}编号{{ node.data.deviceId }}</span>
<span style=" padding-left: 1px" v-if="node.data.deviceId ==='' || !showCode" :title="node.data.deviceId">{{ node.label }}</span>
</span>
</template>
</vue-easy-tree>
</div>
<regionEdit ref="regionEdit"></regionEdit>
<gbDeviceSelect ref="gbDeviceSelect"></gbDeviceSelect>
<GbChannelSelect ref="gbChannelSelect" dataType="civilCode" ></GbChannelSelect>
</div>
</template>
@@ -47,10 +49,12 @@
import VueEasyTree from "@wchbrad/vue-easy-tree";
import regionEdit from './../dialog/regionEdit'
import gbDeviceSelect from './../dialog/GbDeviceSelect'
import GbChannelSelect from "../dialog/GbChannelSelect.vue";
export default {
name: 'DeviceTree',
components: {
GbChannelSelect,
VueEasyTree, regionEdit, gbDeviceSelect
},
data() {
@@ -64,7 +68,7 @@ export default {
treeData: [],
}
},
props: ['edit', 'clickEvent', 'chooseIdChange', 'onChannelChange', 'showHeader'],
props: ['edit', 'enableAddChannel', 'clickEvent', 'onChannelChange', 'showHeader', 'hasChannel', 'addChannelToCivilCode', 'treeHeight'],
created() {
},
methods: {
@@ -90,7 +94,8 @@ export default {
url: `/api/region/tree/list`,
params: {
query: this.searchSrt,
parent: node.data.id
parent: node.data.id,
hasChannel: this.hasChannel
}
}).then((res) => {
if (res.data.code === 0) {
@@ -112,83 +117,52 @@ export default {
return
}
console.log(node.level)
if (node.data.type === 1) {
data.parentId = node.parent.data.id;
this.$contextmenu({
items: [
{
label: "移除通道",
icon: "el-icon-delete",
disabled: false,
onClick: () => {
console.log(data)
this.$axios({
method: "post",
url: `/api/common/channel/region/delete`,
data: {
channelIds: [data.id]
}
}).then((res) => {
console.log("移除成功")
if (this.onChannelChange) {
this.onChannelChange()
}
node.parent.loaded = false
node.parent.expand();
}).catch(function (error) {
console.log(error);
});
}
if (node.data.type === 0) {
let menuItem = [
{
label: "刷新节点",
icon: "el-icon-refresh",
disabled: false,
onClick: () => {
this.refreshNode(node);
}
],
event, // 鼠标事件信息
customClass: "custom-class", // 自定义菜单 class
zIndex: 3000, // 菜单样式 z-index
});
} else if (node.data.type === 0) {
this.$contextmenu({
items: [
{
label: "刷新节点",
icon: "el-icon-refresh",
disabled: false,
onClick: () => {
this.refreshNode(node);
}
},
{
label: "新建节点",
icon: "el-icon-plus",
disabled: false,
onClick: () => {
this.addRegion(data.id, node);
}
},
{
label: "编辑节点",
icon: "el-icon-edit",
disabled: node.level === 1,
onClick: () => {
this.editCatalog(data, node);
}
},
{
label: "删除节点",
icon: "el-icon-delete",
disabled: node.level === 1,
divided: true,
onClick: () => {
this.$confirm('确定删除?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.removeRegion(data.id, node)
}).catch(() => {
},
{
label: "新建节点",
icon: "el-icon-plus",
disabled: false,
onClick: () => {
this.addRegion(data.id, node);
}
},
{
label: "编辑节点",
icon: "el-icon-edit",
disabled: node.level === 1,
onClick: () => {
this.editCatalog(data, node);
}
},
{
label: "删除节点",
icon: "el-icon-delete",
disabled: node.level === 1,
divided: true,
onClick: () => {
this.$confirm('确定删除?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.removeRegion(data.id, node)
}).catch(() => {
});
}
},
});
}
},
]
if (this.enableAddChannel) {
menuItem.push(
{
label: "添加设备",
icon: "el-icon-plus",
@@ -196,36 +170,34 @@ export default {
onClick: () => {
this.addChannelFormDevice(data.id, node)
}
},
}
)
menuItem.push(
{
label: "移除设备",
icon: "el-icon-delete",
disabled: node.level === 1,
divided: true,
onClick: () => {
this.removeChannelFormDevice(data.id, node)
}
},
// {
// label: "导出",
// icon: "el-icon-download",
// disabled: false,
// children: [
// {
// label: "导出到文件",
// onClick: () => {
//
// },
// },
// {
// label: "导出到其他平台",
// onClick: () => {
//
// },
// }
// ]
// },
}
)
menuItem.push(
{
label: "添加通道",
icon: "el-icon-plus",
disabled: node.level === 1,
onClick: () => {
this.addChannel(data.id, node)
}
}
)
}
],
this.$contextmenu({
items: menuItem,
event, // 鼠标事件信息
customClass: "custom-class", // 自定义菜单 class
zIndex: 3000, // 菜单样式 z-index
@@ -310,7 +282,7 @@ export default {
message: "保存成功"
})
if (this.onChannelChange) {
this.onChannelChange()
this.onChannelChange(node.data.deviceId)
}
node.loaded = false
node.expand();
@@ -330,6 +302,13 @@ export default {
});
})
},
addChannel: function (id, node) {
this.$refs.gbChannelSelect.openDialog((data) => {
console.log("选择的数据")
console.log(data)
this.addChannelToCivilCode(node.data.deviceId, data)
})
},
refreshNode: function (node) {
node.loaded = false
node.expand();
@@ -365,14 +344,11 @@ export default {
}, node.data);
},
nodeClickHandler: function (data, node, tree) {
console.log(data)
console.log(node)
this.chooseId = data.deviceId;
if (this.clickEvent) {
this.clickEvent(data)
}
// this.chooseId = data.id;
// this.chooseName = data.name;
// if (this.catalogIdChange)this.catalogIdChange(this.chooseId, this.chooseName);
}
},
destroyed() {

View File

@@ -138,7 +138,7 @@ export default {
supportDblclickFullscreen: false,
timeout: 10,
useMSE: true,
useWCS: location.hostname === "localhost" || location.protocol === "https:",
useWCS: false,
useWebFullScreen: true,
videoBuffer: 0.1,
wasmDecodeErrorReplay: true,

View File

@@ -0,0 +1,185 @@
<template>
<div id="gbChannelSelect" v-loading="getChannelListLoading">
<el-dialog
title="添加国标通道"
width="60%"
top="2rem"
:close-on-click-modal="false"
:visible.sync="showDialog"
:destroy-on-close="true"
append-to-body
@close="close()"
>
<div class="page-header" style="width: 100%">
<div class="page-header-btn" style="width: 100%; text-align: left">
搜索:
<el-input @input="getChannelList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
在线状态:
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="getChannelList" v-model="online" placeholder="请选择"
default-first-option>
<el-option label="全部" value=""></el-option>
<el-option label="在线" value="true"></el-option>
<el-option label="离线" value="false"></el-option>
</el-select>
类型:
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="getChannelList" v-model="channelType" placeholder="请选择"
default-first-option>
<el-option label="全部" value=""></el-option>
<el-option label="国标设备" :value="0"></el-option>
<el-option label="推流设备" :value="1"></el-option>
<el-option label="拉流代理" :value="2"></el-option>
</el-select>
<el-button size="mini" :loading="getChannelListLoading"
@click="getChannelList()">刷新</el-button>
<el-button type="primary" size="mini" style="float: right" @click="onSubmit"> </el-button>
</div>
</div>
<!--通道列表-->
<el-table size="small" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%;"
header-row-class-name="table-header" @selection-change="handleSelectionChange" >
<el-table-column type="selection" width="55" >
</el-table-column>
<el-table-column prop="gbName" label="名称" min-width="180">
</el-table-column>
<el-table-column prop="gbDeviceId" label="编号" min-width="180">
</el-table-column>
<el-table-column prop="gbManufacturer" label="厂家" min-width="100">
</el-table-column>
<el-table-column label="类型" min-width="100">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" effect="plain" v-if="scope.row.gbDeviceDbId">国标设备</el-tag>
<el-tag size="medium" effect="plain" type="success" v-if="scope.row.streamPushId">推流设备</el-tag>
<el-tag size="medium" effect="plain" type="warning" v-if="scope.row.streamProxyId">拉流代理</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="状态" min-width="100">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" v-if="scope.row.gbStatus === 'ON'">在线</el-tag>
<el-tag size="medium" type="info" v-if="scope.row.gbStatus !== 'ON'">离线</el-tag>
</div>
</template>
</el-table-column>
</el-table>
<el-pagination
style="text-align: right"
@size-change="handleSizeChange"
@current-change="currentChange"
:current-page="currentPage"
:page-size="count"
:page-sizes="[10, 25, 35, 50, 200, 1000, 50000]"
layout="total, sizes, prev, pager, next"
:total="total">
</el-pagination>
</el-dialog>
</div>
</template>
<script>
export default {
name: "gbChannelSelect",
props: ['dataType', "selected"],
computed: {},
data() {
return {
showDialog: false,
channelList: [], //设备列表
currentDevice: {}, //当前操作设备对象
searchSrt: "",
online: null,
channelType: "",
videoComponentList: [],
updateLooper: 0, //数据刷新轮训标志
currentDeviceChannelsLenth: 0,
winHeight: 580,
currentPage: 1,
count: 10,
total: 0,
getChannelListLoading: false,
multipleSelection: [],
};
},
methods: {
initData: function () {
this.getChannelList();
},
currentChange: function (val) {
this.currentPage = val;
this.getChannelList();
},
handleSizeChange: function (val) {
this.count = val;
this.getChannelList();
},
handleSelectionChange: function (val){
this.multipleSelection = val;
},
getChannelList: function () {
this.getChannelListLoading = true;
if (this.dataType === "civilCode") {
this.$axios({
method: 'get',
url: `/api/common/channel/civilcode/list`,
params: {
page: this.currentPage,
count: this.count,
channelType: this.channelType,
query: this.searchSrt,
online: this.online,
}
}).then( (res)=> {
if (res.data.code === 0) {
this.total = res.data.data.total;
this.channelList = res.data.data.list;
}
this.getChannelListLoading = false;
}).catch( (error)=> {
console.error(error);
this.getChannelListLoading = false;
});
}else {
this.$axios({
method: 'get',
url: `/api/common/channel/parent/list`,
params: {
page: this.currentPage,
count: this.count,
query: this.searchSrt,
channelType: this.channelType,
online: this.online,
}
}).then( (res)=> {
if (res.data.code === 0) {
this.total = res.data.data.total;
this.channelList = res.data.data.list;
}
this.getChannelListLoading = false;
}).catch( (error)=> {
console.error(error);
this.getChannelListLoading = false;
});
}
},
openDialog: function (callback) {
this.listChangeCallback = callback;
this.showDialog = true;
this.initData();
},
onSubmit: function () {
if (this.listChangeCallback ) {
this.listChangeCallback(this.multipleSelection)
}
this.showDialog = false;
},
close: function () {
this.showDialog = false;
},
}
};
</script>

View File

@@ -40,7 +40,7 @@
<el-table-column prop="manufacturer" label="厂家" min-width="120" >
</el-table-column>
<el-table-column label="地址" min-width="160" >
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag v-if="scope.row.hostAddress" size="medium">{{ scope.row.hostAddress }}</el-tag>
<el-tag v-if="!scope.row.hostAddress" size="medium">未知</el-tag>
@@ -48,7 +48,7 @@
</template>
</el-table-column>
<el-table-column label="状态" min-width="120">
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" v-if="scope.row.onLine">在线</el-tag>
<el-tag size="medium" type="info" v-if="!scope.row.onLine">离线</el-tag>

View File

@@ -4,6 +4,7 @@
width="65rem"
top="2rem"
center
:append-to-body="true"
:close-on-click-modal="false"
:visible.sync="showVideoDialog"
:destroy-on-close="false"

View File

@@ -0,0 +1,65 @@
<template>
<div id="chooseCivilCode" >
<el-dialog
title="选择行政区划"
width="30%"
top="5rem"
:close-on-click-modal="false"
:visible.sync="showDialog"
:destroy-on-close="true"
@close="close()"
>
<RegionTree ref="regionTree" :showHeader=true :edit="true" :enableAddChannel="false" :clickEvent="treeNodeClickEvent"
:onChannelChange="onChannelChange" :treeHeight="'45vh'"></RegionTree>
<el-form>
<el-form-item>
<div style="text-align: right">
<el-button type="primary" @click="onSubmit">保存</el-button>
<el-button @click="close">取消</el-button>
</div>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>
<script>
import RegionTree from "../common/RegionTree.vue";
export default {
name: "chooseCivilCode",
components: {RegionTree},
props: {},
computed: {},
created() {},
data() {
return {
showDialog: false,
endCallback: false,
regionDeviceId: "",
};
},
methods: {
openDialog: function (callback) {
this.showDialog = true;
this.endCallback = callback;
},
onSubmit: function () {
if (this.endCallback) {
this.endCallback(this.regionDeviceId)
}
this.close();
},
close: function () {
this.showDialog = false;
},
treeNodeClickEvent: function (region) {
this.regionDeviceId = region.deviceId;
},
onChannelChange: function (deviceId) {
//
},
},
};
</script>

View File

@@ -0,0 +1,71 @@
<template>
<div id="chooseGroup" >
<el-dialog
title="选择虚拟组织"
width="30%"
top="5rem"
:append-to-body="true"
:close-on-click-modal="false"
:visible.sync="showDialog"
:destroy-on-close="true"
@close="close()"
>
<GroupTree ref="regionTree" :showHeader=true :edit="true" :enableAddChannel="false" :clickEvent="treeNodeClickEvent"
:onChannelChange="onChannelChange" :treeHeight="'45vh'"></GroupTree>
<el-form>
<el-form-item>
<div style="text-align: right">
<el-button type="primary" @click="onSubmit">保存</el-button>
<el-button @click="close">取消</el-button>
</div>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>
<script>
import GroupTree from "../common/GroupTree.vue";
export default {
name: "chooseCivilCode",
components: {GroupTree},
props: {},
computed: {},
created() {},
data() {
return {
showDialog: false,
endCallback: false,
groupDeviceId: "",
businessGroup: "",
};
},
methods: {
openDialog: function (callback) {
this.showDialog = true;
this.endCallback = callback;
},
onSubmit: function () {
if (this.endCallback) {
this.endCallback(this.groupDeviceId, this.businessGroup)
}
this.close();
},
close: function () {
this.showDialog = false;
},
treeNodeClickEvent: function (group) {
if (group.deviceId === "" || group.deviceId === group.businessGroup) {
return
}
this.groupDeviceId = group.deviceId;
this.businessGroup = group.businessGroup;
},
onChannelChange: function (deviceId) {
//
},
},
};
</script>

View File

@@ -0,0 +1,181 @@
<template>
<div id="log" style="width: 100%;height: 100%;">
<div style="width: 100%; height: 40px; display: grid; grid-template-columns: 1fr 1fr">
<div style="text-align: left; line-height: 40px;">
<span style="width: 5vw">过滤: </span>
<el-input size="mini" v-model="filter" placeholder="请输入过滤关键字" style="width: 20vw"></el-input>
</div>
<div style="text-align: right; line-height: 40px;">
<el-button size="mini" icon="el-icon-download" @click="downloadFile()">下载
</el-button>
</div>
</div>
<log-viewer :log="logData" :auto-scroll="true" :height="winHeight"/>
</div>
</template>
<script>
import userService from "./../service/UserService";
import moment from "moment/moment";
import stripAnsi from "strip-ansi";
export default {
name: 'log',
props: [ 'fileUrl', 'remoteUrl', 'loadEnd'],
components: {},
data() {
return {
loading: true,
winHeight: window.innerHeight - 300,
data: [],
filter: "",
logData: "",
websocket: null,
destroyedCallback: null
};
},
watch: {
remoteUrl(newValue) {
console.log(newValue);
this.remoteUrl = newValue;
this.initData();
},
fileUrl(newValue) {
this.fileUrl = newValue;
this.initData();
},
filter(newValue) {
this.filter = newValue;
this.logData = this.getLogData();
},
data(newValue) {
this.data = newValue;
this.logData = this.getLogData();
}
},
created() {
this.data = []
if (this.fileUrl || this.remoteUrl) {
this.initData();
}
},
destroyed() {
console.log('destroyed');
if (this.destroyedCallback) {
this.destroyedCallback()
}
},
methods: {
initData: function () {
this.loading = true
this.data = []
console.log(this.loading)
if (this.fileUrl) {
this.$axios({
method: 'get',
url: this.fileUrl,
}).then((res) => {
let dataArray = res.data.split("\n");
dataArray.forEach(item => {
this.data.push(item);
})
this.loading = false
if (this.loadEnd && typeof this.loadEnd === "function") {
this.loadEnd()
}
}).catch((error) => {
console.log(error);
});
}else if (this.remoteUrl) {
console.log('remoteUrl' + this.remoteUrl);
console.log(window.location.host)
window.websocket = new WebSocket(this.remoteUrl, userService.getToken());
window.websocket.onclose = e => {
console.log(`conn closed: code=${e.code}, reason=${e.reason}, wasClean=${e.wasClean}`)
}
window.websocket.onmessage = e => {
this.loading = false
this.data.push(e.data);
}
window.websocket.onerror = e => {
console.log(`conn err`)
console.error(e)
}
window.websocket.onopen = e => {
console.log(`conn open: ${e}`);
this.destroyedCallback = ()=>{
window.websocket.close()
}
}
}
},
getLogData: function () {
this.loading = true;
if (this.data.length === 0) {
this.loading = false;
return "";
}else {
let result = '';
for (let i = 0; i < this.data.length; i++) {
if (this.filter.length === 0) {
result += this.data[i] + "\r\n"
}else {
if (this.data[i].indexOf(this.filter) > -1) {
result += this.data[i] + "\r\n"
}
}
}
this.loading = false;
return result;
}
},
getLogDataWithOutAnsi: function () {
if (this.data.length === 0) {
return "";
}else {
let result = '';
for (let i = 0; i < this.data.length; i++) {
if (this.filter.length === 0) {
result += stripAnsi(this.data[i]) + "\r\n"
}else {
if (this.data[i].indexOf(this.filter) > -1) {
result += stripAnsi(this.data[i]) + "\r\n"
}
}
}
return result;
}
},
downloadFile() {
let blob = new Blob([this.getLogDataWithOutAnsi()], {
type: "text/plain;charset=utf-8"
});
let reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = (e)=> {
let a = document.createElement('a');
a.download = `wvp-${this.filter}-${moment().format('yyyy-MM-DD')}.log`;
a.href = e.target.result;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
},
}
};
</script>
<style>
.log-loading{
position: absolute;
left: 50%;
top: 50%;
display: inline-block;
text-align: center;
background-color: transparent;
font-size: 20px;
color: rgb(255, 255, 255);
z-index: 1000;
}
</style>

View File

@@ -4,6 +4,7 @@
width="65rem"
top="2rem"
center
:append-to-body="true"
:close-on-click-modal="false"
:visible.sync="showVideoDialog"
:destroy-on-close="false"

View File

@@ -1,115 +1,106 @@
<template>
<div id="shareChannelAdd" style="width: 100%; background-color: #FFFFFF">
<div class="page-header">
<div class="page-header-btn">
<div style="display: inline;">
搜索:
<el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
<div id="shareChannelAdd" style="width: 100%; background-color: #FFFFFF; display: grid; grid-template-columns: 200px auto;">
<el-tabs tab-position="left" style="" v-model="hasShare" @tab-click="search">
<el-tab-pane label="未共享" name="false"></el-tab-pane>
<el-tab-pane label="已共享" name="true"></el-tab-pane>
</el-tabs>
<div>
<div class="page-header">
<div class="page-header-btn" style="width: 100%;">
<div style="display: inline;">
搜索:
<el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
在线状态:
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
default-first-option>
<el-option label="全部" value=""></el-option>
<el-option label="在线" value="true"></el-option>
<el-option label="离线" value="false"></el-option>
</el-select>
类型:
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="channelType" placeholder="请选择"
default-first-option>
<el-option label="全部" value=""></el-option>
<el-option label="国标设备" :value="0"></el-option>
<el-option label="推流设备" :value="1"></el-option>
<el-option label="拉流代理" :value="2"></el-option>
</el-select>
添加状态:
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="hasShare" placeholder="请选择"
default-first-option>
<el-option label="全部" value=""></el-option>
<el-option label="已共享" value="true"></el-option>
<el-option label="未共享" value="false"></el-option>
</el-select>
<el-button v-if="hasShare !=='true'" size="mini" type="primary" @click="add()">
添加
</el-button>
<el-button v-if="hasShare ==='true'" size="mini" type="danger" @click="remove()">
移除
</el-button>
<el-button size="mini" @click="addByDevice()">按设备添加</el-button>
<el-button size="mini" @click="removeByDevice()">按设备移除</el-button>
<el-button size="mini" @click="addAll()">全部添加</el-button>
<el-button size="mini" @click="removeAll()">全部移除</el-button>
<el-button size="mini" @click="getChannelList()">刷新</el-button>
在线状态:
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
default-first-option>
<el-option label="全部" value=""></el-option>
<el-option label="在线" value="true"></el-option>
<el-option label="离线" value="false"></el-option>
</el-select>
类型:
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="channelType" placeholder="请选择"
default-first-option>
<el-option label="全部" value=""></el-option>
<el-option label="国标设备" :value="0"></el-option>
<el-option label="推流设备" :value="1"></el-option>
<el-option label="拉流代理" :value="2"></el-option>
</el-select>
<el-button v-if="hasShare !=='true'" size="mini" type="primary" @click="add()">
添加
</el-button>
<el-button v-if="hasShare ==='true'" size="mini" type="danger" @click="remove()">
移除
</el-button>
<el-button size="mini" v-if="hasShare !=='true'" @click="addByDevice()">按设备添加</el-button>
<el-button size="mini" v-if="hasShare ==='true'" @click="removeByDevice()">按设备移除</el-button>
<el-button size="mini" v-if="hasShare !=='true'" @click="addAll()">全部添加</el-button>
<el-button size="mini" v-if="hasShare ==='true'" @click="removeAll()">全部移除</el-button>
<el-button size="mini" @click="getChannelList()">刷新</el-button>
</div>
</div>
</div>
<el-table size="small" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%;"
header-row-class-name="table-header" @selection-change="handleSelectionChange" >
<el-table-column type="selection" width="55" :selectable="selectable">
</el-table-column>
<el-table-column prop="gbName" label="名称" min-width="180">
</el-table-column>
<el-table-column prop="gbDeviceId" label="编号" min-width="180">
</el-table-column>
<el-table-column v-if="hasShare ==='true'" label="自定义名称" min-width="180">
<template v-slot:default="scope">
<div slot="—" class="name-wrapper">
<el-input size="mini" placeholder="不填按原名称" v-model:value="scope.row.customName"></el-input>
</div>
</template>
</el-table-column>
<el-table-column v-if="hasShare ==='true'" label="自定义编号" min-width="180">
<template v-slot:default="scope">
<div slot="—" class="name-wrapper">
<el-input size="mini" placeholder="不填按原编号" v-model:value="scope.row.customDeviceId"></el-input>
</div>
</template>
</el-table-column>
<el-table-column v-if="hasShare ==='true'" label="" min-width="80">
<template v-slot:default="scope">
<el-button size="mini" type="primary" @click="saveCustom(scope.row)">保存
</el-button>
</template>
</el-table-column>
<el-table-column prop="gbManufacturer" label="厂家" min-width="100">
</el-table-column>
<el-table-column label="类型" min-width="100">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" effect="plain" v-if="scope.row.gbDeviceDbId">国标设备</el-tag>
<el-tag size="medium" effect="plain" type="success" v-if="scope.row.streamPushId">推流设备</el-tag>
<el-tag size="medium" effect="plain" type="warning" v-if="scope.row.streamProxyId">拉流代理</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="状态" min-width="100">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" v-if="scope.row.gbStatus === 'ON'">在线</el-tag>
<el-tag size="medium" type="info" v-if="scope.row.gbStatus !== 'ON'">离线</el-tag>
</div>
</template>
</el-table-column>
</el-table>
<el-pagination
style="text-align: right"
@size-change="handleSizeChange"
@current-change="currentChange"
:current-page="currentPage"
:page-size="count"
:page-sizes="[15, 25, 35, 50]"
layout="total, sizes, prev, pager, next"
:total="total">
</el-pagination>
<gbDeviceSelect ref="gbDeviceSelect"></gbDeviceSelect>
</div>
<el-table size="small" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%;"
header-row-class-name="table-header" @selection-change="handleSelectionChange" >
<el-table-column type="selection" width="55" :selectable="selectable">
</el-table-column>
<el-table-column prop="gbName" label="名称" min-width="180">
</el-table-column>
<el-table-column prop="gbDeviceId" label="编号" min-width="180">
</el-table-column>
<el-table-column v-if="hasShare ==='true'" label="自定义名称" min-width="180">
<template slot-scope="scope">
<div slot="—" class="name-wrapper">
<el-input size="mini" placeholder="不填按原名称" v-model:value="scope.row.customName"></el-input>
</div>
</template>
</el-table-column>
<el-table-column v-if="hasShare ==='true'" label="自定义编号" min-width="180">
<template slot-scope="scope">
<div slot="—" class="name-wrapper">
<el-input size="mini" placeholder="不填按原编号" v-model:value="scope.row.customDeviceId"></el-input>
</div>
</template>
</el-table-column>
<el-table-column v-if="hasShare ==='true'" label="" min-width="80">
<template slot-scope="scope">
<el-button size="mini" type="primary" @click="saveCustom(scope.row)">保存
</el-button>
</template>
</el-table-column>
<el-table-column prop="gbManufacturer" label="厂家" min-width="100">
</el-table-column>
<el-table-column label="类型" min-width="100">
<template slot-scope="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" effect="plain" v-if="scope.row.gbDeviceDbId">国标设备</el-tag>
<el-tag size="medium" effect="plain" type="success" v-if="scope.row.streamPushId">推流设备</el-tag>
<el-tag size="medium" effect="plain" type="warning" v-if="scope.row.streamProxyId">拉流代理</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="状态" min-width="100">
<template slot-scope="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" v-if="scope.row.gbStatus === 'ON'">在线</el-tag>
<el-tag size="medium" type="info" v-if="scope.row.gbStatus !== 'ON'">离线</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="共享状态" min-width="100">
<template slot-scope="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" :title="scope.row.platformId" v-if="scope.row.platformId">已共享</el-tag>
<el-tag size="medium" type="info" v-if="!scope.row.platformId">未共享</el-tag>
</div>
</template>
</el-table-column>
</el-table>
<el-pagination
style="text-align: right"
@size-change="handleSizeChange"
@current-change="currentChange"
:current-page="currentPage"
:page-size="count"
:page-sizes="[15, 25, 35, 50]"
layout="total, sizes, prev, pager, next"
:total="total">
</el-pagination>
<gbDeviceSelect ref="gbDeviceSelect"></gbDeviceSelect>
</div>
</template>

View File

@@ -1,45 +1,54 @@
<template>
<div id="region" style="width: 100%">
<el-container v-loading="loading" >
<el-aside width="400px" >
<GroupTree ref="groupTree" :show-header="true" :edit="true" :clickEvent="treeNodeClickEvent" :chooseIdChange="chooseIdChange" :onChannelChange="getChannelList"></GroupTree>
<el-container v-loading="loading">
<el-aside width="400px">
<GroupTree ref="groupTree" :show-header="true" :edit="true" :clickEvent="treeNodeClickEvent"
:onChannelChange="onChannelChange" :enableAddChannel="true" :addChannelToGroup="addChannelToGroup"></GroupTree>
</el-aside>
<el-main style="padding: 5px;">
<div class="page-header">
<div class="page-title">通道列表</div>
<div class="page-title">
<el-breadcrumb separator="/">
<el-breadcrumb-item v-for="key in regionParents" key="key">{{ key }}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="page-header-btn">
<div style="display: inline;">
<div style="display: inline;">
搜索:
<el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
在线状态:
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online"
placeholder="请选择"
default-first-option>
<el-option label="全部" value=""></el-option>
<el-option label="在线" value="true"></el-option>
<el-option label="离线" value="false"></el-option>
</el-select>
添加状态:
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="hasGroup" placeholder="请选择"
类型:
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="getChannelList"
v-model="channelType" placeholder="请选择"
default-first-option>
<el-option label="全部" value=""></el-option>
<el-option label="已添加" value="true"></el-option>
<el-option label="未添加" value="false"></el-option>
<el-option label="国标设备" :value="0"></el-option>
<el-option label="推流设备" :value="1"></el-option>
<el-option label="拉流代理" :value="2"></el-option>
</el-select>
<el-button v-if="hasGroup !=='true'" size="mini" type="primary" @click="add()">
添加
<el-button size="mini" type="primary" @click="add()">
添加通道
</el-button>
<el-button v-if="hasGroup ==='true'" size="mini" type="danger" @click="remove()">
移除
<el-button v-bind:disabled="multipleSelection.length === 0" size="mini" type="danger" @click="remove()">
移除通道
</el-button>
<el-button icon="el-icon-refresh-right" circle size="mini" @click="getChannelList()"></el-button>
</div>
</div>
</div>
<el-table size="medium" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%"
header-row-class-name="table-header" @selection-change="handleSelectionChange" @row-dblclick="rowDblclick">
<el-table-column type="selection" width="55" :selectable="selectable">
<el-table size="medium" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%"
header-row-class-name="table-header" @selection-change="handleSelectionChange"
@row-dblclick="rowDblclick">
<el-table-column type="selection" width="55" >
</el-table-column>
<el-table-column prop="gbName" label="名称" min-width="180">
</el-table-column>
@@ -48,7 +57,7 @@
<el-table-column prop="gbManufacturer" label="厂家" min-width="100">
</el-table-column>
<el-table-column label="类型" min-width="100">
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" effect="plain" v-if="scope.row.gbDeviceDbId">国标设备</el-tag>
<el-tag size="medium" effect="plain" type="success" v-if="scope.row.streamPushId">推流设备</el-tag>
@@ -57,21 +66,13 @@
</template>
</el-table-column>
<el-table-column label="状态" min-width="100">
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" v-if="scope.row.gbStatus === 'ON'">在线</el-tag>
<el-tag size="medium" type="info" v-if="scope.row.gbStatus !== 'ON'">离线</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="添加状态" min-width="100">
<template slot-scope="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" :title="scope.row.gbParentId" v-if="scope.row.gbParentId">已添加</el-tag>
<el-tag size="medium" type="info" v-if="!scope.row.gbParentId">未添加</el-tag>
</div>
</template>
</el-table-column>
</el-table>
<el-pagination
style="text-align: right"
@@ -85,7 +86,7 @@
</el-pagination>
</el-main>
</el-container>
<GbChannelSelect ref="gbChannelSelect" dataType="group"></GbChannelSelect>
</div>
</template>
@@ -93,10 +94,14 @@
import uiHeader from '../layout/UiHeader.vue'
import DeviceService from "./service/DeviceService";
import GroupTree from "./common/GroupTree.vue";
import GbChannelSelect from "./dialog/GbChannelSelect.vue";
import RegionTree from "./common/RegionTree.vue";
export default {
name: 'channelList',
components: {
RegionTree,
GbChannelSelect,
uiHeader,
GroupTree,
},
@@ -116,6 +121,7 @@ export default {
groupDeviceId: "",
groupId: "",
businessGroup: "",
regionParents: ["请选择虚拟组织"],
multipleSelection: []
};
},
@@ -123,7 +129,8 @@ export default {
created() {
this.initData();
},
destroyed() {},
destroyed() {
},
methods: {
initData: function () {
this.getChannelList();
@@ -139,15 +146,16 @@ export default {
getChannelList: function () {
this.$axios({
method: 'get',
url: `/api/common/channel/list`,
url: `/api/common/channel/parent/list`,
params: {
page: this.currentPage,
count: this.count,
query: this.searchSrt,
online: this.online,
hasGroup: this.hasGroup
channelType: this.channelType,
groupDeviceId: this.groupDeviceId
}
}).then((res)=> {
}).then((res) => {
if (res.data.code === 0) {
this.total = res.data.data.total;
this.channelList = res.data.data.list;
@@ -157,77 +165,67 @@ export default {
})
}
}).catch((error)=> {
}).catch((error) => {
console.log(error);
});
},
handleSelectionChange: function (val){
handleSelectionChange: function (val) {
this.multipleSelection = val;
},
selectable: function (row, rowIndex) {
if (this.hasGroup === "") {
if (row.gbParentId) {
return false
}else {
return true
}
}else {
return true
}
},
rowDblclick: function (row, rowIndex) {
},
add: function (row) {
if (!this.groupDeviceId) {
if (this.regionDeviceId === "") {
this.$message.info({
showClose: true,
message: "请选择左侧行政区划节点"
})
return;
}
let channels = []
for (let i = 0; i < this.multipleSelection.length; i++) {
channels.push(this.multipleSelection[i].gbId)
}
if (channels.length === 0) {
this.$message.info({
showClose: true,
message: "请选择右侧通道"
message: "请选择左侧虚拟组织节点"
})
return;
}
this.$refs.gbChannelSelect.openDialog((data) => {
console.log("选择的数据")
console.log(data)
this.addChannelToGroup(this.groupDeviceId, this.businessGroup, data)
})
},
addChannelToGroup: function (groupDeviceId, businessGroup, data) {
if (data.length === 0) {
return;
}
let channels = []
for (let i = 0; i < data.length; i++) {
channels.push(data[i].gbId)
}
this.loading = true
this.$axios({
method: 'post',
url: `/api/common/channel/group/add`,
data: {
parentId: this.groupDeviceId,
businessGroup: this.businessGroup,
parentId: groupDeviceId,
businessGroup: businessGroup,
channelIds: channels
}
}).then((res)=> {
}).then((res) => {
if (res.data.code === 0) {
this.$message.success({
showClose: true,
message: "保存成功"
})
this.getChannelList()
// 刷新树节点
this.$refs.groupTree.refresh(this.groupId)
}else {
} else {
this.$message.error({
showClose: true,
message: res.data.msg
})
showClose: true,
message: res.data.msg
})
}
this.loading = false
}).catch((error)=> {
}).catch((error) => {
this.$message.error({
showClose: true,
message: error
})
showClose: true,
message: error
})
this.loading = false
});
},
@@ -240,7 +238,7 @@ export default {
if (channels.length === 0) {
this.$message.info({
showClose: true,
message: "请选择右侧通道"
message: "请选择通道"
})
return;
}
@@ -252,7 +250,7 @@ export default {
data: {
channelIds: channels
}
}).then((res)=> {
}).then((res) => {
if (res.data.code === 0) {
this.$message.success({
showClose: true,
@@ -261,18 +259,18 @@ export default {
this.getChannelList()
// 刷新树节点
this.$refs.groupTree.refresh(this.groupDeviceId)
}else {
} else {
this.$message.error({
showClose: true,
message: res.data.msg
})
showClose: true,
message: res.data.msg
})
}
this.loading = false
}).catch((error)=> {
}).catch((error) => {
this.$message.error({
showClose: true,
message: error
})
showClose: true,
message: error
})
this.loading = false
});
},
@@ -288,13 +286,38 @@ export default {
refresh: function () {
this.initData();
},
treeNodeClickEvent: function (device, data, isCatalog) {
treeNodeClickEvent: function (group) {
if (group.deviceId === "" || group.deviceId === group.businessGroup) {
this.channelList = []
this.regionParents = ["请选择虚拟组织"];
return
}
this.groupDeviceId = group.deviceId;
this.businessGroup = group.businessGroup;
this.initData();
// 获取regionDeviceId对应的节点信息
this.$axios({
method: 'get',
url: `/api/group/path`,
params: {
deviceId: this.groupDeviceId,
businessGroup: this.businessGroup,
}
}).then((res) => {
if (res.data.code === 0) {
let path = []
for (let i = 0; i < res.data.data.length; i++) {
path.push(res.data.data[i].name)
}
this.regionParents = path;
}
}).catch((error) => {
console.log(error);
});
},
chooseIdChange: function (id, deviceId, businessGroup) {
this.groupId = id;
this.groupDeviceId = deviceId;
this.businessGroup = businessGroup;
onChannelChange: function (deviceId) {
//
},
}
};

View File

@@ -22,8 +22,8 @@
gridTemplateRows: layout[spiltIndex].rows, gap: '4px', backgroundColor: '#a9a8a8'}">
<div v-for="i in layout[spiltIndex].spilt" :key="i" class="play-box" :class="getPlayerClass(spiltIndex, i)"
@click="playerIdx = (i-1)">
<div v-if="!videoUrl[i-1]" style="color: #ffffff;font-size: 15px;font-weight: bold;">无信号</div>
<player ref="player" v-else :videoUrl="videoUrl[i-1]" fluent autoplay @screenshot="shot"
<div v-if="!videoUrl[i-1]" style="color: #ffffff;font-size: 15px;font-weight: bold;">{{videoTip[i-1]?videoTip[i-1]:"无信号"}}</div>
<player :ref="'player'[i-1]" v-else :videoUrl="videoUrl[i-1]" fluent autoplay @screenshot="shot"
@destroy="destroy"/>
</div>
</div>
@@ -48,6 +48,7 @@ export default {
data() {
return {
videoUrl: [''],
videoTip: [''],
spiltIndex: 2,//分屏
playerIdx: 0,//激活播放器
@@ -168,6 +169,8 @@ export default {
this.save(channelId)
let idxTmp = this.playerIdx
this.setPlayUrl("", idxTmp);
this.$set(this.videoTip, idxTmp, "正在拉流...")
this.$axios({
method: 'get',
url: '/api/common/channel/play',
@@ -184,7 +187,7 @@ export default {
}
this.setPlayUrl(videoUrl, idxTmp);
} else {
this.$message.error(res.data.msg);
this.$set(this.videoTip, idxTmp, "播放失败: " + res.data.msg)
}
}).catch(function (e) {
}).finally(() => {
@@ -200,9 +203,9 @@ export default {
},
checkPlayByParam() {
let channelId = this.$route.query
if (channelId) {
this.sendDevicePush(channelId)
let query = this.$route.query
if (query.channelId) {
this.sendDevicePush(query.channelId)
}
},
shot(e) {

View File

@@ -0,0 +1,71 @@
<template>
<div id="operations" >
<el-container class="container-box">
<el-aside width="200px" style="text-align: left" >
<el-menu :default-active="activeIndex" :height="winHeight" @select="handleSelect">
<el-menu-item index="systemInfo">
<template slot="title"><i class="el-icon-s-home"></i>平台信息</template>
</el-menu-item>
<el-submenu index="log">
<template slot="title"><i class="el-icon-document"></i>日志信息</template>
<el-menu-item index="historyLog">历史日志</el-menu-item>
<el-menu-item index="realTimeLog">运行日志</el-menu-item>
</el-submenu>
<el-submenu index="senior">
<template slot="title"><i class="el-icon-setting"></i>高级维护</template>
<el-menu-item disabled="disabled" index="tcpdump">网络抓包</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<el-main style="background-color: #FFFFFF; margin: 0 20px 20px 20px">
<operationsForRealLog v-if="activeIndex==='realTimeLog'"></operationsForRealLog>
<operationsForHistoryLog v-if="activeIndex==='historyLog'"></operationsForHistoryLog>
<operationsForSystemInfo v-if="activeIndex==='systemInfo'"></operationsForSystemInfo>
</el-main>
</el-container>
</div>
</template>
<script>
import operationsForRealLog from './operationsForRealLog'
import operationsForHistoryLog from './operationsForHistoryLog.vue'
import operationsForSystemInfo from './operationsForSystemInfo.vue'
export default {
name: 'log',
components: {
operationsForRealLog, operationsForHistoryLog, operationsForSystemInfo
},
data() {
return {
loading: false,
winHeight: (window.innerHeight - 170) + "px",
data: [],
filter: "",
activeIndex: "systemInfo"
};
},
created() {
console.log('created');
},
destroyed() {
},
methods: {
handleSelect: function (index) {
this.activeIndex = index;
},
}
};
</script>
<style>
.container-box {
position: absolute;
top: 80px;
width: calc(100% - 20px);
height: calc(100% - 80px);
}
</style>

View File

@@ -0,0 +1,228 @@
<template>
<div id="app" style="width: 100%; background-color: #FFFFFF">
<div class="page-header">
<div class="page-title">
<div>历史日志</div>
</div>
<div class="page-header-btn">
搜索:
<el-input @input="getFileList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
prefix-icon="el-icon-search" v-model="search" clearable></el-input>
开始时间:
<el-date-picker
size="mini"
v-model="startTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
@change="getFileList"
placeholder="选择日期时间">
</el-date-picker>
结束时间:
<el-date-picker
size="mini"
v-model="endTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
@change="getFileList"
placeholder="选择日期时间">
</el-date-picker>
<!-- <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteRecord()">批量删除</el-button>-->
<el-button icon="el-icon-refresh-right" circle size="mini" :loading="loading"
@click="getFileList()"></el-button>
</div>
</div>
<!--日志列表-->
<el-table size="medium" :data="fileList" style="width: 100%" :height="winHeight">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column prop="fileName" label="文件名">
</el-table-column>
<el-table-column prop="fileSize" label="文件大小">
<template v-slot:default="scope">
{{formatFileSize(scope.row.fileSize)}}
</template>
</el-table-column>
<el-table-column label="开始时间">
<template v-slot:default="scope">
{{formatTimeStamp(scope.row.startTime)}}
</template>
</el-table-column>
<el-table-column label="结束时间">
<template v-slot:default="scope">
{{formatTimeStamp(scope.row.endTime)}}
</template>
</el-table-column>
<el-table-column label="操作" width="200" fixed="right">
<template v-slot:default="scope">
<el-button size="medium" icon="el-icon-document" type="text" @click="showLogView(scope.row)">查看
</el-button>
<el-button size="medium" icon="el-icon-download" type="text" @click="downloadFile(scope.row)">下载
</el-button>
<!-- <el-button size="medium" icon="el-icon-delete" type="text" style="color: #f56c6c"-->
<!-- @click="deleteRecord(scope.row)">删除-->
<!-- </el-button>-->
</template>
</el-table-column>
</el-table>
<el-dialog
top="10"
:title="playerTitle"
:visible.sync="showLog"
width="90%">
<operationsFoShowLog ref="recordVideoPlayer" :fileUrl="fileUrl" :loadEnd="loadEnd"></operationsFoShowLog>
</el-dialog>
</div>
</template>
<script>
import uiHeader from '../layout/UiHeader.vue'
import MediaServer from './service/MediaServer'
import operationsFoShowLog from './dialog/operationsFoShowLog.vue'
import moment from 'moment'
export default {
name: 'app',
components: {
uiHeader, operationsFoShowLog
},
data() {
return {
search: '',
startTime: '',
endTime: '',
showLog: false,
playerTitle: '',
fileUrl: '',
playerStyle: {
"margin": "auto",
"margin-bottom": "20px",
"width": window.innerWidth / 2 + "px",
"height": this.winHeight / 2 + "px",
},
mediaServerList: [], // 滅体节点列表
mediaServerId: "", // 媒体服务
mediaServerPath: null, // 媒体服务地址
fileList: [], // 设备列表
chooseRecord: null, // 媒体服务
updateLooper: 0, //数据刷新轮训标志
winHeight: window.innerHeight - 180,
loading: false,
mediaServerObj: new MediaServer(),
};
},
computed: {},
mounted() {
this.initData();
},
destroyed() {
this.$destroy('recordVideoPlayer');
},
methods: {
initData: function () {
this.getFileList();
},
getFileList: function () {
this.$axios({
method: 'get',
url: `/api/log/list`,
params: {
query: this.search,
startTime: this.startTime,
endTime: this.endTime,
}
}).then((res) => {
console.log(res)
if (res.data.code === 0) {
this.fileList = res.data.data;
}
this.loading = false;
}).catch((error) => {
console.log(error);
this.loading = false;
});
},
showLogView(file) {
this.playerTitle = '正在加载日志...'
this.fileUrl = `/api/log/file/${file.fileName}`
this.showLog = true
this.file = file
},
downloadFile(file) {
const link = document.createElement('a');
link.target = "_blank";
link.download = file.fileName;
if (process.env.NODE_ENV === 'development') {
link.href = `/debug/api/log/file/${file.fileName}`
}else {
link.href = `/api/log/file/${file.fileName}`
}
link.click();
},
loadEnd() {
this.playerTitle = this.file.fileName
},
deleteRecord() {
// TODO
let that = this;
this.$axios({
method: 'delete',
url: `/record_proxy/api/record/delete`,
params: {
page: that.currentPage,
count: that.count
}
}).then(function (res) {
console.log(res)
if (res.data.code === 0) {
that.total = res.data.data.total;
that.fileList = res.data.data.list;
}
}).catch(function (error) {
console.log(error);
});
},
formatTime(time) {
const h = parseInt(time / 3600 / 1000)
const minute = parseInt((time - h * 3600 * 1000) / 60 / 1000)
let second = Math.ceil((time - h * 3600 * 1000 - minute * 60 * 1000) / 1000)
if (second < 0) {
second = 0;
}
return (h > 0 ? h + `小时` : '') + (minute > 0 ? minute + '分' : '') + (second > 0 ? second + '秒' : '')
},
formatTimeStamp(time) {
return moment.unix(time / 1000).format('yyyy-MM-DD HH:mm:ss')
},
formatFileSize(fileSize) {
if (fileSize < 1024) {
return fileSize + 'B';
} else if (fileSize < (1024*1024)) {
let temp = fileSize / 1024;
temp = temp.toFixed(2);
return temp + 'KB';
} else if (fileSize < (1024*1024*1024)) {
let temp = fileSize / (1024*1024);
temp = temp.toFixed(2);
return temp + 'MB';
} else {
let temp = fileSize / (1024*1024*1024);
temp = temp.toFixed(2);
return temp + 'GB';
}
}
}
};
</script>
<style>
</style>

View File

@@ -0,0 +1,38 @@
<template>
<div id="log" style="width: 100%;height: 100%;">
<operationsFoShowLog ref="recordVideoPlayer" :remoteUrl="removeUrl" ></operationsFoShowLog>
</div>
</template>
<script>
import operationsFoShowLog from "./dialog/operationsFoShowLog.vue";
export default {
name: 'log',
components: {operationsFoShowLog},
data() {
return {
loading: false,
removeUrl: this.getURl(),
winHeight: window.innerHeight - 220,
};
},
created() {
console.log("removeUrl11 == " + this.removeUrl)
},
methods: {
getURl: function () {
if (process.env.NODE_ENV !== 'development') {
if (location.protocol === "https:") {
return `wss://${window.location.host}/channel/log`;
}else {
return `ws://${window.location.host}/channel/log`
}
}else {
return "ws://localhost:18080/channel/log";
}
},
}
};
</script>

View File

@@ -0,0 +1,54 @@
<template>
<div id="operationsForSystemInfo" style="margin: 40px">
<el-descriptions v-for="(value, key) in systemInfoList" :key="key" :column="2" :loading="loading">
<template slot="title">
<span>{{key}}</span>
</template>
<el-descriptions-item v-for="(childValue, childKey) in value" :key="childKey" >
<template slot="label">
<span>{{childKey}}</span>
</template>
{{ childValue }}
</el-descriptions-item>
</el-descriptions>
</div>
</template>
<script>
export default {
name: 'operationsForSystemInfo',
data() {
return {
loading: false,
winHeight: window.innerHeight - 220,
systemInfoList: {
"测试": {
"qwqew": "1111"
}
},
};
},
created() {
this.initData()
},
methods: {
initData: function () {
this.loading = true;
this.$axios({
method: 'get',
url: `/api/server/info`,
}).then((res) => {
console.log(res)
if (res.data.code === 0) {
this.systemInfoList = res.data.data;
}
this.loading = false;
}).catch((error) => {
console.log(error);
this.loading = false;
});
},
}
};
</script>

View File

@@ -1,45 +1,53 @@
<template>
<div id="region" style="width: 100%">
<el-container v-loading="loading" >
<el-aside width="400px" >
<RegionTree ref="regionTree" :showHeader=true :edit="true" :clickEvent="treeNodeClickEvent" :chooseIdChange="chooseIdChange" :onChannelChange="getChannelList"></RegionTree>
<el-container v-loading="loading">
<el-aside width="400px">
<RegionTree ref="regionTree" :showHeader=true :edit="true" :clickEvent="treeNodeClickEvent"
:onChannelChange="onChannelChange" :enableAddChannel="true" :addChannelToCivilCode="addChannelToCivilCode"></RegionTree>
</el-aside>
<el-main style="padding: 5px;">
<div class="page-header">
<div class="page-title">通道列表</div>
<div class="page-title">
<el-breadcrumb separator="/">
<el-breadcrumb-item v-for="key in regionParents" key="key">{{ key }}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="page-header-btn">
<div style="display: inline;">
<div style="display: inline;">
搜索:
<el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
在线状态:
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online"
placeholder="请选择"
default-first-option>
<el-option label="全部" value=""></el-option>
<el-option label="在线" value="true"></el-option>
<el-option label="离线" value="false"></el-option>
</el-select>
添加状态:
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="hasCivilCode" placeholder="请选择"
类型:
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="getChannelList" v-model="channelType" placeholder="请选择"
default-first-option>
<el-option label="全部" value=""></el-option>
<el-option label="已添加" value="true"></el-option>
<el-option label="未添加" value="false"></el-option>
<el-option label="国标设备" :value="0"></el-option>
<el-option label="推流设备" :value="1"></el-option>
<el-option label="拉流代理" :value="2"></el-option>
</el-select>
<el-button v-if="hasCivilCode !=='true'" size="mini" type="primary" @click="add()">
添加
<el-button size="mini" type="primary" @click="add()">
添加通道
</el-button>
<el-button v-if="hasCivilCode ==='true'" size="mini" type="danger" @click="remove()">
移除
<el-button v-bind:disabled="multipleSelection.length === 0" size="mini" type="danger" @click="remove()">
移除通道
</el-button>
<el-button icon="el-icon-refresh-right" circle size="mini" @click="getChannelList()"></el-button>
</div>
</div>
</div>
<el-table size="medium" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%"
header-row-class-name="table-header" @selection-change="handleSelectionChange" @row-dblclick="rowDblclick">
<el-table-column type="selection" width="55" :selectable="selectable">
<el-table size="medium" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%"
header-row-class-name="table-header" @selection-change="handleSelectionChange"
@row-dblclick="rowDblclick">
<el-table-column type="selection" width="55">
</el-table-column>
<el-table-column prop="gbName" label="名称" min-width="180">
</el-table-column>
@@ -48,7 +56,7 @@
<el-table-column prop="gbManufacturer" label="厂家" min-width="100">
</el-table-column>
<el-table-column label="类型" min-width="100">
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" effect="plain" v-if="scope.row.gbDeviceDbId">国标设备</el-tag>
<el-tag size="medium" effect="plain" type="success" v-if="scope.row.streamPushId">推流设备</el-tag>
@@ -57,21 +65,13 @@
</template>
</el-table-column>
<el-table-column label="状态" min-width="100">
<template slot-scope="scope">
<template v-slot:default="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" v-if="scope.row.gbStatus === 'ON'">在线</el-tag>
<el-tag size="medium" type="info" v-if="scope.row.gbStatus !== 'ON'">离线</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="添加状态" min-width="100">
<template slot-scope="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" :title="scope.row.gbCivilCode" v-if="scope.row.gbCivilCode">已添加</el-tag>
<el-tag size="medium" type="info" v-if="!scope.row.gbCivilCode">未添加</el-tag>
</div>
</template>
</el-table-column>
</el-table>
<el-pagination
style="text-align: right"
@@ -85,7 +85,7 @@
</el-pagination>
</el-main>
</el-container>
<GbChannelSelect ref="gbChannelSelect" dataType="civilCode"></GbChannelSelect>
</div>
</template>
@@ -93,10 +93,12 @@
import uiHeader from '../layout/UiHeader.vue'
import DeviceService from "./service/DeviceService";
import RegionTree from "./common/RegionTree.vue";
import GbChannelSelect from "./dialog/GbChannelSelect.vue";
export default {
name: 'channelList',
components: {
GbChannelSelect,
uiHeader,
RegionTree,
},
@@ -106,7 +108,6 @@ export default {
searchSrt: "",
channelType: "",
online: "",
hasCivilCode: "false",
winHeight: window.innerHeight - 180,
currentPage: 1,
count: 15,
@@ -115,6 +116,7 @@ export default {
loadSnap: {},
regionId: "",
regionDeviceId: "",
regionParents: ["请选择行政区划"],
multipleSelection: []
};
},
@@ -122,7 +124,8 @@ export default {
created() {
this.initData();
},
destroyed() {},
destroyed() {
},
methods: {
initData: function () {
this.getChannelList();
@@ -138,15 +141,16 @@ export default {
getChannelList: function () {
this.$axios({
method: 'get',
url: `/api/common/channel/list`,
url: `/api/common/channel/civilcode/list`,
params: {
page: this.currentPage,
count: this.count,
query: this.searchSrt,
online: this.online,
hasCivilCode: this.hasCivilCode
channelType: this.channelType,
civilCode: this.regionDeviceId
}
}).then((res)=> {
}).then((res) => {
if (res.data.code === 0) {
this.total = res.data.data.total;
this.channelList = res.data.data.list;
@@ -156,48 +160,39 @@ export default {
})
}
}).catch((error)=> {
}).catch((error) => {
console.log(error);
});
},
handleSelectionChange: function (val){
handleSelectionChange: function (val) {
this.multipleSelection = val;
},
selectable: function (row, rowIndex) {
if (this.hasCivilCode === "") {
if (row.gbCivilCode) {
return false
}else {
return true
}
}else {
return true
}
},
rowDblclick: function (row, rowIndex) {
// if (row.gbCivilCode) {
// this.$refs.regionTree.refresh(row.gbCivilCode)
// }
},
add: function (row) {
if (!this.regionDeviceId) {
if (this.regionDeviceId === "") {
this.$message.info({
showClose: true,
message: "请选择左侧行政区划节点"
message: "请选择左侧行政区划"
})
return;
}
this.$refs.gbChannelSelect.openDialog((data) => {
console.log("选择的数据")
console.log(data)
this.addChannelToCivilCode(this.regionDeviceId, data)
})
},
addChannelToCivilCode: function (regionDeviceId, data) {
if (data.length === 0) {
return;
}
let channels = []
for (let i = 0; i < this.multipleSelection.length; i++) {
channels.push(this.multipleSelection[i].gbId)
}
if (channels.length === 0) {
this.$message.info({
showClose: true,
message: "请选择右侧通道"
})
return;
for (let i = 0; i < data.length; i++) {
channels.push(data[i].gbId)
}
this.loading = true
@@ -205,30 +200,28 @@ export default {
method: 'post',
url: `/api/common/channel/region/add`,
data: {
civilCode: this.regionDeviceId,
civilCode: regionDeviceId,
channelIds: channels
}
}).then((res)=> {
}).then((res) => {
if (res.data.code === 0) {
this.$message.success({
showClose: true,
message: "保存成功"
})
this.getChannelList()
// 刷新树节点
this.$refs.regionTree.refresh(this.regionId)
}else {
} else {
this.$message.error({
showClose: true,
message: res.data.msg
})
showClose: true,
message: res.data.msg
})
}
this.loading = false
}).catch((error)=> {
}).catch((error) => {
this.$message.error({
showClose: true,
message: error
})
showClose: true,
message: error
})
this.loading = false
});
},
@@ -240,7 +233,7 @@ export default {
if (channels.length === 0) {
this.$message.info({
showClose: true,
message: "请选择右侧通道"
message: "请选择通道"
})
return;
}
@@ -252,7 +245,7 @@ export default {
data: {
channelIds: channels
}
}).then((res)=> {
}).then((res) => {
if (res.data.code === 0) {
this.$message.success({
showClose: true,
@@ -261,18 +254,18 @@ export default {
this.getChannelList()
// 刷新树节点
this.$refs.regionTree.refresh(this.regionId)
}else {
} else {
this.$message.error({
showClose: true,
message: res.data.msg
})
showClose: true,
message: res.data.msg
})
}
this.loading = false
}).catch((error)=> {
}).catch((error) => {
this.$message.error({
showClose: true,
message: error
})
showClose: true,
message: error
})
this.loading = false
});
},
@@ -288,67 +281,39 @@ export default {
refresh: function () {
this.initData();
},
treeNodeClickEvent: function (device, data, isCatalog) {
treeNodeClickEvent: function (region) {
this.regionDeviceId = region.deviceId;
if (region.deviceId === "") {
this.channelList = []
this.regionParents = ["请选择行政区划"];
}
this.initData();
// 获取regionDeviceId对应的节点信息
this.$axios({
method: 'get',
url: `/api/region/path`,
params: {
deviceId: this.regionDeviceId,
}
}).then((res) => {
if (res.data.code === 0) {
let path = []
for (let i = 0; i < res.data.data.length; i++) {
path.push(res.data.data[i].name)
}
this.regionParents = path;
}
}).catch((error) => {
console.log(error);
});
},
chooseIdChange: function (id, deviceId) {
this.regionDeviceId = deviceId;
this.regionId = id;
gbChannelSelectEnd: function (selectedData) {
console.log(selectedData);
},
onChannelChange: function (deviceId) {
//
},
}
};
</script>
<style>
.videoList {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
}
.video-item {
position: relative;
width: 15rem;
height: 10rem;
margin-right: 1rem;
background-color: #000000;
}
.video-item-img {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
width: 100%;
height: 100%;
}
.video-item-img:after {
content: "";
display: inline-block;
position: absolute;
z-index: 2;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
width: 3rem;
height: 3rem;
background-image: url("../assets/loading.png");
background-size: cover;
background-color: #000000;
}
.video-item-title {
position: absolute;
bottom: 0;
color: #000000;
background-color: #ffffff;
line-height: 1.5rem;
padding: 0.3rem;
width: 14.4rem;
}
</style>

View File

@@ -20,6 +20,7 @@
<el-menu-item index="/mediaServerManger">节点管理</el-menu-item>
<el-menu-item index="/platformList/15/1">国标级联</el-menu-item>
<el-menu-item v-if="editUser" index="/userManager">用户管理</el-menu-item>
<el-menu-item index="/operations">运维中心</el-menu-item>
<!-- <el-submenu index="/setting">-->
<!-- <template slot="title">系统设置</template>-->
@@ -113,17 +114,25 @@ export default {
let that = this;
if (this.alarmNotify) {
console.log("申请SSE推送API调用浏览器ID: " + this.$browserId);
this.sseSource = new EventSource('/api/emit?browserId=' + this.$browserId);
let url = (process.env.NODE_ENV === 'development' ? "debug" : "") + 'api/emit?browserId=' + this.$browserId
this.sseSource = new EventSource(url);
this.sseSource.addEventListener('message', function (evt) {
console.log("收到信息:" + evt.data);
let data = JSON.parse(evt.data)
that.$notify({
title: '报警信息',
dangerouslyUseHTMLString: true,
message: evt.data,
message: `<strong>设备名称:</strong> <i> ${data.deviceName}</i>` +
`<br><strong>设备编号:</strong> <i>${ data.deviceId}</i>` +
`<br><strong>通道编号:</strong> <i>${ data.channelId}</i>` +
`<br><strong>报警级别:</strong> <i>${ data.alarmPriorityDescription}</i>` +
`<br><strong>报警方式:</strong> <i>${ data.alarmMethodDescription}</i>` +
`<br><strong>报警类型:</strong> <i>${ data.alarmTypeDescription}</i>` +
`<br><strong>报警时间:</strong> <i>${ data.alarmTime}</i>`,
type: 'warning',
position: 'bottom-right',
duration: 3000
duration: 5000
});
console.log("收到信息:" + evt.data);
});
this.sseSource.addEventListener('open', function (e) {
console.log("SSE连接打开.");

View File

@@ -6,6 +6,7 @@ import router from './router/index.js';
import axios from 'axios';
import VueCookies from 'vue-cookies';
import VCharts from 'v-charts';
import logViewer from '@femessage/log-viewer';
import VueClipboard from 'vue-clipboard2';
import Fingerprint2 from 'fingerprintjs2';
@@ -40,6 +41,7 @@ Vue.use(VueClipboards);
Vue.prototype.$notify = Notification;
Vue.use(Contextmenu);
Vue.use(VCharts);
Vue.use(logViewer);
axios.defaults.baseURL = (process.env.NODE_ENV === 'development') ? process.env.BASE_API : (window.baseUrl ? window.baseUrl : "");
axios.defaults.withCredentials = true;

View File

@@ -30,6 +30,7 @@ import wasmPlayer from '../components/common/jessibuca.vue'
import rtcPlayer from '../components/dialog/rtcPlayer.vue'
import region from '../components/region.vue'
import group from '../components/group.vue'
import operations from '../components/operations.vue'
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
@@ -184,8 +185,11 @@ export default new VueRouter({
path: '/channel/group',
name: 'group',
component: group,
}
,
},
{
path: '/operations',
component: operations,
},
]
},
{