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.
iot/projects/IoT/IoT.Shared/Views/Device/Details.cshtml

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>