物联网平台设计心得:五级联动及记忆恢复

在设计物联网平台的时候,涉及到一个五级联动的问题,操作顺序如下:依次选择 所属省份,所属市县,所属地区,所属公司,设备名称。在使用Jquery时代,做好这个其实很容易,但是稍显繁琐,并且得很好的处理上一级下拉列表选中,然后触发下一级下拉列表加载数据的问题。相比使用Angularjs而言,代码量大而且繁琐,并且还得处理好顺序加载的问题。本节我们就看看Angularjs能给我们带来怎么样的体验吧。本文成文仓促,讲解难免会有谬误,还请见谅。

五级联动的设计

由于省份,市县,地区,公司四张表,在数据库中的设计基本一致,我们就专门为这四种下拉列表设计一个公共的模板出来。

app.directive(‘sectorPart‘, [function() {
    return {
        restrict: ‘AE‘,
        replace: true,
        scope: { options: "=" },
        template: ‘<select class="form-control" ng-options="item as item.name for item in options" name="state" style="width:220px;height:33px;">‘
                + ‘<option value="">请选择</option>‘
                + ‘</select>‘
    };
}]);

由于设备表中的数据字段类型不太一致,所以这里我们专门为设备设计一种下拉列表模板:

app.directive(‘sectorMachine‘, [function () {
    return {
        restrict: ‘AE‘,
        replace: true,
        scope: { options: "=" },
        template: ‘<select class="form-control" ng-options="item as item.machine_name for item in options" name="state" style="width:220px;height:33px;">‘
                + ‘<option value="">请选择</option>‘
                + ‘</select>‘
    };
}]);

好了,模板都设计完毕了,我们接下来将模板(Directive)应用到页面中:

  <div class="searchcontainer">
        <div class="row">
            <div class="col-md-4">
                <div class="input-group">
                    <span class="input-group-addon" id="basic-addon1">所属省份:</span>
                    <sector-part options="ProvinceData" ng-model="selectedProvince" ng-change="GetCityList()"></sector-part>
                </div>
            </div>
            <div class="col-md-4">
                <div class="input-group">
                    <span class="input-group-addon" id="basic-addon1">所属市县:</span>
                    <sector-part options="CityData" ng-model="selectedCity" ng-change="GetDistrictList()"></sector-part>
                </div>
            </div>
            <div class="col-md-4">
                <div class="input-group">
                    <span class="input-group-addon" id="basic-addon1">所属地区:</span>
                    <sector-part options="DistrictData" ng-model="selectedDistrict" ng-change="GetCompanyList()"></sector-part>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-md-4">
                <div class="input-group">
                    <span class="input-group-addon" id="basic-addon1">所属公司:</span>
                    <sector-part options="CompanyData" ng-model="selectedCompany" ng-change="GetMachineList()"></sector-part>
                </div>
            </div>
            <div class="col-md-4">
                    <div class="input-group">
                        <span class="input-group-addon" id="basic-addon1">设备名称:</span>
                        <sector-machine options="MachineData" ng-model="selectedMachine" ng-change="RefreshPage()"></sector-machine>
                    </div>
                </div>
            <div class="col-md-4">
                <div class="input-group">
                    <button class="btn btn-success" ng-click="LoadControllerList()" style="height:33px;line-height:16px;width:315px;">点击加载</button>
                </div>
            </div>
        </div>
    </div>

从HTML模板中,我们可以看到以下几个关键点:options是我传入到下拉列表的数据,下拉列表会根据options的值来加载列表并显示;ng-model是我选中的项,一旦有列表被选中,就会将数据传递到这个model中;ng-change是下拉列表被选中的时候触发的事件。

最后让我们来看看Controller中的写法吧:

app.controller(‘collectorController‘, [‘$scope‘, ‘$cookies‘, ‘$timeout‘,‘$compile‘, ‘baseService‘, ‘collectorService‘, ‘uiGridConstants‘, function ($scope, $cookies,$timeout,$compile, baseService, collectorService, uiGridConstants) {
    var self = this;

    $scope.selectedProvince = null;
    $scope.selectedCity = null;
    $scope.selectedDistrict = null;
    $scope.selectedCompany = null;
    $scope.selectedMachine = null;

    //省份绑定
    collectorService.GetProvinceData().then(function (data) {
        var flag = data.data.success;
        if (flag) {
            $scope.ProvinceData = data.data.data;
        }
    }, null);

    $scope.GetCityList = function () {
        var selectedProvinceId;
        if ($scope.selectedProvince != undefined)
            selectedProvinceId = $scope.selectedProvince.id;
        else
            return;
        //市区绑定
        collectorService.GetCityData(selectedProvinceId).then(function (data) {
            var flag = data.data.success;
            if (flag) {
                $scope.CityData = data.data.data;
            }
        }, null);
    }

    $scope.GetDistrictList = function () {
        var selectedCityId;
        if ($scope.selectedCity != undefined)
            selectedCityId = $scope.selectedCity.id;
        else
            return;
        //区县绑定
        collectorService.GetDistrictData(selectedCityId).then(function (data) {
            var flag = data.data.success;
            if (flag) {
                $scope.DistrictData = data.data.data;
            }
        }, null);
    }

    $scope.GetCompanyList = function () {
        var selectedDistrictId;
        if ($scope.selectedDistrict != undefined)
        else
            return;
        //公司绑定
        collectorService.GetCompanyData(selectedDistrictId).then(function (data) {
            var flag = data.data.success;
            if (flag) {
                $scope.CompanyData = data.data.data;
            }
        }, null);
    }

    $scope.GetMachineList = function () {
        var selectedCompanyId;
        if ($scope.selectedCompany != undefined)
            selectedCompanyId = $scope.selectedCompany.id;
        else
            return;
        //设备绑定
        collectorService.GetMachineList(selectedCompanyId).then(function (data) {
            var flag = data.data.success;
            if (flag) {
                $scope.MachineData = data.data.data;
            }
        }, null);
    }
}]);

看上去是不是挺简洁的。反正这些方法的触发都是根据ng-change来进行的。然后ng-model由于是mvvm模式,所以一旦选中项改变,会自动被传到controller中来。至于collectorService就是一个简单的获取数据的service而已,这里不是主要的,我简单的贴一下:

app.service(‘collectorService‘, [‘$http‘, function ($http) {
    var provinceData = function () {
        return $http({
            method: ‘POST‘,
            url: ‘/Process/GetLocationList?provinceid=-1&cityid=-1‘
        });
    }

    var cityData = function (provinceId) {
        return $http({
            method: ‘POST‘,
            url: ‘/Process/GetLocationList?provinceid=‘ + provinceId + ‘&cityid=-1‘
        });
    }

    var districtData = function (cityId) {
        return $http({
            method: ‘POST‘,
            url: ‘/Process/GetLocationList?provinceid=-1&cityid=‘ + cityId
        });
    }

    var companyData = function (districtId) {
        return $http({
            method: ‘POST‘,
            url: ‘/BaseData/GetSchoolByDistrictId?districtId=‘ + districtId
        });
    }

    var machineList = function (companyId) {
        return $http({
            method: ‘POST‘,
            url: ‘/Machine/GetMachineBy?companyId=‘ + companyId + ‘&isController=0‘
        });
    }

    return {
        GetProvinceData: provinceData,
        GetCityData: cityData,
        GetDistrictData: districtData,
        GetCompanyData: companyData,
        GetMachineList: machineList
    };
}]);

好了,以上就是五级联动了。我们可以一级一级的点下去了。是不是很方便呢?操作图展示:

五级联动记忆恢复

在实际使用的时候,有的用户反映,五级联动选择很麻烦,需要一个一个的点,如果能记忆上次的选择项就好了。这样就可以不用费力的每次都点击了。基于此种用户需求,我决定利用cookie来记忆用户上次的选择内容,然后在下次浏览的时候,来载入之前的浏览记录。下面我们来分析一下如何能够做到自动的根据已有记录逐级加载下来列表并选中。

首先,我们需要将数据保存到cookie中。

其次,我们需要监视列表选项的变化,这里我们可以用$watchcollection方法。

最后,列表选项变化后,我们就需要依据选中内容,加载下级列表,所以这里我们需要多selectedProvice,selectedCity等变量赋值。

明白了这些步骤,下面我们进行改造:

app.controller(‘collectorController‘, [‘$scope‘, ‘$cookies‘, ‘$timeout‘,‘$compile‘, ‘baseService‘, ‘collectorService‘, ‘uiGridConstants‘, function ($scope, $cookies,$timeout,$compile, baseService, collectorService, uiGridConstants) {
    var self = this;

    $scope.ProvinceData = null;
    $scope.CityData = null;
    $scope.DistrictData = null;
    $scope.CompanyData = null;
    $scope.MachineData = null;
    $scope.RealTimeData = null;
    $scope.HistoryData = null;

    $scope.selectedProvince = null;
    $scope.selectedCity = null;
    $scope.selectedDistrict = null;
    $scope.selectedCompany = null;
    $scope.selectedMachine = null;

    //监测省份的变化,如果发生了变化,则加载城市列表
    $scope.$watchCollection(‘selectedProvince‘, function (oldval, newval) {
        $scope.GetCityList();
    });

    //监测城市变化,如果发生了变化,则加载地区列表
    $scope.$watchCollection(‘selectedCity‘, function (oldval, newval) {
        $scope.GetDistrictList();
    });
    //监测地区变化,如果发生了变化,则加载公司列表
    $scope.$watchCollection(‘selectedDistrict‘, function (oldval, newval) {
        $scope.GetCompanyList();
    });
    //监测公司变化,如果发生了变化,则加载机器列表
    $scope.$watchCollection(‘selectedCompany‘, function (oldval, newval) {
        $scope.GetMachineList();
    });

    //省份绑定
    collectorService.GetProvinceData().then(function (data) {
        var flag = data.data.success;
        if (flag) {
            $scope.ProvinceData = data.data.data;
            $scope.selectedProvince = baseService.getSelectedDataMapper($scope.ProvinceData, ‘province‘);
        }
    }, null);

    $scope.GetCityList = function () {
        var selectedProvinceId;
        if ($scope.selectedProvince != undefined)
            selectedProvinceId = $scope.selectedProvince.id;
        else
            return;
        //市区绑定
        collectorService.GetCityData(selectedProvinceId).then(function (data) {
            var flag = data.data.success;
            if (flag) {
                $scope.CityData = data.data.data;
                $scope.selectedCity = baseService.getSelectedDataMapper($scope.CityData, ‘city‘);
            }
        }, null);
    }

    $scope.GetDistrictList = function () {
        var selectedCityId;
        if ($scope.selectedCity != undefined)
            selectedCityId = $scope.selectedCity.id;
        else
            return;
        //区县绑定
        collectorService.GetDistrictData(selectedCityId).then(function (data) {
            var flag = data.data.success;
            if (flag) {
                $scope.DistrictData = data.data.data;
                $scope.selectedDistrict = baseService.getSelectedDataMapper($scope.DistrictData, ‘district‘);
            }
        }, null);
    }

    $scope.GetCompanyList = function () {
        var selectedDistrictId;
        if ($scope.selectedDistrict != undefined)
            selectedDistrictId = $scope.selectedDistrict.id;
        else
            return;
        //公司绑定
        collectorService.GetCompanyData(selectedDistrictId).then(function (data) {
            var flag = data.data.success;
            if (flag) {
                $scope.CompanyData = data.data.data;
                $scope.selectedCompany = baseService.getSelectedDataMapper($scope.CompanyData, ‘company‘);
            }
        }, null);
    }

    $scope.GetMachineList = function () {
        var selectedCompanyId;
        if ($scope.selectedCompany != undefined)
            selectedCompanyId = $scope.selectedCompany.id;
        else
            return;
        //设备绑定
        collectorService.GetMachineList(selectedCompanyId).then(function (data) {
            var flag = data.data.success;
            if (flag) {
                $scope.MachineData = data.data.data;
                $scope.selectedMachine = baseService.getSelectedDataMapper($scope.MachineData, ‘machine‘);
            }
        }, null);
    }

    //获取实时数据
    $scope.GetRealTimeDataByMachine = function () {

        //将级联列表项放到cookie中,以便于之后的操作简易化
        var expireDate = new Date();
        expireDate.setDate(expireDate.getDate() + 7);
        delete $cookies[‘frontselection‘];

        var cookieData = JSON.stringify({
            province: $scope.selectedProvince,
            city: $scope.selectedCity,
            district: $scope.selectedDistrict,
            company: $scope.selectedCompany,
            machine: $scope.selectedMachine
        });
        $cookies.put(‘frontselection‘, cookieData, { ‘expires‘: expireDate });
    }

}]);

可以看出,我们在点击最后的加载按钮的时候,把cookie存储到了浏览器中。然后在页面进入的时候,我们先加载了省份列表,省份列表加载成功后,我们马上从cookie中拿出上次选中的省份,然后给selectedProvice赋值,这个赋值动作会马上触发$watchcollection中的动作,然后进行市县的绑定。一级一级的触发,直到最后。

有人会问,那个baseService是干什么的。由于我将$scope.selectedProvince,$scope.selectedCity等对象直接保存到了cookie中,在取出来的时候,我发现这些entity已经变了,entity内部会自动多出来一个_hashcode的属性,导致和原来的entity有差别,这就会导致angularjs无法通过验证,我必须通过baseService的方法,来还原出原来的selectedProvice等对象才行。

app.service(‘baseService‘, [‘$cookies‘, function ($cookies) {

    //获取比对数据并赋值
    //type: province,city,district,company,machine
    var selectionMapper = function (sourceData, type) {
        //从cookie获取值
        var collectorSelectionFromCookie = $cookies.get(‘frontselection‘);
        if (collectorSelectionFromCookie != undefined) {
            //如果cookie存在,则进行解析
            collectorSelectionFromCookie = JSON.parse($cookies.get(‘frontselection‘));
            for (var i = 0; i < sourceData.length; i++) {
                var current = sourceData[i];
                if (type == "province") {
                    if (current.id == collectorSelectionFromCookie.province.id) {
                        return current;
                    }
                }
                if (type == "city") {
                    if (current.id == collectorSelectionFromCookie.city.id) {
                        return current;
                    }
                }
                if (type == "district") {
                    if (current.id == collectorSelectionFromCookie.district.id) {
                        return current;
                    }
                }
                if (type == "company") {
                    if (current.id == collectorSelectionFromCookie.company.id) {
                        return current;
                    }
                }
                if (type == "machine") {
                    if (current.machine_id == collectorSelectionFromCookie.machine.machine_id) {
                        return current;
                    }
                }
                if (type == "monitor") {
                    if (current.id == collectorSelectionFromCookie.monitor.id) {
                        return current;
                    }
                }
            }
        }
        return null;
    }

    return {
        getSelectedDataMapper: selectionMapper
    };
}]);

最后我们打开页面,看看加载的结果吧:

时间: 2024-10-23 04:18:54

物联网平台设计心得:五级联动及记忆恢复的相关文章

物联网平台设计心得:你所不知道的CRC校验

在物联网平台设计过程中,我的中间件一方面需要处理来自于硬件端的包,另一方面需要处理来自于用户端的包,用户端包括web端和手机端等等.所以编写一个统一的CRC认证是非常必须要. 那么,在设计开始,CRC认证到底是什么呢?所谓的CRC认证,就是指,在硬件端或者用户端进行数据传输前,通过一套算法,将待传输的数据,通过加验,算出其校验码,附加在包体的最后,然后中间件收到此包后,对包进行解析,拿出其中的数据内容部分,然后对包重新进行一次CRC加验,如果本次加验结果和包体附带的CRC校验码数据一致,那么就说

物联网平台设计心得:DateTimePicker实现选择联动

所谓的选择联动,就是指,当我DateTimePicker1选择2月4号的时候,我DateTimePicker2只能选择2月4号和2月5号两天,当然你可以自行规定要选择的日期.这在一些图表查询条件里面是很常用的一个功能.下面我们就来看看如何设计. DateTimePicker的选取与使用 在这里,我们使用的DateTimePicker是一个开源的组件,他的model名称为:ui.bootstrap.datetimepicker,我们可以去这个网址找到其相关的内容:http://dalelotts.

国内物联网平台初探(五):机智云IoT物联网云服务平台及智能硬件自助开发平台

国内物联网平台初探(五)——机智云IoT物联网云服务平台及智能硬件自助开发平台 马智 平台定位 机智云平台是致力于物联网.智能硬件云服务的开放平台.平台提供了从定义产品.设备端开发调试.应用开发.产测.运营管理等覆盖智能硬件接入到运营管理全生命周期服务的能力. 机智云平台为开发者提供了自助式智能硬件开发工具与开放的云端服务.通过傻瓜化的工具.不断增强的SDK与API服务能力最大限度降低了物联网硬件开发的技术门槛,降低研发成本,提升开发者的产品投产速度,帮助开发者进行硬件智能化升级,更好的连接.服

国外物联网平台初探(六):Electric Imp

国外物联网平台初探(六)--Electric Imp 马智 公司背景 Electric Imp成立于2011年,公司设立在美国加利福尼亚州洛斯阿尔托斯和英国剑桥 公司投资者包括:富士康技术集团.PTI创投.Rampart资本.Redpoint创投 ? 定位 ? Electric Imp提供的硬件.软件.操作系统.安全.API.管理工具和云端服务完全集成的创新型解决方案,能够减少产品上市时间和成本,并具备安全.可扩展和灵活的特性.Electric Imp助力实现创新性的商用和工业应用,使生产商能够

国外物联网平台初探(五):Exosite Murano

国外物联网平台初探(五)--Exosite Murano 马智 ? 定位 Murano是一个基于云的IoT软件平台,提供安全.可扩展的基础设施,支持端到端的生态系统,帮助客户安全.可扩展地开发.部署和管理应用.服务以及联网产品. ? 功能 Murano平台简化了整个IoT技术栈,可视为集成在一起的多个云软件层. Murano提供IoT基础设施.开发环境和功能集成,包括设备连接.产品管理.数据路由.服务集成(如data store/告警/第三方分析平台).应用开放API.用户认证/角色/权限和应用

Js 实现五级联动

js实现多级联动的方法很多,这里给出?种5级联动的例子,其实可以扩展成N级联动,在做项目的时候碰到了这样?个问题但是有不能从数据库中动态的加载这些选项,所以只有想办法从单个的页面着手来处理了,应为项目的表单是动态产生的,所以需要每个流程的设计过程中需要有单独的页面来处理,这样就决定了不能改变已有的业务逻辑来实现多级表单的联动.Code如下:<html><head><title>级联</title><meta http-equiv="Conte

国内首篇介绍JanOS物联网操作系统的文章 - 如何把你的手机主板打造成物联网平台

天地会珠海分舵注:如无意外,您现在正在看的将是国内首篇且是唯一一篇介绍炙手可热的物联网的操作系统JanOS的文章!不信你去百度!希望大家能喜欢.但本文只是引言,更多信息请还是访问JanOS的官网:http://janos.io/ JanOS 让你的手机瞬间变身成物联网平台 JanOS是一个设计成运行在你的手机芯片上的操作系统.它可以在没有屏幕的情况下跑起来,让你可以可以通过当今红得发紫的JavaScript的API来访问你的手机的所有功能,从打电话到照相功能无所不包. 你问我在搞毛? 当前炙手可

国内物联网平台初探(一):百度物接入IoT Hub

国内物联网平台初探(一) ——百度物接入IoT Hub 马智 物接入IoT Hub - 架构 全托管的云服务,帮助建立设备与云端之间安全可靠的双向连接 支撑海量设备的数据收集.监控.故障预测等各种物联网场景 物接入IoT Hub - 功能 通信协议:支持MQTT 数据安全:设备级认证.策略授权:双向安全连接.SSL传输 开发语言:支持多种开发语言.兼容主流硬件设备 支持C.C#.Python.Java.PHP等 支持CLI命令行工具(Python) 分析服务:对接百度大数据服务 物接入IoT H

物联网平台构架系列 (五):Amazon, Microsoft, IBM IoT 解决方案导论 之 安全

最近研究了一些物联网平台技术资料,以做选型参考.脑子里积累大量信息,便想写出来做一些普及.作为科普文章,力争通俗易懂,不确保概念严谨性.我会给考据癖者提供相关英文链接,以便深入研究. -- 冯立超 HiwebFrank 5. 安 全 我想用遥控器把隔壁邻居家的电视给关了! 不知是否可以,但至少,我拿着一个空调遥控器可以到各个房间开关空调. 如果物联网设备没有任何安全措施,那么状况将无法设想. 如何做到全方位安全? 微软早在2003年就提出了可信赖的计算 Trustworthy Computing