阅读更多

1顶
0踩

编程语言

原创新闻 YY游戏云的AngularJS实践

2016-04-15 10:57 by 主编 ITeye管理员 评论(1) 有6046人浏览
导语:本文主要介绍多玩YY在使用AngularJS开发云控制台前端框架过程中的点点滴滴。利用AngularJS,这套系统实现了与客户端相近的体验,并能同时保障代码架构清晰易维护。
为什么选择AngularJS
轻松构建单页面应用
可以说,这是我们最终选择AngularJS的重要原因,如果你希望构建一个结构清晰、可维护、开发效率高、体验好的单页应用,AngularJS是相当不错的框架。

单页面应用的魅力

什么是单页面应用?单页应用,指一种基于Web的应用或者网站,页面永远都是局部更新元素,而不是整页刷新,给用户的感觉就像整个网站都是一个页面。当用户点击某个菜单或者按键时,不会跳转到其他页面,前端会从后端获取对应页面的数据而不是HTML,之后在页面中需要更新内容的地方,局部动态刷新,而如果是传统的多页网站,当用户访问不同的页面时,服务器会直接返回一个HTML,然后浏览器负责将这个HTML展现给用户。目前,大部分云控制台,都是单页应用架构,单页应用能带来一种更近似客户端,而不是网页的体验。单页面应用网站,在体验方面,具有如下优点:
  • 做“页面跳转”时,永远都是局部动态刷新,用户不会感觉整个屏幕闪了一下,而仅仅是需要变化的区域做了局部刷新。例如两个不同的页面,假设页面元素都是一样的,只是元素中的文字不一样(例如每个页面都有一个面包屑,一排按钮及一个表格,这几个元素的布局也是一样的),当用户跳转到另外一个页面时,会看到整个页面并没有重新渲染,只是文字发生了变化。简单地说,这有点类似使用App,永远都是局部发生变化,你见过哪个App,当点击到不同的功能视图时,整个屏幕会白屏闪一下的么?
  • URL可收藏,可回退。如果浏览器的URL一直不变,那还不能称为真正的单页应用。不同的功能,不同的资源页面,对应的URL是不一样的。当用户跳转到另外的功能时,会发现URL会变成对应的值;通过回退键,也可以回到之前浏览的页面。这个特性有什么用呢?如果URL不会随着功能而变化,当用户刷新当前页面时,就会回到之前的默认页面,而不是预期的当前功能页面,同样的,URL也不具备可收藏性,因为点开之前收藏的URL,永远都是网站的默认页面。这对一些强交互的管控系统来说,体验不好。
  • 功能切换时快速流畅。快速流畅主要因为两个原因:一是页面都是局部刷新,从用户感官来说更快;二是和后台通信的内容,都是数据,而不是页面模板,请求量更少;而传统网站,在访问不同页面时,服务端返回的是HTML,体积更大,而且还需要一直重复加载JavaScript、CSS文件。
  • 因为网站的单页化,可以更好地使用全局类的交互(做页面切换时,需要一直保持不变的交互)。例如,页面上需要显示某次耗时操作的进度,例如上传文件进度,耗时操作的当前状态等,你可以在页面最右侧固定显示进度。当用户访问单页应用时,他会明白,当点击其他模块时,这个右侧的通知栏不会消失,会固定显示。而如果是多页网站,用户则会困惑,担心自己跳转到其他页面后,进度通知就会消失。


AngularJS是开发单页应用的利器

  • 单页面应用对于代码分层,结构清晰有更高的要求,而AngularJS是一个MVVM框架,其自身的约定,减少了我们写出“一锅粥”代码的可能性(在下面讨论“编写更易维护的代码”时会详述)。
  • AngularJS的著名第三方组件UI-Router,是一个控制页面路由的组件,它支持我们快速搭建单页应用(AngularJS本身的路由功能也可以,但功能会稍微弱一些)。
  • AngularJS的检查更新机制,使页面刷新时更加快速自然。 当数据“可能”发生变化时,AngularJS会检查出所有变化的元素,再“一次性”刷新所有变化的UI元素。


编写更易维护的代码
很多人经常会抱怨,不同水平的人凑在一起写JavaScript,到最后项目经常就是一锅粥,同一个JavaScript文件里面,各种各样的逻辑都混在一起,要增删功能,简直是恶梦。无规矩不成方圆。作为框架,AngularJS无疑能大大改善这种状况,使得项目整体的分层明了,职责清晰。在笔者看来,AngularJS能够帮助我们编写更易维护的代码,一是因为其“关注点分离”的理念,二是因为其强大的特性为项目节省了不少代码量,从而降低程序员犯错的概率。

关注点分离

关注点分离是AngularJS的一大设计哲学。所谓关注点分离,指的是各个逻辑层职责清晰明确。例如,当你需要修改甚至替换展现层时,无需关注业务层是怎么实现的。在AngularJS中,服务层(Ajax请求)- 业务层(Controller)- 展现层(HTML 模板)- 交互层(animation)这些都有对应的基础组件。不同组件职责不同,也很难将本属于B组件的职责放到A组件上去实现。举几个例子:

  • HTML及Controller需要协同工作,但职责分明。视图、交互层面的逻辑,例如展示隐藏某些元素,是HTML模板的职责,Controller只能用于数据初始化。如果你反其道而行,想在Controller中做HTML模板做的事情,将会非常别扭。这一点非常重要,传统的JavaScript代码,经常会出现的情况,就是JavaScript里面会有大量DOM操作的逻辑,同时还有大量数据操作相关的逻辑,这些逻辑耦合到一起,当需要单独重构数据层或者视图层时(例如项目UI改版),都会捉襟见肘,同时,由于JavaScript代码量的迅速膨胀,维护起来也会很麻烦。
  • 你无法将后台通信逻辑放到Controller中实现,而要放到Factory中。后台通信逻辑,一般要做成公用的。而由于Controller之间是不能相互调用的,所以你也不可能将后台通信逻辑放到其中一个Controller,然后其他Controller来调用这个Controller暴露的接口。唯一的办法,就是将后台通信逻辑放到Factory或者Service中。
  • Filter及Directive看似都可以用于数据转换,但实则不同。由于Filter只能做数据格式化,不支持引入模板,所以公用的UI交互,涉及到DOM元素或者需要引入HTML模板时时,也只能通过Directive来实现。

综上所述,AngularJS项目,其展现层、交互层的逻辑,都是在HTML或者指令中,服务层(后台通信),只适合出现在Factory(或者Service)中,而业务层则由Controller来负责。这样每层的逻辑都是轻薄的,而不是纠结在一起。 如果你只是要优化展示逻辑,那改改HTML就可以了,不用去管Controller是怎么写的。这一点我们有亲身体会。项目开发过程中,我们重构了视觉效果,所有的HTML都要重写。但在重构时,我们的Controller、后台通信(Service)、Filter基本都不用改,只要改HTML就行了。而如果项目是用jQuery写的,显然不可能做到,你需要重新为新的HTML增加一些可供jQuery选择器使用的class或id,然后需要在JavaScript里面绑定事件,根据新的CSS样式名来写新的交互效果,而在AngularJS上,有些不用做了(例如为了jQuery选择器,而为HTML元素增加新的class、id;在JavaScript中绑定事件),有些(例如交互效果)则只要改HTML就行,而不是改JavaScript。

AngularJS为我们省去的代码量

对于任何项目来说,代码臃肿、冗余是可维护性的天敌。因此,实现同样的功能,代码量越少,抽象度越高,冗余度越低,在某种程度上意味着项目更方便维护。而能减少代码量,也是AngularJS被推崇的一大优点。让我们来看看,它是如何减少了代码量的:

1.首先,作为一个大而全的框架(双刃剑,有利有弊),AngularJS提供的诸多特性,使我们可以更专注于业务代码的编写。

2.其次,AngularJS双向数据绑定的特性,将我们从大量的值绑定代码中解放出来。和jQuery对比,AngularJS不用为了选择某个元素,而刻意为HTML加上一些跟样式无关的class、2-2-2. id;不用写一堆从HTML元素中取值,设值的代码;不用在JavaScript代码中绑定事件;不用在JavaScript值发生变化时写代码去更新HTML对应的值。双向数据绑定,让我们告别很多简单无趣的绑定事件、绑定值的代码。

3.Directive、Filter、Factory等,天然的就是一个个可以复用的组件,减少了冗余重复代码。一些需要公用的逻辑,如果放在Controller中,都会相当别扭,就这样被AngularJS“逼着”,把公用逻辑都放到Directive、Filter、Factory中去。

开发心得总结
我理解的AngularJS基础组件
化繁为简,几大基础组件的使用场景

首先我们需要理清AngularJS几个组件的使用场景。AngularJS的一个毛病,就是新概念,新特性太多,新手一下子要了解这么多,学习曲线略陡。为了帮助大家理解,总结下我理解的几大组件使用场景。

1.请求资源与数据缓存的东西放进Service。Factory、Service本质上都是Provider的语法糖,两者只是使用方式有所不同,建议大家直接都用Service,ES6 class更容易,之后想平滑迁移到Angular2也会更容易,同时也能避免团队成员在选择Service还是Factory时产生困惑。

2.数据需要格式化的东西用Filter处理。例如把status值转化为中文值,把时间戳转成时间字符串之类。

3.需要公用的DOM操作,放在指令中去写。另外,如果需要引入jQuery组件,也可以写个指令把jQuery组件初始化代码放进去。

4.Controller与视图按照一对一的关系维护,在Controller内初始化Scope对象与在Scope上添加方法(行为),为ViewModel做赋值。其他所有过程都不应该出现在Controller中。Controller中不应该出现和页面展示、交互相关的代码。例如展示隐藏某些元素之类,这些应该是HTML模板或者指令负责。代码越薄越好。

5.全局常量值放到Constant。

指令(Directive)魔法

指令这个特性,用“魔法”一词来形容它,都不为过。

解决的痛点:一言以蔽之,指令提供了一套前端组件化的方法及约定,这使得编写,使用UI组件更加方便了。相对于jQuery,它解决了以下痛点:

1.动态生成了HTML元素后,不用再手动去为其加上JavaScript特性。举个例子:HTML原生的checkbox框比较丑,在jQuery时代,可以将checkbox替换成自定义的效果,如果是页面一开始就有的checkbox,我们可以在document.ready的时候调用自定义checkbox的初始化方法。但是,如果这个checkbox是动态生成的,在每个动态生成checkbox的地方,我们都得去调用checkbox的初始化方法,相当麻烦。但用了AngularJS的指令,就不会有这个问题了,只要在模板的chceckbox中加上指令,不管这个模板是动态变化的还是静态的,无需通过业务代码来逐个调用初始化方法,呈现给用户的,就已经是AngularJS替换后的checkbox效果。

2.一个组件的HTML和JavaScript,是一个整体,而不是割裂的(题外话,这一点React做得比Angular1.x还要好)。基于jQuery的UI组件,其引入方法,经常是这样的,首先,要求你自己copy一段指定的HTML,然后再调用初始化方法。而指令则支持定义对应的模板HTML,用户在引入时,可能只要写一个指令标签,就会自动生成N行的HTML及绑定对应的JavaScript效果。当然,理论上jQuery也能做到这样,但是会比Angular的实现麻烦许多。

3.应用、移除UI特性时方便直观。假设有这么一个需求,给一个普通输入框增加输入限制,只能输入特定字符(如字母数字),写好对应指令,只要给这个input输入框加上这个指令标签,就能马上应用这个特性,之后要移除,只要把标签去掉就好。相比之下,jQuery就会麻烦多。jQuery下,一般是通过元素选择器来绑定JavaScript效果。因此,在添加该特性时,你需要考虑给对应的输入框指定一个合适的元素选择器。移除特性时,你要考虑:有可能你在动态生成输入框的地方,都加了这些初始化代码,这些JavaScript都需要移除;如果元素选择器用的是class,得考虑是不是其他输入框也有这个class,如果是,那么移除代码时也会影响到其他输入框。

技巧

1.如果你迫不得已需要引入jQuery组件,你可以写一个指令把它包装起来,在该指令中初始化组件。

2.要注意require参数中的值是驼峰的,在HTML中就得转成对应的中划线命名,例如有require参数phoneKey,那么HTML中应为phone-key=”xxx”。虽然这个道理很浅显,但经常一不小心就会弄错了,然后发现在指令内部怎么着都拿不到require参数。

3.如果你在link中加了elm.bind(‘click’),当click回调函数中,作用域的值发生变化,记得调用scope.$apply(),否则值变化不会生效。

文件、目录约定
目录结构

第三方库、CSS、图片放置到哪个目录,不在本文讨论范围,这里略过。需要进一步说明的,是业务代码目录。


我们将系统自身的JavaScript、HTML模板都放在pages目录,其中子目录common放置公用的JavaScript及模板;其他子目录,以功能模块名作为目录名,然后将这个模块相关的JavaScript及模板放在其中。这样开发同个模块功能时,可以方便地在HTML及对应JavaScript之间切换。有些代码规范可能还会建议在模块这一级目录下,再根据AngularJS的几大组件Controller、Filter、Service等,创建不同的子目录,例如模块A/controller,模块A/service之类,我们则将所有JavaScript及HTML放在同一级,这样做主要有几个原因:

1.我们的项目,平均每个模块只有十来个文件,特别是每个模块一般只有一个Filter及Service,为了这一个文件创建一个目录,显得多此一举。

2.通过文件名,已经可以很方便地区分不同的JavaScript组件类型及HTML模板类型,同时,由于IDE一般会按照文件名字母排序,所以相同功能的JavaScript及HTML会挨在一起,查找对应的模板或JavaScript代码会方便很多。

文件名约定

这个约定对于Angular来说,特别重要。具体的约定是:



例如,为“防火墙”模块开发“创建防火墙”的功能,它的Controller,对应的JavaScript为:firewall.create.ctrl.js,对应的HTML模板为:

firewall.create.ctrl.HTML。为了文件名书写的方便,定义了组件的简写:controller -> ctrl ;factory,service -> svr ; filter-> fil ; directive -> dire。

这样约定有两个显而易见的优点:

1.通过文件名,就能知道对应模块、AngularJS基本组件类型、是模板HTML还是JavaScript 。

2.相同功能的JavaScript及HTML,会挨在一起(如果IDE是按照文件命名排序)。

与后端服务器通信
根据后台接口规范,结合AngularJS自身能力,我们做了一些封装,使接口请求逻辑变得非常简单。具体问题具体分析,先看看我们的后台接口的标准响应格式是怎样的,前端会按照这个接口返回格式做一些定制:
{
    errno:0,
    errmsg:"",
    data:[
       {
            id:"test",
            name:"test"    
        }
    ]
}

我们项目服务端的标准响应是一个json,通过errno描述此次请求的结果码,通过errmsg描述出错的原因(假如请求出错的话),通过data返回正常数据。

出错处理

当接口返回的errno!=0时,说明接口返回异常(系统异常或用户输入错误),这时我们希望能弹框提示用户“出错了”。显然,如果在每个接口请求逻辑中,都去写这个逻辑,会非常累赘,所幸AngularJS提供了拦截器的功能,我们只要写一个拦截器,就可以对所有的异常返回做统一处理。 首先,我们需要显式地抛出HTTP错误。因为当后台逻辑出错或者用户输入参数有误时,返回的HTTP状态码都是200(这只是我们项目的约定),AngularJS并不会认为200是出错的情况,因此,我们需要做点小动作。
$httpProvider.defaults.transformResponse.push(function (responseData) {
            if (responseData.errno != 0) {
                throw responseData;
            }
            ……
      });

AngularJS的$httpProvider.defaults.transformResponse.push(下面简称transformResponse)函数,可以统一处理所有的HTTP响应。在这里,我们就通过它捕获了所有errno!=0的请求,并往外抛一个exception。接着,我们需要在$httpProvider.interceptors捕获这个异常并弹框,代码如下:
$httpProvider.interceptors.push(function () {
  return {
     responseError: function (response) {
       if (response) {
          if (response.hasOwnProperty("errmsg")) {
              if (response.errno > 0) {
                                alert(response.errmsg);
            } else {
             alert("系统维护中,请稍候重试");
            }

         }
         else {
            if (response.status == 404) {
               alert("抱歉,后台服务出错,找不到对应的接口");
            }
            else {
                alert("抱歉,后台服务出错");
            }
          }
        }
       }
     }
    });

对$resource做进一步封装

项目中每个模块,都创建了对应的service文件,用于与后台进行通信。例如“硬盘”模块,对应DiskSvr,“防火墙“模块,对应FirewallSvr。这样划分后,前端所有的后台请求逻辑,找起来会很方便。

在封装后台通信逻辑时,我们用到$resource,这是AngularJS自身的一个组件,当你的后台接口符合RESTFul规范时,你可以很方便地使用resource和后台进行通信。而由于我们的后台并不是完整的RESTFul实现,我们需要做一些简单的封装。示意代码如下:
app.factory("DiskSvr", function () {

    var url = "schedule/disk";

    var customAPI = {
        clone: {
            method: "post"
        }
    }

    return getApi(url, customAPI);
});

//公用的,每个Svr都可以用
getApi = function (path, customAPI) {

    Angular.forEach(customAPI, function (value, key) {
        if (!value.url) {
            value.url = util.connectPath(path, key);
        } else {
            value.url = util.connectPath(path, value.url);
        }
    });

    //所有的
    var defaultAPI = {
        detail: {
            url: baseUrl + "/get"
        },
        delete: {
            url: baseUrl + "/delete",
            method: "delete"
        },
        create: {
            url: baseUrl + "/create",
            method: "post"
        },
        update: {
            url: baseUrl + "/update",
            method: "put"
        }
    }

    return $resource(path, {}, Angular.extend(defaultAPI, customAPI));
}

上面的代码,主要做了这些事情:

1.为所有的svr注入了每个模块接口都必备的,最基础的增删改查四个接口。这样就无需在每个svr中加入这些接口。例如,在业务逻辑中调用DiskSvr.create(),就会用post请求调用schedule/disk/create接口。

2.简化了新增接口的配置。新增一个接口,只要配置对应的HTTP方法及名字即可。

3.通过引用$resource组件、进一步封装及svr文件,在业务Controller中,不会看到任何的和后台通信的基础代码,如果在这个Controller中你需要和后台通信,你只需注入响应的svr,然后调用对应方法即可。

注入请求header头

在我们的项目中,约定了所有的请求都要在header中带上一些相同的信息,这对AngularJS来说,是非常简单的事情: 执行以下代码后,之后所有的HTTP请求都会带上名为project的header信息:



Controller间通信问题
Controller调用

假设controllerA希望调用controllerB的某个函数,告诉同伴Controller,我的某个你所关心的东西改变了,要怎么做呢?举具体业务场景,有两个Controller,一个是主页Controller,另外主页上有个弹框表单,这个弹框表单也有个Controller,用户成功提交了这个表单后,弹框Controller需要告知主页Controller,“哥们,请更新主页上的某项数据”。建议的做法,是用AngularJS的消息机制。例如,上面的例子中,弹框Controller是主页Controller的子Controller。那么弹框Controller可以往上冒泡传递消息:



其父Controller去捕获这个消息:



这是一种很好的解耦办法,假设这两个Controller是由两个开发负责的,那么我开发我的Controller,你开发你的,我不用去关心你那边的逻辑。

数据共享

多个Controller之间要共享数据,要怎么做呢? 最简单但也不推荐的一个做法,就是把数据塞到rootscope中,但是,这就像JavaScript的全局变量,野蛮不好控制。 这里推荐下我们的做法:写一个专门用于存储、设置共享数据的共享数据Facoty。在里面定义set方法,所有的共享变量,都需要经过set方法来设置。然后取数据则通过DATA变量获取。 伪代码如下:
app.factory('ShareSvr', function(){
    var shareData = {
        peopleNum
    }
    return {
        DATA:shareData,
        setPepleNum:function(num){
            shareData.peopleNum = num;
        }
    }
});

app.controller('TestController',function(ShareSvr){
    var self = this;
    this.DATA = ShareSvr.DATA;
}

这里并没有要求DATA值只能通过get方法获取,是为了之后在Controller对应的视图HTML中取值方便些。

第三方 库/资源 推荐
UI Router
路由(route),几乎所有的MVC框架都应该具有的特性,它是前端构建单页面应用(SPA)必不可少的组成部分。相比原生的ngRouter,UI Router功能更加强大,具备多视图,嵌套路由等特性,可以解决路由大部分的应用场景。

ngDialog
一个弹框控件,功能强大,我比较喜欢的地方,是它没有写死弹框的HTML、可以很方便地定义自己想要的弹框模板。例如,我们项目就通过它做了两种弹框,一种是普通弹框,一种是侧拉框(从屏幕右侧滑出,占满浏览器高度,宽度占满一半屏幕(或者其他自定义宽度)。

AngularJS代码规范
https://github.com/johnpapa/angular-styleguide/blob/master/a1/i18n/zh-CN.md
https://github.com/mgechev/Angularjs-style-guide/blob/master/README-zh-cn.md

Angular-filter
提供了很多实用的filter,string类、math类,集合类等。

w5c-validator
基于Angular.js原有的表单验证,统一验证规则和提示信息,在原有的基础上扩展了一些错误提示的功能,让大家不用在每个表单上写一些提示信息的模板,专心的去实现业务逻辑,国人出品。

ng-table
轻量,功能强大的表格组件。可以很方便地修改表格的样式、交互效果。

作者简介:李泽扬,在多玩YY负责升龙游戏云平台前端开发。在此之前曾任职于腾讯,主要技术栈为Java及前端,GitHub帐号为giantray。
责编:陈秋歌(chenqg@csdn.net)
本文为《程序员》原创文章,未经允许不得转载,更多精彩文章请订阅2016年程序员:http://dingyue.programmer.com.cn/
  • 大小: 50.8 KB
  • 大小: 16.8 KB
  • 大小: 15.7 KB
  • 大小: 14.8 KB
  • 大小: 18.9 KB
1
0
评论 共 1 条 请登录后发表评论
1 楼 hantsy 2016-04-17 10:51
完全不懂 REST。

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • YY游戏云的AngularJS实践(转载)

    为什么选择AngularJS轻松构建单页面应用可以说,这是我们最终选择AngularJS的重要原因,如果你希望构建一个结构清晰、可维护、开发效率高、体验好的单页应用,AngularJS是相当不错的框架。 单页面应用的魅力 什么是...

  • YY游戏云平台在AngularJS上的实践总结

    为了使前端能达到仿客户端体验,同时保障代码架构清晰规范,易维护,最终多玩YY选择了AngularJS(1.x)作为云控制台的前端框架。本文主要围绕AngularJS(1.x),介绍多玩YY在开发控制台过程中的点点滴滴。 为什么...

  • 程序员2016年4月:Spark核心技术与实践

    YY游戏云平台在AngularJS上的实践总结 (李泽扬(giantray),多玩YY升龙游戏云平台前端开发工程师) 深入了解Angular:ngModel绑定值不更改的解决技巧(雪狼、破狼、彭洪 伟) 百味 漫画——你的时间去哪了?...

  • 知乎上关于ReactNative的评论汇总(网友们有才哟...)

    近些年 Web 前端的开发越来越多的受到工程复杂度上升导致整体性能下降的困扰,所以最近几年的新型框架大多有一些独特的机制来提升性能,而这些机制大多是从 Native UI 或者游戏开发中借鉴来的,比如 AngularJS 中的...

  • 廖雪峰Python 2.X 教程

    Python简介Python是著名的“龟叔”Guido van Rossum在1989年圣诞节期间,为了打发无聊的圣诞节而编写的一个编程语言。当你用一种语言开始作真正的软件开发时,你除了编写代码外,还需要很多基本的已经写好的现成的...

  • 廖雪峰Python 3.X 教程

    Python简介 Python是著名的“龟叔”Guido van Rossum在1989年圣诞节期间,为了打发无聊的圣诞节而编写的一个编程语言。 现在,全世界差不多有600多种编程语言,但流行的编程语言也就那么20来种。...

  • 基于SSM+JSP+HTML的东风锻造有限公司重大停管理系统(Java毕业设计,附源码,数据库,教程).zip

    Java 项目, Java 毕业设计,Java 课程设计,基于 ssm 开发的,含有代码注释,新手也可看懂。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 包含:项目源码、数据库脚本、软件工具等,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行! 1. 技术组成 前端:jsp 后台框架:SSM 开发环境:idea 数据库:MySql(建议用 5.7 版本,8.0 有时候会有坑) 数据库工具:navicat 部署环境:Tomcat(建议用 7.x 或者 8.x 版本), maven 2. 部署 如果部署有疑问的话,可以找我咨询 Java工具包下载地址: https://pan.quark.cn/s/eb24351ebac4

  • 数据库系统课程设计报告-体育项目比赛管理系统设计与开发

    一、系统需求分析 1 (一)需求概述 1 (二)业务流分析 1 从运动员角度分析 1 (三)数据流分析 4 (四)数据字典 5 二、数据库概念结构设计 6 (一)实体分析 6 (二)属性分析 6 (三)联系分析 8 (四)概念模型分析(.PDM图) 9 三、数据库逻辑结构设计 9 (一)概念模型转化为逻辑模型 9 1.一对一关系的转化 9 2.一对多关系的转化 9 3.多对多关系的转化 10 (二)逻辑模型设计(.PDM图) 10 四、 数据库物理实现(一)表设计 10 (一)表设计 10 (二)创建表和完整性约束代码设计 11 五、数据库功能调试 15 (一)运动员管理模块 15 (二)负责人管理模块 16 (三)系统管理员管理模块 17 六、设计系统前台软件 21 (一)开发软件选择 21 (二)软件功能要求与设计 22 (三)软件功能实现 22 (四)系统测试 24 七、设计总结 27

  • 基于SSM+JSP的文物管理系统+数据库(Java毕业设计,包括源码,教程).zip

    Java 项目, Java 毕业设计,Java 课程设计,基于 SpringBoot 开发的,含有代码注释,新手也可看懂。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 包含:项目源码、数据库脚本、软件工具等,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行! 1. 技术组成 前端:jsp 后台框架:SSM 开发环境:idea 数据库:MySql(建议用 5.7 版本,8.0 有时候会有坑) 数据库工具:navicat 部署环境:Tomcat(建议用 7.x 或者 8.x 版本), maven 2. 部署 如果部署有疑问的话,可以找我咨询 Java工具包下载地址: https://pan.quark.cn/s/eb24351ebac4

  • 智慧园区整体解决方案-37PPT(46页).pptx

    智慧园区,作为现代化城市发展的新兴模式,正逐步改变着传统园区的运营与管理方式。它并非简单的信息化升级,而是跨越了行业壁垒,实现了数据共享与业务协同的复杂运行系统。在智慧园区的构建中,人们常常陷入一些误区,如认为智慧园区可以速成、与本部门无关或等同于传统信息化。然而,智慧园区的建设需要长期规划与多方参与,它不仅关乎技术层面的革新,更涉及到管理理念的转变。通过打破信息孤岛,智慧园区实现了各系统间的无缝对接,为园区的科学决策提供了有力支持。 智慧园区的核心价值在于其提供的全方位服务与管理能力。从基础设施的智能化改造,如全面光纤接入、4G/5G网络覆盖、Wi-Fi网络及物联网技术的运用,到园区综合管理平台的建设,智慧园区打造了一个高效、便捷、安全的运营环境。在这个平台上,园区管理方可以实时掌握运营动态,包括道路状况、游客数量、设施状态及自然环境等信息,从而实现事件的提前预警与自动调配。同时,智慧园区还为园区企业提供了丰富的服务,如项目申报、资质认定、入园车辆管理及统计分析等,极大地提升了企业的运营效率。此外,智慧园区还注重用户体验,通过信息发布系统、服务门户系统及各类智慧应用,如掌上营销、智慧停车、智能安防等,为园区员工、企业及访客提供了便捷、舒适的生活与工作体验。值得一提的是,智慧园区还充分利用大数据、云计算等先进技术,对园区的能耗数据进行采集、分析与管理,实现了绿色、节能的运营目标。 在智慧园区的建设过程中,还涌现出了许多创新的应用场景。例如,在环境监测方面,智慧园区通过集成各类传感器与监控系统,实现了对园区水质、空气质量的实时监测与预警;在交通管理方面,智慧园区利用物联网技术,对园区观光车、救援车辆等进行实时定位与调度,提高了交通效率与安全性;在公共服务方面,智慧园区通过构建统一的公共服务平台,为园区居民提供了包括平安社区、便民社区、智能家居在内的多元化服务。这些创新应用不仅提升了园区的智能化水平,还为园区的可持续发展奠定了坚实基础。同时,智慧园区的建设也促进了产业链的聚合与发展,通过搭建聚合产业链平台,实现了园区内企业间的资源共享与合作共赢。总的来说,智慧园区的建设不仅提升了园区的综合竞争力,还为城市的智慧化发展树立了典范。它以用户需求为导向,以技术创新为驱动,不断推动着园区向更加智慧、高效、绿色的方向发展。对于写方案的读者而言,智慧园区的成功案例与创新应用无疑提供了宝贵的借鉴与启示,值得深入探索与学习。

  • Java毕业设计-SpringBoot+Vue的基于SpringBoot的冬奥会科普平台(附源码、数据库、教程).zip

    Java 项目, Java 毕业设计,Java 课程设计,基于 SpringBoot 开发的,含有代码注释,新手也可看懂。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 包含:项目源码、数据库脚本、软件工具等,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行! 1. 技术组成 前端:html、javascript、Vue 后台框架:SpringBoot 开发环境:idea 数据库:MySql(建议用 5.7 版本,8.0 有时候会有坑) 数据库工具:navicat 部署环境:Tomcat(建议用 7.x 或者 8.x 版本), maven 2. 部署 如果部署有疑问的话,可以找我咨询 Java工具包下载地址: https://pan.quark.cn/s/eb24351ebac4 后台路径地址:localhost:8080/项目名称/admin/dist/index.html 前台路径地址:localhost:8080/项目名称/front/index.html (无前台不需要输入)

  • MATLAB设计的芯片字符识别(GUI界面设计).zip

    MATLAB设计的芯片字符识别(GUI界面设计)

  • 【工程项目】MATLAB口罩识别[自动定位颜色,多人检测,未戴预警 ].zip

    【工程项目】MATLAB口罩识别[自动定位颜色,多人检测,未戴预警 ]

  • 基于SSM+JSP的雅博书城在线系统+数据库(Java毕业设计,包括源码,教程).zip

    Java 项目, Java 毕业设计,Java 课程设计,基于 SpringBoot 开发的,含有代码注释,新手也可看懂。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 包含:项目源码、数据库脚本、软件工具等,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行! 1. 技术组成 前端:jsp 后台框架:SSM 开发环境:idea 数据库:MySql(建议用 5.7 版本,8.0 有时候会有坑) 数据库工具:navicat 部署环境:Tomcat(建议用 7.x 或者 8.x 版本), maven 2. 部署 如果部署有疑问的话,可以找我咨询 Java工具包下载地址: https://pan.quark.cn/s/eb24351ebac4

  • 基于SpringBoot+Vue的校园疫情防控系统 (2)(Java毕业设计,包括源码、数据库、教程).zip

    Java 项目,仅供学习参考。 Java 毕业设计,Java 课程设计,基于 SpringBoot 开发的,含有代码注释,新手也可看懂。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 包含:项目源码、数据库脚本、软件工具等,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行! 1. 技术组成 前端:html、javascript、Vue 后台框架:SpringBoot 开发环境:idea 数据库:MySql(建议用 5.7 版本,8.0 有时候会有坑) 数据库工具:navicat 部署环境:Tomcat(建议用 7.x 或者 8.x 版本), maven 2. 部署 如果部署有疑问的话,可以找我咨询 Java工具包下载地址: https://pan.quark.cn/s/eb24351ebac4 后台路径地址:localhost:8080/项目名称/admin/dist/index.html 前台路径地址:localhost:8080/项目名称/front/index.html (无前台不需要输入)

  • 2007-2023年 省级-工业机器人安装密度.rar

    工业机器人安装密度通常指的是单位面积或单位人口所拥有的工业机器人数量。这一指标能够直观地反映出一个地区或国家工业机器人的普及程度和使用情况。 本数据参照康茜(2021)和芦婷婷(2021)的方法,根据IRF联盟公布的中国各行业工业机器人安装量(IFR公布的14个大类,对应国民经济行业分类与代码(GB/4754-2011)中13-43的细分行业代码),然后从《中国劳动统计年鉴》里面收集细分行业各个省份的就业人数占全国总就业人数的百分比,工业机器人安装密度=各个省份的就业人数占全国总就业人数的百分比×全国各行业机器人安装数量。 数据 年份、省份、省份代码、所属地域、工业机器人安装密度(台) 参考文献:[1]康茜,林光华.工业机器人与农民工就业:替代抑或促进[J].山西财经大学学报,2021,43(02):43-56. [2]芦婷婷,祝志勇.人工智能是否会降低劳动收入份额——基于固定效应模型和面板分位数模型的检验[J].山西财经大学学报,2021,43(11):29-41. [3]闫雪凌,朱博楷,马超.工业机器人使用与制造业就业:来自中国的证据[J].统计研究,2020,37(01):74-87. [4]王永钦,董雯.机器人的兴起如何影响中国劳动力市场?——来自制造业上市公司的证据[J].经济研究,2020,55(10):159-175.

  • 2006-2023年 地级市-绿色全要素生产率.rar

    绿色全要素生产率(Green Total Factor Productivity,GTFP)是一个综合考虑环境因素的生产效率指标,旨在更全面地评估经济发展的可持续性和环境友好性。通过提升绿色全要素生产率,可以促进资源的有效利用、环境保护和可持续发展。 本数据通过将劳动、资本等生产要素的投入与地区生产总值(GDP)作为合意产出相联系,同时考虑工业二氧化硫、烟粉尘和废水等非合意的环境排放,采用如SBM-Malmquist-Luenberger指数法等计量手段进行测算。这种方法不仅评估了生产效率的改善情况,还反映了技术进步和环境管理在促进绿色增长方面的作用。 参考文献:排污权交易制度与能源利用效率 -对地级及以上城市的测度与实证 数据 年份、城市、超效率SBM、超效率CCR

  • 航空航天领域翼型振动与颤振分析的MATLAB仿真程序实现及应用

    内容概要:本文档详细记录了一段用于进行航空器机翼加装挂载(如导弹或其他装备)后的结构动力响应分析,特别是对颤振现象研究的 MATLAB 代码片段。主要内容涵盖初始化几何参数、物性参数以及质量特性等基本信息设定,通过定义多个矩阵(弯曲模式、扭转模式)用以描述系统运动方程的形式表达;采用Theodorsen函数表征气动力特性对于系统稳定性的影响;最终利用模态分析确定临界速度并给出最小颤振速率发生位置的相关讨论与实验数据对比验证。 适合人群:航空航天专业研究人员,工程物理学者及高等院校飞行器设计方向研究生及以上水平的技术爱好者。 使用场景及目标:①理解机翼与附加载体之间的动态交互机制;②掌握利用数学工具进行复杂机械系统的稳定性判断方法;③为实际产品研发提供理论依据和技术支持。 其他说明:文档中的部分内容已被省略以保护原创版权,同时确保敏感算法细节不在未经授权的情况下传播。由于文中涉及到大量的矩阵运算以及高级工程力学概念,请在使用前确认自己拥有足够的前置知识。

  • MATLAB 界面指纹识别MATLAB(GUI界面,比对两幅指纹)(构架).zip

    MATLAB 界面指纹识别MATLAB(GUI界面,比对两幅指纹)(构架)

Global site tag (gtag.js) - Google Analytics