diff --git a/projects/Platform/Controllers/HomeController.cs b/projects/Platform/Controllers/HomeController.cs index f1f4359c..3e476d11 100644 --- a/projects/Platform/Controllers/HomeController.cs +++ b/projects/Platform/Controllers/HomeController.cs @@ -43,6 +43,11 @@ namespace Platform.Controllers return View(); } + public IActionResult Test() + { + return View(); + } + public IActionResult Building(HomeModel model) { var userOrganId = User.GetOrganId().Value;//当前用户机构Id diff --git a/projects/Platform/Platform.csproj b/projects/Platform/Platform.csproj index 84660cd9..ca53ad3d 100644 --- a/projects/Platform/Platform.csproj +++ b/projects/Platform/Platform.csproj @@ -17,4 +17,10 @@ + + + true + PreserveNewest + + diff --git a/projects/Platform/Views/Home/Index.cshtml b/projects/Platform/Views/Home/Index.cshtml index e2b6cb04..8e1e4fd4 100644 --- a/projects/Platform/Views/Home/Index.cshtml +++ b/projects/Platform/Views/Home/Index.cshtml @@ -66,59 +66,4 @@

此处显示设备种类、数量的统计信息,显示定时器和触发器的统计信息,考虑按机构显示

-
-@section scripts{ - - - - - -} \ No newline at end of file + \ No newline at end of file diff --git a/projects/Platform/Views/Home/Test.cshtml b/projects/Platform/Views/Home/Test.cshtml new file mode 100644 index 00000000..976c573f --- /dev/null +++ b/projects/Platform/Views/Home/Test.cshtml @@ -0,0 +1,23 @@ +@section scripts{ + +} \ No newline at end of file diff --git a/projects/Platform/Views/Shared/_Layout.cshtml b/projects/Platform/Views/Shared/_Layout.cshtml index b08dd3e5..d8466a27 100644 --- a/projects/Platform/Views/Shared/_Layout.cshtml +++ b/projects/Platform/Views/Shared/_Layout.cshtml @@ -185,7 +185,18 @@ @**@ + + + + + @RenderSection("scripts", required: false) + \ No newline at end of file diff --git a/projects/Platform/wwwroot/js/common.js b/projects/Platform/wwwroot/js/common.js new file mode 100644 index 00000000..730a1154 --- /dev/null +++ b/projects/Platform/wwwroot/js/common.js @@ -0,0 +1,190 @@ +Vue.prototype.debug = config.debug; +Vue.prototype.isMobile = config.isMobile; +Vue.prototype.baseUrl = config.baseUrl; +Vue.prototype.uploadUrl = config.uploadUrl; + +function vueComponent(name, url) { + Vue.component(name, function (resolve, reject) { + axios.get(url).then(function (response) { + resolve(parseModel(response)); + }); + }); +} +function parseModel(response) { + var html = new DOMParser().parseFromString(response.data, 'text/html'); + var template = html.getElementsByTagName('template')[0].innerHTML; + var script = html.getElementsByTagName('script')[0].innerHTML; + script = '(' + script.replace(/^\s*export\s*default\s*/, '').replace(/;?\s*$/, '') + ')\n//# sourceURL=' + response.config.url; + var model = eval(script); + model.template = template; + return model; +} + +//update +function updateById(list, item) { + return update(list, item, 'id'); +} + +function updateByNumber(list, item) { + return update(list, item, 'number'); +} + +function updateByKey(list, item) { + return update(list, item, 'key'); +} + +function update(list, item, key) { + key = key || 'number'; + var result = false; + var to = Enumerable.from(list).where(function (o) { return o[key] === item[key]; }).firstOrDefault(); + if (to) { + copy(item, to); + } + else { + list.push(item); + result = true; + } + //console.log(result ? 'insert' : 'update' + ' data by ' + key); + return result; +} +//delete +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++) { + if (list[i][key] === item[key]) { + list.splice(i, 1); + result = true; + break; + } + } + return result; +} +//util +function copy(from, to) { + for (var attr in to) { + if (from.hasOwnProperty(attr)) { + if (!(from[attr] instanceof Array)) { + to[attr] = from[attr]; + } + } + } +} + +function subscribe(events, action) { + if (!events || !action) { + return; + } + for (var i = 0; i < events.length; i++) { + PubSub.subscribe(events[i], function (m, d) { action(m, d); }); + } +} + +function unsubscribe(events) { + if (!events) { + return; + } + for (var i = 0; i < events.length; i++) { + PubSub.unsubscribe(events[i]); + } +} + +// +function nodePower(number, command) { + loading.show(); + axios.post('/platform/api/v1/node/power' + command, '"' + number + '"', { headers: { 'Content-Type': 'application/json;charset=UTF-8' } }) + .then(function (response) { + console.log(response); + }) + .catch(function (error) { + console.log(error); + }) + .finally(function () { + loading.hide(); + }); +} + +function nodeMethod(number, method) { + loading.show(); + axios.post('/platform/api/v1/node/' + method, '"' + number + '"', { headers: { 'Content-Type': 'application/json;charset=UTF-8' } }) + .then(function (response) { + console.log(response); + }) + .catch(function (error) { + console.log(error); + }) + .finally(function () { + loading.hide(); + }); +} +// +function selectNode(e) { + var checkbox = $(e.target); + if (checkbox.hasClass('checkall')) { + if (e.target.checked) { + $('input.item:visible').not(':checked').prop("checked", true); + } + else { + $('input.item:visible').filter(':checked').prop("checked", false); + } + } + else if (checkbox.hasClass('uncheck')) { + $('input.item:visible').each(function () { + $(this).prop("checked", !$(this).prop("checked")).change(); + }); + } + var parent = $('input.checkall'); + if ($('input.item').not(':checked').length === 0) { + parent.prop("indeterminate", false); + parent.prop("checked", true); + } + else if ($('input.item').filter(':checked').length === 0) { + parent.prop("indeterminate", false); + parent.prop("checked", false); + } + else { + parent.prop("indeterminate", true); + } +} +//batch select +$(function () { + $(document).on('change', 'th :checkbox', function () { + if ($(this).is(':checked')) { + $(this).parents('table').find(':checkbox').not(':checked').prop("checked", true); + } + else { + $(this).parents('table').find(':checkbox').filter(':checked').prop("checked", false); + } + }); + $(document).on('change', 'td :checkbox', function () { + var parent = $(this).parents('table').find('th :checkbox'); + var children = $(this).parents('table').find('td :checkbox'); + if ($(this).is(':checked')) { + if (parent.not(':checked')) { + if (children.not(':checked').length === 0) { + parent.prop("indeterminate", false); + parent.prop("checked", true); + } + else { + parent.prop("indeterminate", true); + } + } + } + else { + if (parent.is(':checked')) { + if (children.filter(':checked').length === 0) { + parent.prop("indeterminate", false); + parent.prop("checked", false); + } + else { + parent.prop("indeterminate", true); + } + } + } + }); +}); diff --git a/projects/Platform/wwwroot/js/components.js b/projects/Platform/wwwroot/js/components.js new file mode 100644 index 00000000..941b75a1 --- /dev/null +++ b/projects/Platform/wwwroot/js/components.js @@ -0,0 +1,25 @@ +Vue.component('pagination', function (resolve, reject) { + axios.get("components/shared/pagination.html").then(function (response) { + resolve(parseModel(response)); + }); +}); +Vue.component('layout', function (resolve, reject) { + axios.get("components/shared/layout.html").then(function (response) { + resolve(parseModel(response)); + }); +}); +Vue.component('list', function (resolve, reject) { + axios.get("components/shared/list.html").then(function (response) { + resolve(parseModel(response)); + }); +}); +Vue.component('display', function (resolve, reject) { + axios.get("components/shared/display.html").then(function (response) { + resolve(parseModel(response)); + }); +}); +Vue.component('update', function (resolve, reject) { + axios.get("components/shared/update.html").then(function (response) { + resolve(parseModel(response)); + }); +}); diff --git a/projects/Platform/wwwroot/js/form.js b/projects/Platform/wwwroot/js/form.js new file mode 100644 index 00000000..c4a8be01 --- /dev/null +++ b/projects/Platform/wwwroot/js/form.js @@ -0,0 +1,26 @@ +var formComponents = [ + 'display-string', + 'display-boolean', + 'display-imageurl', + 'display-integer', + 'display-selectlist', + 'display-multiselectlist', + 'display-multilinetext', + 'display-html', + 'display-cron', + 'edit-string', + 'edit-password', + 'edit-boolean', + 'edit-imageurl', + 'edit-integer', + 'edit-selectlist', + 'edit-multiselectlist', + 'edit-multilinetext', + 'edit-html', + 'edit-cron', +]; +for (var i = 0; i < formComponents.length; i++) { + var name = formComponents[i]; + var url = "components/shared/" + name.replace('-', '/') + ".html"; + vueComponent(name, url); +} \ No newline at end of file diff --git a/projects/Platform/wwwroot/js/iot.js b/projects/Platform/wwwroot/js/iot.js index e6b6ab95..39c01be0 100644 --- a/projects/Platform/wwwroot/js/iot.js +++ b/projects/Platform/wwwroot/js/iot.js @@ -1,123 +1,154 @@ -var time = '1d'; -if(window.WXInlinePlayer&&WXInlinePlayer.isSupport()) { - WXInlinePlayer.init({ - asmUrl: baseUrl+'/lib/WXInlinePlayer/prod.all.asm.combine.js', - wasmUrl: baseUrl +'/lib/WXInlinePlayer/prod.all.wasm.combine.js' - }); -} -function getDeviceDataValue(device, name) { +Vue.prototype.getDeviceDataValue = function (device, name) { var data = Enumerable.from(device.data).where(o => o.name === name).firstOrDefault(); if (data) { return data['value']; } return null; -} -function getDeviceDataDescription(device, name) { +}; + +Vue.prototype.getDeviceDataDescription = function (device, name) { var data = Enumerable.from(device.data).where(o => o.name === name).firstOrDefault(); if (data) { return data['description']; } return null; } -function getDeviceDataUnit(device, name) { +Vue.prototype.getDeviceDataUnit = function (device, name) { var data = Enumerable.from(device.data).where(o => o.name === name).firstOrDefault(); if (data) { return data['unit']; } return null; } -function getDeviceData(device, name) { +Vue.prototype.getDeviceData = function (device, name) { var data = Enumerable.from(device.data).where(o => o.name === name).firstOrDefault(); if (data) { return data['value'] + ' ' + data['unit']; } return null; } -function getData(device, name) { +Vue.prototype.getData = function (device, name) { return Enumerable.from(device.data).where(o => o.name === name).firstOrDefault(); } +Vue.prototype.execApi = function (number, method, query) { + loading.show(); + axios.post(config.baseUrl + '/platform/api/v1/api/execApi', { connectionId, number, method, query }) + .then(function (response) { + }) + .catch(function (error) { + console.log(error); + }) + .finally(function () { + loading.hide(); + }); +} +Vue.prototype.execScene = function (id) { + loading.show(); + axios.post('/platform/api/v1/api/execScene', '"' + id + '"', { headers: { 'Content-Type': 'application/json;charset=UTF-8' } }) + .then(function (response) { + console.log(response); + }) + .catch(function (error) { + console.log(error); + }) + .finally(function () { + loading.hide(); + }); +} +Vue.prototype.execOrganScene = function (id) { + loading.show(); + axios.post('/platform/api/v1/api/execOrganScene', '"' + id + '"', { headers: { 'Content-Type': 'application/json;charset=UTF-8' } }) + .then(function (response) { + console.log(response); + }) + .catch(function (error) { + console.log(error); + }) + .finally(function () { + loading.hide(); + }); +} //devices -function parseModel(response) { - var html = new DOMParser().parseFromString(response.data, 'text/html'); - var template = html.getElementsByTagName('template')[0].innerHTML; - var script = html.getElementsByTagName('script')[0].innerHTML; - var model = eval(script); - model.template = template; - return model; +var iotComponents = [ + 'gateway', + 'light', + 'humiture', + 'smoke', + 'person', + 'curtain', + 'switch', + 'switch3', + 'socket', + 'ir', + 'color-light', + 'door', + 'camera', + 'serial-port', + 'ir-command' +]; +for (var i = 0; i < iotComponents.length; i++) { + var name = 'iot-' + iotComponents[i]; + var url = "components/iot/" + iotComponents[i] + ".html"; + vueComponent(name, url); } -function urlContent(path) { - if (!path.startsWith("/dfs/")) { - return baseUrl + path; +var deviceInfo = []; +deviceInfo['网关'] = 'iot-gateway'; +deviceInfo['光强检测器'] = 'iot-light'; +deviceInfo['温湿度传感器'] = 'iot-humiture'; +deviceInfo['烟雾报警器'] = 'iot-smoke'; +deviceInfo['人体感应器'] = 'iot-person'; +deviceInfo['窗帘电机'] = 'iot-curtain'; +deviceInfo['一路开关'] = 'iot-switch'; +deviceInfo['三路开关'] = 'iot-switch3'; +deviceInfo['插座'] = 'iot-socket'; +deviceInfo['智能插座'] = 'iot-socket'; +deviceInfo['红外转发器'] = 'iot-ir'; +deviceInfo['调色灯'] = 'iot-color-light'; +deviceInfo['门锁'] = 'iot-door'; +deviceInfo['摄像头'] = 'iot-camera'; +deviceInfo['串口控制器'] = 'iot-serial-port'; +/// +function updateSelect(action, id, value) { + var select = $('select#' + id); + if (select.length) { + select.find("option[value!='']").remove(); + select[0].dispatchEvent(new Event('change')); + if (value) { + var url = config.baseUrl + '/platform/IoTCenter/Ajax/' + action + '?parentId=' + value; + $.getJSON(url, function (data) { + $.each(data, function (i, v) { + select.append(''); + }); + }); + } } - return path; } -Vue.component('iot-gateway', function (resolve, reject) { - axios.get(baseUrl+"/pages/iot/device/gateway.html").then(function (response) { - resolve(parseModel(response)); - }); -}); -Vue.component('iot-light', function (resolve, reject) { - axios.get(baseUrl+"/pages/iot/device/light.html").then(function (response) { - resolve(parseModel(response)); - }); -}); -Vue.component('iot-humiture', function (resolve, reject) { - axios.get(baseUrl+"/pages/iot/device/humiture.html").then(function (response) { - resolve(parseModel(response)); - }); +$(document).on('change', 'select#productId', function (e) { + var value = $(this).val(); + updateSelect('getProductApiJson', 'apiId', value); }); -Vue.component('iot-smoke', function (resolve, reject) { - axios.get(baseUrl+"/pages/iot/device/smoke.html").then(function (response) { - resolve(parseModel(response)); - }); -}); -Vue.component('iot-person', function (resolve, reject) { - axios.get(baseUrl+"/pages/iot/device/person.html").then(function (response) { - resolve(parseModel(response)); - }); -}); -Vue.component('iot-curtain', function (resolve, reject) { - axios.get(baseUrl+"/pages/iot/device/curtain.html").then(function (response) { - resolve(parseModel(response)); - }); -}); -Vue.component('iot-switch', function (resolve, reject) { - axios.get(baseUrl+"/pages/iot/device/switch.html").then(function (response) { - resolve(parseModel(response)); - }); -}); -Vue.component('iot-switch3', function (resolve, reject) { - axios.get(baseUrl+"/pages/iot/device/switch3.html").then(function (response) { - resolve(parseModel(response)); - }); -}); -Vue.component('iot-socket', function (resolve, reject) { - axios.get(baseUrl+"/pages/iot/device/socket.html").then(function (response) { - resolve(parseModel(response)); - }); -}); -Vue.component('iot-ir', function (resolve, reject) { - axios.get(baseUrl+"/pages/iot/device/ir.html").then(function (response) { - resolve(parseModel(response)); - }); +$(document).on('change', 'select#nodeId', function (e) { + var value = $(this).val(); + updateSelect('getDeviceJson', 'deviceId', value); + updateSelect('getCommandJson', 'commandId', value); + if ($(this).parents('form.GlobalSceneCommand').length === 0) { + updateSelect('getSceneJson', 'sceneId', value); + } }); -Vue.component('iot-color-light', function (resolve, reject) { - axios.get(baseUrl+"/pages/iot/device/color-light.html").then(function (response) { - resolve(parseModel(response)); - }); +$(document).on('change', 'select#deviceNodeId', function (e) { + var value = $(this).val(); + updateSelect('getDeviceJson', 'deviceId', value); }); -Vue.component('iot-door', function (resolve, reject) { - axios.get(baseUrl + "/pages/iot/device/door.html").then(function (response) { - resolve(parseModel(response)); - }); +$(document).on('change', 'select#deviceId', function (e) { + var value = $(this).val(); + updateSelect('getApiJson', 'apiId', value); + updateSelect('getDataJson', 'dataId', value); }); -Vue.component('iot-camera', function (resolve, reject) { - axios.get(baseUrl+"/pages/iot/device/camera.html").then(function (response) { - resolve(parseModel(response)); - }); +$(document).on('change', 'select#organId', function (e) { + var value = $(this).val(); + updateSelect('GetOrganSceneJson', 'organSceneId', value); + updateSelect('GetOrganNodeJson', 'nodeId', value); }); -Vue.component('iot-serial-port', function (resolve, reject) { - axios.get(baseUrl+"/pages/iot/device/serial-port.html").then(function (response) { - resolve(parseModel(response)); - }); -}); \ No newline at end of file +//$(document).on('change', 'select', function (e) { +// $(this).parents('form').find("button[type='submit']").click(); +//}); diff --git a/projects/Platform/wwwroot/js/signalr.js b/projects/Platform/wwwroot/js/signalr.js new file mode 100644 index 00000000..5f33dcb0 --- /dev/null +++ b/projects/Platform/wwwroot/js/signalr.js @@ -0,0 +1,27 @@ +var hubUrl = config.baseUrl + '/platform/hub?group='+config.gorup||'group'; +var connection = new signalR.HubConnectionBuilder().withUrl(hubUrl).build(); +var connectionId; + +function connect() { + if (connection.state === signalR.HubConnectionState.Disconnected) { + connection.start().then(function () { + console.log('signalr connected'); + }).catch(function (err) { + console.log(err); + setTimeout(connect, 5000); + }); + } +} +connection.onclose(function () { + console.log('connect closed'); + connect(); +}); + +connection.on('Connected', function (id) { + connectionId = id; +}); + +connection.on("ServerToClient", function (method, message, to, from) { + PubSub.publish(method, { message: message, to: to, from: from }); +}); +connect();