举个栗子,比如说我现在要做bmob的college表的增删改查功能,应该怎么做呢,按照以下的顺序:
1.在views/manage下新建一个文件叫做bmobcollegeUsersList.ejs的UI文件,里面的代码如下,这里就是要注意第一行的ng-controller,自己取一个名字,比如我叫做bmobcollegeUsersList。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
<br /> <div class="row" ng-controller="bmobcollegeUsersList" > <% include public/modal %> <div class="col-xs-12"> <div class="panel"> <% include public/tableTool %> <div class="pull-right"> <% include public/searchBox %> </div> </div> <div class="box"> <div class="box-body table-responsive no-padding" > <table class="table table-hover"> <tr> <th><input type="checkbox" class="mini" id="selectAll"/></th> <th>学工号[u]</th> <th>是否绑定[v]</th> <th>姓名[n]</th> <th>性别[g]</th> <th>院系部门[f]</th> <th>读者类型[k]</th> <th>修改时间[t]</th> <th>操作</th> </tr> <tr class="datalist" ng-repeat="user in data"> <td><input type="checkbox" name="listItem" class="mini" value="{{user.objectId}}" ng-click="getNewIds()"/></td> <td class=" sorting_1">{{user.studentid}}</td> <td ng-switch on="user.occupied"> <span ng-switch-when="true">是</span> <span ng-switch-when="false">否</span> </td> <td class=" ">{{user.username}}</td> <td class=" ">{{user.gender}}</td> <td class=" ">{{user.faculty}}</td> <td ng-switch on="user.status"> <span ng-switch-when="0">本科生</span> <span ng-switch-when="1">研究生</span> <span ng-switch-when="2">博士生</span> <span ng-switch-when="3">博士后</span> <span ng-switch-when="4">教师</span> <span ng-switch-when="5">其他</span> <span ng-switch-when="6">行政人员</span> <span ng-switch-when="7">管理员</span> </td> <td class=" ">{{user.updatedAt | date : "yyyy-MM-dd HH:mm:ss"}}</td> <td class=" "> <button class="btn btn-primary btn-xs" data-whatever="{{user.objectId}}" data-toggle="modal" data-target="#addNewRegUser"><span class="fa fa-fw fa-edit" aria-hidden="true"></span>编辑</button> <button class="btn btn-default btn-xs" ng-click="delOneItem(user.objectId)"><span class="fa fa-fw fa-trash-o" aria-hidden="true"></span>删除</button> </td> </tr> </table> </div><!-- /.box-body --> <% include public/tableFooter %> </div><!-- /.box --> </div><!-- /.col --> <!--添加新用户模态窗口--> <div class="modal fade" id="addNewRegUser"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title">修改用户学号信息</h4> </div> <div class="modal-body"> <form role="form" class="form-horizontal" name="myForm" ng-submit="processForm(myForm.$valid)" novalidate> <div class="form-group"> <label class="control-label col-sm-4">用户名</label> <div class="col-sm-6"> <p class="form-control-static text-primary">{{formData.username}}</p> <!--<input type="text" class="form-control" name="nickName" ng-minlength="5" ng-maxlength="12" ng-pattern="/^[a-zA-Z][a-zA-Z0-9_]{4,11}$/" ng-model="formData.nickName" required/>--> <!--<label for="inputError" class="control-label text-danger" ng-show="myForm.nickName.$invalid && !myForm.nickName.$pristine"><i class="fa fa-times-circle-o"></i> 5-12个英文字符</label>--> </div> </div> <div class="form-group"> <label class="control-label col-sm-4">学工号</label> <div class="col-sm-6"> <input type="text" class="form-control" name="studentid" ng-minlength="2" ng-maxlength="15" ng-model="formData.studentid" required/> <label for="inputError" class="control-label text-danger" ng-show="myForm.studentid.$invalid && !myForm.studentid.$pristine"><i class="fa fa-times-circle-o"></i>请填入2-15位数字</label> </div> </div> <div class="form-group hide"> <label class="control-label col-sm-4">学号绑定情况</label> <div class="col-sm-6"> <div class="dropdown"> <button id="dLabel" type="button" data-toggle="" aria-haspopup="true" aria-expanded="false" required> <i id="categoryName">{{formData.occupied}}</i> <span class="caret"></span> </button> <ul class="dropdown-menu" role="menu" name="occupied" aria-labelledby="dLabel" id="groupTree" class="ztree"> <li ><a href="#">true</a></li> <li ><a href="#">false</a></li> </ul> </div> </div> </div> <div class="form-group"> <label class="control-label col-sm-4">学号绑定情况</label> <div class="col-sm-6"> <input type="text" class="form-control" name="occupied" ng-model="formData.occupied" required/> <label for="inputError" class="control-label text-danger" ng-show="myForm.occupied.$invalid && !myForm.occupied.$pristine"><i class="fa fa-times-circle-o"></i>已绑定请填true,未绑定请填false</label> </div> </div> <div class="form-group"> <label class="control-label col-sm-4">姓名</label> <div class="col-sm-6"> <input type="text" class="form-control" name="username" ng-model="formData.username" required/> <label for="inputError" class="control-label text-danger" ng-show="myForm.username.$invalid && !myForm.username.$pristine"><i class="fa fa-times-circle-o"></i>请填写该用户姓名</label> </div> </div> <div class="form-group"> <label class="control-label col-sm-4">性别</label> <div class="col-sm-6"> <input type="text" class="form-control" name="gender" ng-model="formData.gender" required/> <label for="inputError" class="control-label text-danger" ng-show="myForm.gender.$invalid && !myForm.gender.$pristine"><i class="fa fa-times-circle-o"></i>请填写男或女</label> </div> </div> <div class="form-group"> <label class="control-label col-sm-4">院系部门</label> <div class="col-sm-6"> <input type="text" class="form-control" name="faculty" ng-model="formData.faculty" required/> <label for="inputError" class="control-label text-danger" ng-show="myForm.faculty.$invalid && !myForm.faculty.$pristine"><i class="fa fa-times-circle-o"></i>请填写该用户所在院系</label> </div> </div> <div class="form-group"> <label class="control-label col-sm-4">读者类型</label> <div class="col-sm-6"> <input type="text" class="form-control" name="status" ng-model="formData.status" required/> <label for="inputError" class="control-label text-danger" ng-show="myForm.status.$invalid && !myForm.status.$pristine"><i class="fa fa-times-circle-o"></i>请填写该用户的类型(数字0-7)</label> </div> </div> <div class="modal-footer"> <button type="submit" class="btn btn-primary" ng-disabled="myForm.$invalid">提交</button> </div> </form> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal --> </div><!-- /.row --> </div> |
2.建立好后到controller.js中加一个控制器,其实这个controller只要改一下对应的ng-controller的名字就好了,其他的都不用变。比如我下面这个其实是复制DoraCMS原来会员管理的控制器,只是改了第一行的regUsersList为bmobcollegeUsersList。里面的分别是页面显示,删除条目,修改条目,新增条目的控制器,这些都是不用变的,全部可以直接复用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<br /> //学号信息管理 doraApp.controller("bmobcollegeUsersList",['$scope','$http','pageData','getItemService',function($scope,$http,pageData,getItemService){ $scope.formData = {}; console.log("dada"); //获取注册用户列表信息 initPagination($scope,$http); // 删除用户 initDelOption($scope,$http,'您确认要删除选中的会员吗?'); // 修改用户 $('#addNewRegUser').on('show.bs.modal', function (event) { var obj = $(event.relatedTarget); var editId = obj.data('whatever'); // 如果不为空则为编辑状态 if(editId){ getItemService.itemInfo(pageData.bigCategory,editId).success(function(result){ $scope.formData = result; $scope.targetID = editId; }) }else{ $scope.formData = {}; } }).on('hidden.bs.modal', function (e) { // 清空数据 clearModalData($scope,$(this)); }); // 添加新用户或修改用户 $scope.processForm = function(isValid){ angularHttpPost($http,isValid,getTargetPostUrl($scope,pageData.bigCategory),$scope.formData,function(data){ initPagination($scope,$http); }); }; }]); |
3.然后我们以获取用户列表的修改举例,首先到dora.backstage.js文件看initPagination的定义,进去之后发现与getPageInfos函数有关,而它实际上是启动了一个地址为/admin/manage/getDocumentList/的路由,前面这些我们都不用变动,我们到admin.js的文件中看这个路由的定义如下,我们就是在这里下功夫该,首先我在携带可能的查询条件中添加了if(targetObj=="bmobUser")和if(targetObj=="college")的情况,后面要对其他的表做增删改查在这里添加即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
<br />router.get('/manage/getDocumentList/:defaultUrl',function(req,res){ var targetObj = adminFunc.getTargetObj(req.params.defaultUrl); var params = url.parse(req.url,true); var keywords = params.query.searchKey; var area = params.query.area; var keyPr = []; var querystring; //携带可能的查询条件 if(keywords){ var reKey = new RegExp(keywords, 'i'); if(targetObj == Content){ keyPr.push({'comments' : { $regex: reKey } }); keyPr.push({'title' : { $regex: reKey } }); }else if(targetObj == AdminUser){ keyPr = {'userName' : { $regex: reKey} }; }else if(targetObj == User){ keyPr.push({'userName' : { $regex: reKey } }); keyPr.push({'name' : { $regex: reKey } }); }else if(targetObj == ContentTags){ keyPr.push({'alias' : { $regex: reKey } }); keyPr.push({'name' : { $regex: reKey } }); }else if(targetObj == Ads){ keyPr.push({'name' : { $regex: reKey } }); }else if(targetObj=="bmobUser"){//获得bmobUser表的查询条件 switch(keywords.slice(0,1)){//获得关键词的第一个字符,是不同的字母时查询不同的列 case "u"://u 查询用户学号 querystring = {"username":keywords.slice(1)}; break; case "U"://U 查询用户学号 querystring = {"username":keywords.slice(1)}; break; case "k"://k 用户类型 querystring = {"emailVerified":Boolean(parseInt(keywords.slice(1)))};//这里要注意转化为bool型 break; case "K"://K 用户类型 querystring = {"emailVerified":Boolean(parseInt(keywords.slice(1)))}; break; case "n"://u 用户姓名 querystring = {"nickName":keywords.slice(1)}; break; case "N"://U 用户姓名 querystring = {"nickName":keywords.slice(1)}; break; case "v"://v 违规次数为这个值的显示 querystring = {"violation":parseInt(keywords.slice(1))};//这里要注意转成int型 break; case "V"://V 违规次数大于这个值的显示,例如我传的参数是V1,那么大于1的,比如2次,3次的都会显示出来 querystring = {"violation":{"$gte":parseInt(keywords.slice(1))}};//大于这个数字的人全部显示 break; case "e"://e 邮箱 querystring = {"email":keywords.slice(1)}; break; case "E"://E 邮箱 querystring = {"email":keywords.slice(1)}; break; case "t"://t 注册时间 querystring = {"createdAt":keywords.slice(1)}; break; case "T"://T 注册时间 querystring = {"createdAt":keywords.slice(1)}; break; default://其他情况下关键字直接解读,并且只查询username列,即学号列。 querystring = {"username":keywords}; break; }; }else if(targetObj=="college"){//获得college表的查询条件 switch(keywords.slice(0,1)){//获得关键词的第一个字符,是不同的字母时查询不同的列 case "s"://s 查询用户学校 querystring = {"school":keywords.slice(1)}; break; case "S"://S 查询用户学校 querystring = {"school":keywords.slice(1)}; break; case "f"://s 查询用户学院部门 querystring = {"faculty":keywords.slice(1)}; break; case "S"://S 查询用户学院部门 querystring = {"faculty":keywords.slice(1)}; break; case "p"://s 查询用户专业 querystring = {"profession":keywords.slice(1)}; break; case "P"://S 查询用户专业 querystring = {"profession":keywords.slice(1)}; break; case "u"://u 查询用户学号 querystring = {"studentid":keywords.slice(1)}; break; case "U"://U 查询用户学号 querystring = {"studentid":keywords.slice(1)}; break; case "k"://k 用户类型 querystring = {"status":keywords.slice(1)};//这里要注意转化为bool型 break; case "K"://K 用户类型 querystring = {"status":keywords.slice(1)}; break; case "n"://u 用户姓名 querystring = {"username":keywords.slice(1)}; break; case "N"://U 用户姓名 querystring = {"username":keywords.slice(1)}; break; case "v"://v 是否验证 querystring = {"occupied":Boolean(parseInt(keywords.slice(1)))};//这里要注意转成int型 break; case "V"://V 是否验证 querystring = {"occupied":Boolean(parseInt(keywords.slice(1)))};//大于这个数字的人全部显示 break; case "g"://g 性别 querystring = {"gender":keywords.slice(1)}; break; case "G"://G 性别 querystring = {"gender":keywords.slice(1)}; break; case "t"://t 修改时间 querystring = {"updatedAt":keywords.slice(1)}; break; case "T"://T 修改时间 querystring = {"updatedAt":keywords.slice(1)}; break; default://其他情况下关键字直接解读,并且只查询username列,即学号列。 querystring = {"studentid":keywords}; break; }; } } if(targetObj=="bmobUser"||targetObj=="college"){//显示bmob数据库的数据 DbOpt.bmobpagination(targetObj,req, res,querystring); }else{ keyPr = adminFunc.setQueryByArea(req,keyPr,targetObj,area); console.log('Keypr'+keyPr); DbOpt.pagination(targetObj,req, res,keyPr); } }); |
4.在上面的最后一个if判断中,实际上就是判断我这个页面对应的内容是不是和bmob有关的,如果是,我们就调用bmobpagination函数来显示,bmobpagination我已经写好了,大家可以看一下里面的逻辑,是所有的bmob表都可以直接复用的,基本不用修改。而如果当前页面的内容是他mondb数据库的,与bmob无关,就继续调用他的pagination执行数据库操作。
5.最后修改bmobcollegeUsersList.ejs让它正常显示数据库得到的结果即可。
6.总结一下:其实我们增加一个功能,只需要增加一个对应的controller,然后找到admin.js的路由,在路由里添加一下判断条件,最后用 Dbopt.js中我们写的数据库操作的函数来进行交互就行,非常简单,这也是代码高度复用的好处。我们写Dbopt.js的函数的时候要注意保证代码的可复用性,即能同时处理多个库的请求,比如我写的bmoboagination函数,传入的参数是querystring,是在前面的路由里就由keywords得到的,我根据obj的不同生成不用的queryurl,所以这一个函数可以满足所有bmob表的显示,大家只需要把querystring确定好之后调用就可以了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
<br /> //bmobuser表的显示 bmobpagination : function(obj,req,res,querystring){ var params = url.parse(req.url,true); var startNum = (params.query.currentPage - 1)*params.query.limit + 1; var currentPage = Number(params.query.currentPage); var limit = Number(params.query.limit); var pageInfo; var queryurl; if(obj=="bmobUser"){//user类的query用这个格式 queryurl = 'https://api.bmob.cn/1/users'; }else{ queryurl = 'https://api.bmob.cn/1/classes/'+obj; } if(querystring){//判断是否传递了关键词 queryurl = queryurl+'?where='+encodeURI(JSON.stringify(querystring)); } var options = { url: queryurl, method:"GET", headers: { "X-Bmob-Application-Id": "*******************************", "X-Bmob-REST-API-Key": "*******************************", }, }; function callback(error, response, body) { if (!error && response.statusCode == 200) { var info = JSON.parse(body); pageInfo = { "totalItems" : info.results.length, "currentPage" : currentPage, "limit" : limit, "startNum" : Number(startNum) }; //console.log(info.results); //console.log('dadamemeda'); //console.log(pageInfo); return res.json({ docs : info.results.slice(startNum - 1,startNum + limit -1), pageInfo : pageInfo }); } } request(options, callback); }, |