You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
342 lines
14 KiB
342 lines
14 KiB
<div style="text-align:center;" v-if="ViewModel">{{ViewModel.Name}}</div>
|
|
<div class="row" v-if="ViewModel">
|
|
<div class="col-md-6">
|
|
<canvas id="NodeChart" style="width:100%;height:250px;"></canvas>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<canvas id="NodeChart" style="width:100%;height:250px;"></canvas>
|
|
</div>
|
|
</div>
|
|
<div class="row" v-if="ViewModel">
|
|
<div class="col-md-6">
|
|
<canvas id="NodeChart" style="width:100%;height:250px;"></canvas>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<canvas id="NodeChart" style="width:100%;height:250px;"></canvas>
|
|
</div>
|
|
</div>
|
|
<hr />
|
|
<div class="row" v-if="ViewModel">
|
|
<div class="col-md-6">
|
|
<select class="form-control" id="camera" @change="CameraSelected">
|
|
<option v-for="c in GetCameras()" :value="c.Number">{{c.Name}}</option>
|
|
</select>
|
|
<div style="width:100%;height:265px;margin:0;padding:0;background:#000;">
|
|
<video id="flvPlayer" class="video" muted controls autoplay style="width:100%;max-width:100%;height:100%;"></video>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="box box-solid">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<img src="/images/temperature.png" style="width:48px;height:48px;margin:20px;" />
|
|
</div>
|
|
<div class="col-md-4" style="height:88px;">
|
|
<h3 style="line-height:88px;margin:0;">{{GetData('温度','Description')}}</h3>
|
|
</div>
|
|
<div class="col-md-4" style="height:88px;">
|
|
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">温度:{{GetData('温度','Value') }} {{GetData('温度','Unit')}}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="box box-solid">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<img src="/images/humidity.png" style="width:48px;height:48px;margin:20px;" />
|
|
</div>
|
|
<div class="col-md-4" style="height:88px;">
|
|
<h3 style="line-height:88px;margin:0;">{{GetData('湿度','Description')}}</h3>
|
|
</div>
|
|
<div class="col-md-4" style="height:88px;">
|
|
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">湿度:{{GetData('湿度','Value') }} {{GetData('湿度','Unit')}}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="box box-solid">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<img src="/images/light.png" style="width:48px;height:48px;margin:20px;" />
|
|
</div>
|
|
<div class="col-md-4" style="height:88px;">
|
|
<h3 style="line-height:88px;margin:0;">{{GetDataByTag('前门','光照度','Description')}}</h3>
|
|
</div>
|
|
<div class="col-md-4" style="height:88px;">
|
|
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">前门光照:{{GetDataByTag('前门','光照度','Value') }} {{GetDataByTag('前门','光照度','Unit')}}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="box box-solid">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<img src="/images/light.png" style="width:48px;height:48px;margin:20px;" />
|
|
</div>
|
|
<div class="col-md-4" style="height:88px;">
|
|
<h3 style="line-height:88px;margin:0;">{{GetDataByTag('后门','光照度','Description')}}</h3>
|
|
</div>
|
|
<div class="col-md-4" style="height:88px;">
|
|
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">后门光照:{{GetDataByTag('后门','光照度','Value') }} {{GetDataByTag('后门','光照度','Unit')}}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="box box-solid">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<img src="/images/person.png" style="width:48px;height:48px;margin:20px;" />
|
|
</div>
|
|
<div class="col-md-4" style="height:88px;">
|
|
<img src="/images/warn.png" style="width:36px;height:36px;margin:32px 0 0 0;" v-if="GetDataByTag('前门','状态','Value')==='警报'" />
|
|
</div>
|
|
<div class="col-md-4" style="height:88px;">
|
|
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">前门人体:{{GetDataByTag('前门','状态','Value') }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="box box-solid">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<img src="/images/person.png" style="width:48px;height:48px;margin:20px;" />
|
|
</div>
|
|
<div class="col-md-4" style="height:88px;">
|
|
<img src="/images/warn.png" style="width:36px;height:36px;margin:32px 0 0 0;" v-if="GetDataByTag('后门','状态','Value')==='警报'" />
|
|
</div>
|
|
<div class="col-md-4" style="height:88px;">
|
|
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">后门人体:{{GetDataByTag('后门','状态','Value') }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row" v-if="ViewModel">
|
|
<div class="col-md-6">
|
|
<div class="box box-solid">
|
|
<table class="ptz" v-if="PTZControlSupport()">
|
|
<tr>
|
|
<td><img src="/images/zoomin.png" /></td>
|
|
<td></td>
|
|
<td><img src="/images/up.png" /></td>
|
|
<td></td>
|
|
<td><img src="/images/zoomout.png" /></td>
|
|
</tr>
|
|
<tr>
|
|
<td></td>
|
|
<td><img src="/images/left.png" /></td>
|
|
<td><img src="/images/stop.png" /></td>
|
|
<td><img src="/images/right.png" /></td>
|
|
<td></td>
|
|
</tr>
|
|
<tr>
|
|
<td></td>
|
|
<td></td>
|
|
<td><img src="/images/down.png" /></td>
|
|
<td></td>
|
|
<td></td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="box box-solid btns">
|
|
<div class="row">
|
|
<div class="col-md-6"><button class="btn btn-block btn-primary">一键开</button></div>
|
|
<div class="col-md-6"><button class="btn btn-block btn-primary">一键关</button></div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-3" v-for="scene in ViewModel.Scenes">
|
|
<button class="btn btn-block btn-info">{{scene.Name}}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row" v-if="ViewModel">
|
|
<div class="col-md-6">
|
|
开关
|
|
</div>
|
|
<div class="col-md-6">
|
|
插座
|
|
</div>
|
|
</div>
|
|
<script>
|
|
var flvPlayer;
|
|
var decodedFrames;
|
|
function UpdateChart(id, title, data, labels, colors, type) {
|
|
var ctx = document.getElementById(id).getContext('2d');
|
|
colors = colors || $.map(data, function (item) { return Color16(item); });
|
|
var data = {
|
|
datasets: [{
|
|
label: title,
|
|
data: data,
|
|
backgroundColor: colors
|
|
}],
|
|
labels: labels
|
|
};
|
|
var options = {
|
|
responsive: true,
|
|
legend: {
|
|
position: 'right',
|
|
},
|
|
title: {
|
|
display: true,
|
|
text: title
|
|
},
|
|
animation: {
|
|
duration: 0
|
|
}
|
|
};
|
|
var chart = new Chart(ctx, {
|
|
type: type,
|
|
data: data,
|
|
options: options
|
|
});
|
|
}
|
|
function Color16() {//十六进制颜色随机
|
|
var r = Math.floor(Math.random() * 256);
|
|
var g = Math.floor(Math.random() * 256);
|
|
var b = Math.floor(Math.random() * 256);
|
|
var color = '#' + r.toString(16) + g.toString(16) + b.toString(16);
|
|
return color;
|
|
}
|
|
$('body').on('change', 'input.switch', function (e) {
|
|
if ($(this).is(':checked')) {
|
|
$(this).parent('label').addClass('on');
|
|
$(this).parent('label').removeClass('off');
|
|
} else {
|
|
$(this).parent('label').addClass('off');
|
|
$(this).parent('label').removeClass('on');
|
|
}
|
|
});
|
|
$('body').on('change', '#camera', function (e) {
|
|
UpdateCamera()
|
|
});
|
|
function UpdateCamera() {
|
|
var number = $('#camera').val();
|
|
var device = Enumerable.from(vm.ViewModel.Devices).where(function (o) { return o.Number === number; }).firstOrDefault();
|
|
var url = Enumerable.from(device.Data).where(o => o.Name === '主码流flv').firstOrDefault().Value;
|
|
closePlayer(flvPlayer);
|
|
playFlv(document.getElementById("flvPlayer"), url);
|
|
}
|
|
function playFlv(videoElement, url) {
|
|
try {
|
|
var flvPlayer = flvjs.createPlayer({
|
|
type: 'flv',
|
|
url: url,
|
|
isLive: true,
|
|
cors: true
|
|
}, {
|
|
enableWorker: true,
|
|
enableStashBuffer: false,
|
|
stashInitialSize: 1,
|
|
fixAudioTimestampGap: false
|
|
});
|
|
flvPlayer.attachMediaElement(videoElement);
|
|
flvPlayer.load();
|
|
var timer = setInterval(function () {
|
|
console.log('.');
|
|
if (flvPlayer.statisticsInfo.speed == 0) {
|
|
console.log('reload1');
|
|
clearInterval(timer);
|
|
closePlayer(flvPlayer);
|
|
playFlv(videoElement, url);
|
|
}
|
|
else if (decodedFrames && flvPlayer.statisticsInfo.decodedFrames <= decodedFrames) {
|
|
console.log('reload2');
|
|
clearInterval(timer);
|
|
closePlayer(flvPlayer);
|
|
playFlv(videoElement, url);
|
|
}
|
|
else if (flvPlayer.buffered.end(0) - flvPlayer.currentTime > 1) {
|
|
console.log('reset currentTime');
|
|
flvPlayer.currentTime = flvPlayer.buffered.end(0) - 0.001;
|
|
}
|
|
decodedFrames = flvPlayer.statisticsInfo.decodedFrames;
|
|
}, 10 * 1000);
|
|
} catch (e) {
|
|
console.log(e);
|
|
}
|
|
}
|
|
function closePlayer(flvPlayer) {
|
|
if (flvPlayer != null) {
|
|
flvPlayer.pause();
|
|
flvPlayer.unload();
|
|
flvPlayer.detachMediaElement();
|
|
flvPlayer.destroy();
|
|
flvPlayer = null;
|
|
}
|
|
}
|
|
</script>
|
|
<script>
|
|
var vm = new Vue({
|
|
el: '#template',
|
|
data() {
|
|
return { ViewModel: null }
|
|
},
|
|
mounted() {
|
|
var url = '/Home/GetNode' + '?number=' + new URI().query(true).number;
|
|
$.get(url, function (data) {
|
|
vm.ViewModel = data;
|
|
Vue.nextTick(function () {
|
|
//UpdateChart('NodeChart', '节点', vm.ViewModel.NodeChart.data, vm.ViewModel.NodeChart.labels, null, 'doughnut');
|
|
//UpdateChart('DeviceChart', '设备', vm.ViewModel.DeviceChart.data, vm.ViewModel.DeviceChart.labels, null, 'pie');
|
|
//UpdateChart('EnergyChart', '用电', vm.ViewModel.EnergyChart.data, vm.ViewModel.EnergyChart.labels, null, 'bar');
|
|
UpdateCamera();
|
|
});
|
|
});
|
|
},
|
|
methods: {
|
|
GetData(name, attr) {
|
|
var data = Enumerable
|
|
.from(vm.ViewModel.Devices)
|
|
.selectMany(function (o) { return o.Data; })
|
|
.where(function (o) { return o.Name === name; })
|
|
.firstOrDefault();
|
|
return data == null ? null : data[attr];
|
|
},
|
|
GetDataByTag(tag, name, attr) {
|
|
var data = Enumerable
|
|
.from(vm.ViewModel.Devices)
|
|
.where(function (o) { return o.Tag === tag; })
|
|
.selectMany(function (o) { return o.Data; })
|
|
.where(function (o) { return o.Name === name; })
|
|
.firstOrDefault();
|
|
return data == null ? null : data[attr];
|
|
},
|
|
GetCameras() {
|
|
return Enumerable
|
|
.from(vm.ViewModel.Devices)
|
|
.where(function (o) { return o.Name === '摄像头' })
|
|
.toArray();
|
|
},
|
|
CameraSelected() {
|
|
UpdateCamera();
|
|
},
|
|
PTZControlSupport() {
|
|
return true;
|
|
var number = $('#camera').val();
|
|
var device = Enumerable.from(vm.ViewModel.Devices).where(function (o) { return o.Number === number; }).firstOrDefault();
|
|
var data = Enumerable.from(device.Data).where(o => o.Name === '缩放支持').firstOrDefault().Value;
|
|
return data === '是';
|
|
}
|
|
},
|
|
destroy() {
|
|
closePlayer();
|
|
}
|
|
});
|
|
</script> |