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.
250 lines
14 KiB
250 lines
14 KiB
@model Device
|
|
@{
|
|
Layout = null;
|
|
HtmlTitle = Model.Name;
|
|
var isNode = this.ViewContext.ActionDescriptor.DisplayName.Contains("IoTNode");
|
|
}
|
|
@functions{
|
|
public string GetClass(string value)
|
|
{
|
|
var time = ViewBag.time as string;
|
|
if (time != null && time == value)
|
|
{
|
|
return "button-active";
|
|
}
|
|
return "";
|
|
}
|
|
}
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>@HtmlTitle-设备详情</title>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui, viewport-fit=cover">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="theme-color" content="#2196f3">
|
|
<link rel="stylesheet" href="~/lib/framework7/css/framework7.bundle.min.css">
|
|
<link rel="stylesheet" href="~/lib/font-awesome/css/font-awesome.min.css">
|
|
<link rel="stylesheet" href="~/css/iot.css">
|
|
</head>
|
|
<body>
|
|
<div id="app">
|
|
<div class="view view-main view-init">
|
|
<div class="page">
|
|
<div class="navbar">
|
|
<div class="navbar-inner sliding">
|
|
<div class="left">
|
|
<a href="/Device?id=@Model.NodeId" class="link external" data-panel="left">设备列表</a>
|
|
</div>
|
|
<div class="title">{{model.Name}}-设备详情</div>
|
|
<div class="right">
|
|
<a href="javascript: ;" id="volumeup"><i class="fa fa-volume-up"></i></a>
|
|
<a href="javascript: ;" id="volumeoff"><i class="fa fa-volume-off"></i></a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="page-content">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<div class="left">
|
|
<img style="display:inline;height:1em;" :src="'/iot/'+model.Icon+'.png'" />{{model.DisplayName}}
|
|
<i :class="model.IsOnline?'fa fa-toggle-on':'fa fa-toggle-off'" :style="model.IsOnline?'color:green;':'color:red;'"></i>
|
|
</div>
|
|
<div class="right">
|
|
</div>
|
|
</div>
|
|
<div class="card-content">
|
|
<div class="block-title">设备数据</div>
|
|
<div class="list">
|
|
<ul>
|
|
<li v-for="data in model.Data">
|
|
<div class="item-content" v-if="data.Name!='hidden'">
|
|
<div :class="'item-media'+' '+data.Key"><i class="icon icon-f7"></i></div>
|
|
<div class="item-inner">
|
|
<div class="item-title">{{data.Name}}</div>
|
|
<div class="item-after">{{data.Value}} {{data.Unit}} {{data.Description}}</div>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div id="video-container" class="card-content" v-if="model.Name=='摄像头'">
|
|
</div>
|
|
<div class="card-content" v-if="isAdmin">
|
|
<div class="block-title">设备控制</div>
|
|
<div class="block">
|
|
<div class="row">
|
|
<div class="col" v-for="api in _.orderBy(model.Apis,['Command'])">
|
|
<form method="get" action="/Command/Exec">
|
|
<input type="hidden" name="cmd" :value="api.Command" />
|
|
<input type="hidden" name="node" :value="model.Node.Number" />
|
|
<input type="hidden" name="id" :value="model.Id" />
|
|
<div class="row">
|
|
<template v-for="parameter in api.Parameters">
|
|
<template v-if="parameter.Name!='hidden'">
|
|
<template v-if="isSelect(model,parameter.Name)">
|
|
<div class="col">
|
|
<select :name="parameter.Name" style="height:29px;" data-val="true" data-val-required="请选择">
|
|
<option value="">请选择</option>
|
|
<option v-for="option in getSelect(model,parameter.Name)" :value="option.value">{{option.text}}</option>
|
|
</select>
|
|
<span class="field-validation-valid text-danger" :data-valmsg-for="parameter.Name" data-valmsg-replace="true"> </span>
|
|
</div>
|
|
</template>
|
|
<template v-else>
|
|
<div class="col">
|
|
<template v-if="parameter.Minimum||parameter.Maximnu">
|
|
<input :name="parameter.Name" :value="getData(model,parameter.Name)" data-val="true" data-val-required="请输入"
|
|
data-val-number="必须输入数字" :data-val-range="'范围:'+parameter.Minimum+'~'+parameter.Maximnu" :data-val-range-min="parameter.Minimum" :data-val-range-max="parameter.Maximnu"
|
|
style="height:29px;" type="text" :placeholder="'请输入'+parameter.Description" />
|
|
</template>
|
|
<template v-else>
|
|
<input :name="parameter.Name" :value="getData(model,parameter.Name)" data-val="true" data-val-required="请输入"
|
|
style="height:29px;" type="text" :placeholder="'请输入'+parameter.Description" />
|
|
</template>
|
|
<span class="field-validation-valid text-danger" :data-valmsg-for="parameter.Name" data-valmsg-replace="true"> </span>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
</template>
|
|
<div class="col">
|
|
<button class="button button-fill button-outline" type="submit">{{api.Name}}</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@if (!isNode && Model.Data.Any(o => o.Type == "Int" || o.Type == "Float"))
|
|
{
|
|
var list = Model.Data.Where(o => o.Type == "Int" || o.Type == "Float").OrderBy(o => o.Key).ToList();
|
|
<div class="block-title">数据统计:</div>
|
|
<div class="block">
|
|
<p class="segmented segmented-raised">
|
|
<a href="@Url.Action()" class="link external button @GetClass("10m")">10分钟</a>
|
|
<a href="@Url.Action(null,new {time="1h" })" class="link external button @GetClass("1h")">1小时</a>
|
|
<a href="@Url.Action(null,new {time="1d" })" class="link external button @GetClass("1d")">1天</a>
|
|
<a href="@Url.Action(null,new {time="1w" })" class="link external button @GetClass("1w")">1周</a>
|
|
</p>
|
|
</div>
|
|
<div class="block">
|
|
<div class="row">
|
|
@foreach (var item in list)
|
|
{
|
|
<div class="col">
|
|
<canvas id="@item.Key" data-label="@item.Name" class="chart"></canvas>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="callback" class="popup popup-tablet-fullscreen">
|
|
<div class="page">
|
|
<div class="navbar">
|
|
<div class="navbar-inner">
|
|
<div class="left"></div>
|
|
<div class="title">API调用结果</div>
|
|
<div class="right"><a href="#" class="link popup-close">关闭</a></div>
|
|
</div>
|
|
</div>
|
|
<div class="page-content">
|
|
<div class="block">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<audio id="alarm" muted style="display:none;" src="~/iot/warning.wav"></audio>
|
|
<script src="~/lib/isMobile/isMobile.js"></script>
|
|
<script src="~/lib/jquery/jquery.min.js"></script>
|
|
<script src="~/lib/lodash/lodash.min.js"></script>
|
|
<script src="~/lib/framework7/js/framework7.bundle.min.js"></script>
|
|
<script src="~/lib/clappr/clappr.min.js"></script>
|
|
<script src="~/lib/clappr/clappr-rtmp-plugin/rtmp.min.js"></script>
|
|
<script src="~/lib/flv.js/flv.min.js"></script>
|
|
<script src="~/lib/hls.js/hls.min.js"></script>
|
|
<script src="~/lib/vue/vue.min.js"></script>
|
|
<script src="~/lib/signalr/signalr.min.js"></script>
|
|
<script src="~/lib/jquery-validation/jquery.validate.min.js"></script>
|
|
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
|
|
<script src="~/lib/Chart.js/Chart.bundle.min.js"></script>
|
|
<script>
|
|
var isNode =@(isNode?"true":"false");
|
|
var isList = false;
|
|
var updateUrl = '/Home/GetNode/@Model.Id';
|
|
var wsUrl = '/hub?group=page';
|
|
var isAdmin=@(User.IsInRole("EditDevice")?"true":"false");
|
|
var model = @Json.Serialize(Model, new Newtonsoft.Json.JsonSerializerSettings { ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore });
|
|
function load() {
|
|
}
|
|
</script>
|
|
<script src="~/js/iot.js"></script>
|
|
<script>
|
|
var hasChart =@((!isNode && Model.Data.Any(o => o.Type == "Int" || o.Type == "Float"))?"true":"false");
|
|
function updateChart() {
|
|
var url = '@Url.Action("Data",new { id=Model.Id,time=ViewBag.time})';
|
|
$.getJSON(url, function (result) {
|
|
console.log(result);
|
|
$.each(result, function (i,n) {
|
|
var id = n.id;
|
|
Chart.helpers.each(Chart.instances, function (instance) {
|
|
if (instance.chart.canvas.id == id) {
|
|
console.log('update chart:' + id);
|
|
instance.chart.data.labels = n.labels;
|
|
instance.chart.data.datasets[0].data = n.data;
|
|
instance.chart.update();
|
|
}
|
|
})
|
|
});
|
|
|
|
}).fail(function () {
|
|
console.log('error');
|
|
});
|
|
$('canvas.chart').each(function () {
|
|
console.log($(this).attr('id'));
|
|
});
|
|
}
|
|
function createChart() {
|
|
$('canvas.chart').each(function () {
|
|
var id = $(this).attr('id');
|
|
var canvas = document.getElementById(id);
|
|
var label = $(this).attr('data-label');
|
|
var ctx = canvas.getContext('2d');
|
|
var config = createConfig(label, [], []);
|
|
new Chart(ctx, config);
|
|
});
|
|
}
|
|
function createConfig(label, labels, data) {
|
|
return {
|
|
type: 'line',
|
|
data: {
|
|
labels: labels,
|
|
datasets: [{
|
|
label: label,
|
|
data: data,
|
|
borderColor: 'green',
|
|
fill: false
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
title: {
|
|
display: true,
|
|
text: label,
|
|
}
|
|
}
|
|
};
|
|
}
|
|
if (hasChart) {
|
|
createChart();
|
|
updateChart();
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |