Former-commit-id: dced54e6fe642289bab17ac2fffd243d80b21071
Former-commit-id: 4a5a65b2cb789cad303bea31509e324ff40ec262
TSXN
wanggang 5 years ago
parent bc6d5601b6
commit 82b68626d5

@ -108,6 +108,11 @@
"destination": "wwwroot/lib/linq.js",
"files": [ "linq.min.js" ]
},
{
"library": "Chart.js@2.9.3",
"destination": "wwwroot/lib/chart.js/",
"files": [ "Chart.bundle.min.js" ]
},
{
"library": "flv.js@1.5.0",
"destination": "wwwroot/lib/flv.js/",

@ -33,7 +33,24 @@
</a>
<div class="sidebar">
<nav class="mt-2">
Menu
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
<li class="nav-item">
<router-link :to="{path:'/'}" :class="'nav-link'+isActive(['/','/pages/product.html','/pages/device.html'])">
<i class="nav-icon far fa-image"></i>
<p>
产品
</p>
</router-link>
</li>
<li class="nav-item">
<router-link :to="{path:'/pages/nodes.html'}" :class="'nav-link'+isActive(['/pages/nodes.html','/pages/node.html'])">
<i class="nav-icon far fa-image"></i>
<p>
节点
</p>
</router-link>
</li>
</ul>
</nav>
</div>
</aside>
@ -63,8 +80,11 @@
</div>
<footer class="main-footer">
<strong>
{{model.copyright.replace('{0}',new Date().getFullYear())}} <b>v {{model.version}}</b>
{{model.copyright.replace('{0}',new Date().getFullYear())}}
</strong>
<div class="float-right d-none d-sm-inline-block" style="padding-right:60px;">
<b>version: {{model.version}}</b>
</div>
</footer>
</div>
</template>
@ -93,18 +113,20 @@
}).finally(function () {
//loading.hide();
});
console.log('layout.html');
console.log(this.$route.path);
},
methods: {
logout() {
store.commit('logout');
router.push('/pages/login.html');
},
handleOpen(e) {
console.log('handleOpen', e);
},
handleClose(e) {
console.log('handleClose', e);
isActive(pages) {
for (var i = 0; i < pages.length; i++) {
if (this.$route.path == pages[i]) {
return ' active';
}
}
return '';
}
}
}

@ -36,6 +36,7 @@
<script src="lib/jwt-decode/build/jwt-decode.min.js"></script>
<script src="lib/admin-lte/js/adminlte.min.js"></script>
<script src="lib/signalr/signalr.min.js"></script>
<script src="lib/chart.js/Chart.bundle.min.js"></script>
<script src="lib/flv.js/flv.min.js"></script>
<!--<script src="lib/toastr.js/toastr.min.js"></script>-->
<!--<script src="lib/bootstrap/js/bootstrap.min.js"></script>-->

@ -18,8 +18,6 @@
}
);
axios.interceptors.response.use(function (response) {
console.log('axios.interceptors.response:');
console.log(response);
loading.hide();
return response;
}, function (error) {

@ -36,9 +36,12 @@ function update(list, item, key) {
return result;
}
//delete
function remove(list, item) {
function removeById(list, item) {
return remove(list, item, 'id');
}
function removeByKey(list, item) {
return remove(list, item, 'key');
}
function remove(list, item, key) {
var result = false;
for (var i = 0; i < list.length; i++) {

@ -14,9 +14,5 @@ const app = new Vue({
store: store,
router,
mounted: function () {
console.log('mounted:app');
setTimeout(function () {
PubSub.publish('msg', 'data');
}, 5000)
}
});

@ -5,7 +5,7 @@ var connectionId;
function connect() {
if (connection.state === signalR.HubConnectionState.Disconnected) {
connection.start().then(function () {
console.log('signalR 连接成功');
console.log('signalr connected');
}).catch(function (err) {
console.log(err);
setTimeout(connect, 5000);

File diff suppressed because one or more lines are too long

@ -50,7 +50,8 @@
title: '设备',
url: '/IoTCenter/api/v1/device/getDevice?number=' + this.$route.query.number,
device: null,
events: ['DeviceEntityInserted', 'DeviceEntityInserted', 'DeviceEntityInserted']
events: ['DeviceEntityInserted', 'DeviceEntityUpdated', 'DeviceEntityInserted',
'DataEntityInserted', 'DataEntityUpdated', 'DataEntityInserted']
}
},
mounted: function () {
@ -63,6 +64,9 @@
axios.post(url).then(function (response) {
vm.device = response.data;
vm.subscribe();
vm.$nextTick(function () {
vm.updateChart();
});
});
},
updateChart: function () {
@ -75,7 +79,7 @@
},
changeTime: function (key, time, title) {
var vm = this;
var url = '/IoTCenter/api/v1/Device/GetChartData';
var url = config.baseUrl + '/IoTCenter/api/v1/Device/GetChartData';
var data = {
number: this.device.number,
key: key,
@ -137,7 +141,12 @@
subscribe() {
var vm = this;
subscribe(this.events, function (method, data) {
vm.load();
if (method.indexOf('Data') == 0) {
updateById(vm.device.data, JSON.parse(data.message));
if (vm.hasChart()) {
vm.updateChart();
}
}
});
},
unsubscribe() {

@ -1,12 +1,13 @@
<template>
<layout v-bind:title="title" v-bind:url="url">
<div class="row overlay-wrapper">
<div class="col-md-2 col-sm-4 col-xs-6" v-for="item in organs">
<div class="col-md-2 col-sm-4 col-xs-6" v-for="item in products">
<div class="card">
<div class="card-header">
<h3 class="card-title">{{item.name}}</h3>
<div class="card-tools"><span data-toggle="tooltip" class="badge bg-green">{{item.count}}</span></div>
</div>
<router-link :to="{path:'/pages/organ.html',query:{number:item.number}}" class="card-body" style="display: block; text-align: center;">
<router-link :to="{path:'/pages/product.html',query:{number:item.number}}" class="card-body" style="display: block; text-align: center;">
<img :src="config.baseUrl+item.image" style="margin: 0px auto; width: 64px;">
</router-link>
</div>
@ -18,10 +19,11 @@
export default {
data: function () {
return {
title: '机构列表',
url: '/IoTCenter/api/v1/organ/getOrgans',
organs: [],
events: ['OrganEntityInserted', 'OrganEntityUpdated', 'OrganEntityDeleted']
title: '产品列表',
url: '/IoTCenter/api/v1/product/getProducts',
products: [],
events: ['ProductEntityInserted', 'ProductEntityUpdated', 'ProductEntityDeleted',
'DeviceEntityInserted', 'DeviceEntityUpdated', 'DeviceEntityDeleted']
}
},
mounted: function () {
@ -32,7 +34,7 @@
var url = config.baseUrl + this.url;
var vm = this;
axios.post(url).then(function (response) {
vm.organs = response.data;
vm.products = response.data;
vm.subscribe();
});
},
@ -43,11 +45,11 @@
});
},
unsubscribe() {
unsubscribe(this.events);
this.unsubscribe(this.events);
}
},
beforeDestroy: function () {
this.unsubscribe();
unsubscribe();
}
}
</script>

@ -1 +1,201 @@

<template>
<layout>
<!--场景-->
<div class="row" v-if="node.scenes.length">
<div class="col">
<div class="card" style="margin:10px;">
<div class="card-header">{{node.name}}的场景</div>
<div class="card-body">
<button class="btn btn-success" v-for="scene in node.scenes" v-on:click="execScene(scene.id)">{{scene.name}}</button>
</div>
</div>
</div>
</div>
<!--环境-->
<!--<div class="col col-md-12 my-2 px-3">环境</div>-->
<div class="row">
<!--光强检测器-->
<div v-for="device in getDevices('光强检测器')" class="col" style="min-width:320px;">
<iot-light v-bind:device="device"></iot-light>
</div>
<!--温湿度传感器-->
<div v-for="device in getDevices('温湿度传感器')" class="col" style="min-width:320px;">
<iot-humiture v-bind:device="device"></iot-humiture>
</div>
<!--烟雾报警器-->
<div v-for="device in getDevices('烟雾报警器')" class="col" style="min-width:320px;">
<iot-smoke v-bind:device="device"></iot-smoke>
</div>
<!--人体感应器-->
<div v-for="device in getDevices('人体感应器')" class="col" style="min-width:320px;">
<iot-person v-bind:device="device"></iot-person>
</div>
<!--</div>
<div class="col col-md-12 my-2 px-3">用电</div>
<div class="row">-->
<!--门锁-->
<div v-for="device in getDevices('门锁')" class="col" style="min-width:320px;">
<iot-door v-bind:device="device"></iot-door>
</div>
<!--调色灯-->
<div v-for="device in getDevices('调色灯')" class="col" style="min-width:320px;">
<iot-color-light v-bind:device="device"></iot-color-light>
</div>
<!--窗帘电机-->
<div v-for="device in getDevices('窗帘电机')" class="col" style="min-width:320px;">
<iot-curtain v-bind:device="device"></iot-curtain>
</div>
<!--一路开关-->
<div v-for="device in getDevices('一路开关')" class="col" style="min-width:320px;">
<iot-switch v-bind:device="device"></iot-switch>
</div>
<!--三路开关-->
<div v-for="device in getDevices('三路开关')" class="col" style="min-width:320px;">
<iot-switch3 v-bind:device="device"></iot-switch3>
</div>
<!--插座-->
<div v-for="device in getDevices('插座')" class="col" style="min-width:320px;">
<iot-socket v-bind:device="device"></iot-socket>
</div>
<!--智能插座-->
<div v-for="device in getDevices('智能插座')" class="col" style="min-width:320px;">
<iot-socket v-bind:device="device"></iot-socket>
</div>
</div>
<!--<div class="col col-md-12 my-2 px-3">遥控器</div>-->
<div class="row">
<!--摄像头-->
<div v-for="device in getDevices('摄像头')" class="col" style="min-width:320px;">
<iot-camera v-bind:device="device"></iot-camera>
</div>
<!--红外转发器-->
<div v-for="device in getDevices('红外转发器')" class="col" style="min-width:320px;">
<iot-ir v-bind:device="device"></iot-ir>
</div>
<!--串口控制器-->
<div v-for="device in getSPDevices()" class="col" style="min-width:320px;">
<iot-serial-port v-bind:device="device"></iot-serial-port>
</div>
</div>
</layout>
</template>
<script>
export default {
data() {
return {
title: "节点",
url: '/IoTCenter/api/v1/node/getNode?number=' + this.$route.query.number,
node: {
devices: [],
scenes: []
},
events: ['SceneEntityInserted', 'SceneEntityUpdated', 'SceneEntityDeleted',
'NodeEntityInserted', 'NodeEntityUpdated', 'NodeEntityDeleted',
'DeviceEntityInserted', 'DeviceEntityUpdated', 'DeviceEntityDeleted',
'DataEntityInserted', 'DataEntityUpdated', 'DataEntityDeleted']
};
},
mounted: function () {
this.load();
},
methods: {
load: function () {
var vm = this;
var url = config.baseUrl + this.url;
axios.post(url).then(function (response) {
vm.node = response.data;
vm.subscribe();
});
},
getDevices: function (name) {
return Enumerable.from(this.node.devices).where(function (o) { return o.name === name; }).toArray();
},
getSPDevices: function () {
return Enumerable.from(this.node.devices).where(function (o) {
if (o.name === '串口控制器') {
var data = Enumerable.from(o.data)
.where(function (d) { return d.name === "指令"; })
.firstOrDefault();
if (data) {
var btns = Enumerable.from(JSON.parse(data.value))
.orderBy(function (b) { return b.order; })
.toArray();
if (Enumerable.from(btns).any(function (b) { return b.name !== '测试'; })) {
return true;
}
}
return false;
}
return false;
}).toArray();
},
getDeviceDataAttr: function (number, name, attr) {
var device = Enumerable.from(this.node.devices).where(function (o) { return o.number === number; }).firstOrDefault();
var data = Enumerable.from(device.data).where(o => o.name === name).firstOrDefault();
if (data !== null) {
return data[attr];
}
return null;
},
getDataValue: function (number, name) {
return this.getDeviceDataAttr(number, name, 'value');
},
scenes: function () {
return Enumerable.from(this.node.scenes).orderBy('o=>o.displayOrder').toArray();
},
subscribe() {
var vm = this;
subscribe(this.events, function (method, data) {
var item = JSON.parse(data.message);
if (method.indexOf('Node') == 0) {
if (vm.node.id === item.id) {
if (method.indexOf('Deleted') >= 0) {
console.log('node has deleted');
router.push('/pages/nodes.html');
}
else {
vm.load();
}
}
}
else {
var list;
if (method.indexOf('Device') == 0) {
if (vm.node.id === device.nodeId) {
list = device.devices;
}
}
else if (method.indexOf('Scenes') == 0) {
if (vm.node.id === scene.nodeId) {
list = device.scenes;
}
}
else if (method.indexOf('Data') == 0) {
var device = Enumerable.from(vm.node.devices).firstOrDefault(function (o) { return o.id === item.deviceId; });
if (device) {
list = device.data;
}
}
if (list) {
if (method.indexOf('Deleted') >= 0) {
removeById(list, item);
}
else {
updateById(list, item);
}
}
}
});
},
unsubscribe() {
this.unsubscribe(this.events);
},
beforeDestroy: function () {
unsubscribe();
}
}
};
</script>

@ -1 +1,57 @@

<template>
<layout v-bind:title="title" v-bind:url="url">
<div class="row overlay-wrapper">
<div class="col-md-2 col-sm-4 col-xs-6" v-for="item in nodes">
<div class="card">
<div class="card-header">
<h3 class="card-title">
<span v-if="item.isOnline" style="color:green;">{{item.name}}</span>
<span v-else style="color:red;">{{item.name}}</span>
</h3>
<div class="card-tools"><span data-toggle="tooltip" class="badge bg-green">{{item.count}}</span></div>
</div>
<router-link :to="{path:'/pages/node.html',query:{number:item.number}}" class="card-body" style="display: block; text-align: center;">
<img :src="config.baseUrl+item.image" style="margin: 0px auto; width: 64px;">
</router-link>
</div>
</div>
</div>
</layout>
</template>
<script>
export default {
data: function () {
return {
title: '节点列表',
url: '/IoTCenter/api/v1/node/getNodes',
nodes: [],
events: ['NodeEntityInserted', 'NodeEntityUpdated', 'NodeEntityDeleted']
}
},
mounted: function () {
this.load();
},
methods: {
load() {
var url = config.baseUrl + this.url;
var vm = this;
axios.post(url).then(function (response) {
vm.nodes = response.data;
vm.subscribe();
});
},
subscribe() {
var vm = this;
subscribe(this.events, function (method, data) {
vm.load();
});
},
unsubscribe() {
this.unsubscribe(this.events);
}
},
beforeDestroy: function () {
unsubscribe();
}
}
</script>

@ -1,13 +1,12 @@
<template>
<layout v-bind:title="title" v-bind:url="url">
<div class="row overlay-wrapper">
<div class="col-md-2 col-sm-4 col-xs-6" v-for="item in organ.products">
<div class="col-md-2 col-sm-4 col-xs-6" v-for="item in organs">
<div class="card">
<div class="card-header">
<h3 class="card-title">{{item.name}}</h3>
<div class="card-tools"><span data-toggle="tooltip" class="badge bg-green">{{item.count}}</span></div>
</div>
<router-link :to="{path:'/pages/product.html',query:{number:item.number}}" class="card-body" style="display: block; text-align: center;">
<router-link :to="{path:'/pages/organ.html',query:{number:item.number}}" class="card-body" style="display: block; text-align: center;">
<img :src="config.baseUrl+item.image" style="margin: 0px auto; width: 64px;">
</router-link>
</div>
@ -19,12 +18,10 @@
export default {
data: function () {
return {
title: '机构',
url: '/IoTCenter/api/v1/organ/getProducts?number=' + this.$route.query.number,
organ: {
products: []
},
events: ['ProductEntityInserted', 'ProductEntityUpdated', 'ProductEntityDeleted']
title: '机构列表',
url: '/IoTCenter/api/v1/organ/getOrgans',
organs: [],
events: ['OrganEntityInserted', 'OrganEntityUpdated', 'OrganEntityDeleted']
}
},
mounted: function () {
@ -35,7 +32,7 @@
var url = config.baseUrl + this.url;
var vm = this;
axios.post(url).then(function (response) {
vm.organ = response.data;
vm.organs = response.data;
vm.subscribe();
});
},
@ -46,11 +43,11 @@
});
},
unsubscribe() {
this.unsubscribe(this.events);
unsubscribe(this.events);
}
},
beforeDestroy: function () {
unsubscribe();
this.unsubscribe();
}
}
</script>

@ -24,7 +24,9 @@
product: {
devices: []
},
events: ['ProductEntityInserted', 'ProductEntityUpdated', 'ProductEntityDeleted']
events: ['ProductEntityInserted', 'ProductEntityUpdated', 'ProductEntityDeleted',
'DeviceEntityInserted', 'DeviceEntityUpdated', 'DeviceEntityDeleted',
'DataEntityInserted', 'DataEntityUpdated', 'DataEntityDeleted']
}
},
mounted: function () {
@ -42,7 +44,39 @@
subscribe() {
var vm = this;
subscribe(this.events, function (method, data) {
vm.load();
var item = JSON.product(data.message);
if (method.indexOf('Product') == 0) {
vm.load();
}
else {
var list;
if (method.indexOf('Device') == 0) {
if (vm.product.id === device.productId) {
list = device.devices;
}
}
else {
if (method.indexOf('Device') == 0) {
if (vm.product.id === device.productId) {
list = product.devices;
}
}
else if (method.indexOf('Data') == 0) {
var device = Enumerable.from(vm.product.devices).firstOrDefault(function (o) { return o.id === item.deviceId; });
if (device) {
list = device.data;
}
}
}
if (list) {
if (method.indexOf('Deleted') >= 0) {
removeById(list, item);
}
else {
updateById(list, item);
}
}
}
});
},
unsubscribe() {

Loading…
Cancel
Save