00沒有抱怨的世界
周末效率好低,兩天沒更了,看看這看看那,裝了個win10發現觸摸板驅動不適配,然后找了好久都不行,23333。
AngularJS用的時間很短,高級的用法有點吃不消了,$digest,$watch這種東西的原理看起來好吃力啊,后面還有大把大把的需求要用這個來做了#¥@%#@!
01.先看看效果吧
這里的所有數據相關信息都是直接配置到DB的,作為元數據,包括搜索條件,顯示方式,數據過濾器等等,配置目前只實現了幾個,加的配置越多,能適用的業務就越廣。數據本身也是在DB的,在后台簡單的實現了控制Collection級別CRUD權限的功能。

輸入條件搜索之后:

dtGrid小廣告^_^
AngularJS有一款非常好的表格插件Angular ui-grid。但是奈何在高牆之上,API不好找,於是本人找到了一款國內非常不錯的表格插件DtGrid。這個插件是基於jQuery寫的,而jQuery和Angular的兼容性又非常棒,於是稍加改造就可以用在Angular環境下了。
這里有詳細的文檔和實例,www.dtGrid.com,
10.前端"實現"
html部分定義了一個<div ng-dt-grid id="user"></div>用於讓Angular執行指令,默認的屬性級指令等等參數都不用寫了,直接link執行操作。實現打引號也是因為很多配置都沒有實現,打算先把分頁做了。
↑ 分割線 ↑
var comDirective = angular.module('comDirective', []); //依賴這個模塊的controller均會編譯這條指令
comDirective.directive("ngDtGrid",function(){
return {
/* template : "<div id='toolbar'></div>", //not a good impl */ //第一版,先實現多條件查詢和展示,很多dtGrid附帶的功能還沒有完全移植,慢慢來
link : function(scope, element, attrs, ctrl){
$.post('/displayData/'+ attrs.id,{},function(data){ //先去根據要顯示的數據集去后台拿這個數據集的配置
if(!!data._id) {
scope.metaData = data;
scope.data = [];
scope.init = true;
/**
* init data grid
* */
var dtGridColumns = [];
$.each(data.columns,function(obj){
dtGridColumns.push({
id:data.columns[obj].columnName,
title:data.columns[obj].displayName,
type: data.columns[obj].dataType == "date"? data.columns[obj].dataType : "string",
columnClass:'text-center'
});
});
var dtGridOption = { //dtGrid核心配置
lang : 'zh-cn',
ajaxLoad : false,
datas : scope.data,
columns : dtGridColumns,
gridContainer : data._id,
pageSize : 20,
pageSizeLimit : [10, 20, 50]
};
scope.grid = $.fn.DtGrid.init(dtGridOption); //顯示到DOM上 (dtGrid 插件的用法 $.fn.DtGrid.init)
scope.grid.refresh();
$("#search-"+data._id).click(function(){ //定義的數據搜索條件的一些配置,比如這個搜索條件是字符串還是日期還是選擇下拉框等等,這里提取搜索條件
var criteria = {};
$.each(data.columns,function(col){
if(data.columns[col].searchable) {
var fieldVal = null;
var fieldType = data.columns[col].dataType;
var colName = data.columns[col].columnName;
if(fieldType == 'date') {
var dateFrom = $("#"+data.columns[col].columnName + "From").val();
var dateTo = $("#"+data.columns[col].columnName + "To").val();
criteria[colName] = {};
if(dateFrom.length != 0) criteria[colName].$gt = new Date(dateFrom).getTime();
if(dateTo.length != 0) criteria[colName].$lt = new Date(dateTo).getTime();
} else {
fieldVal = $("#"+data.columns[col].columnName).val().replace(/\s+/,"");
if(fieldType == 'array') {
if(fieldVal.split(/[,|,|;|;]/).length != 0) {
var optionsObj = [];
var tempArray = fieldVal.split(/[,|,|;|;]/);
for(var i = 0;i< tempArray.length;i++) {
if(tempArray[i].trim().length != 0) { var tempObj = {}; tempObj[colName] = tempArray[i];
optionsObj.push(tempObj); }
}
if(!criteria.$and) {
criteria.$and = [];
}
if(optionsObj.length != 0) criteria.$and.push({$or:JSON.stringify(optionsObj)});
}
} else if(fieldType instanceof Object) {
if(fieldType.multiSelect) {
//todo append $or options to $and property
if(fieldVal.length != 0)
criteria[colName] = fieldVal;
} else {
if(fieldVal.length != 0)
criteria[colName] = fieldVal;
}
} else {
if(fieldVal.length != 0)
criteria[colName] = fieldVal;
}
}
}
});
$.get("/collection/"+data._id, //數據接口,把MongoDB封裝了REST接口,分頁暫時還沒實現,不要急,慢慢來
{where:criteria,option:{page:[0,20]}},
function(data) {
if(data instanceof Array) {
scope.data = data; //把服務器返回的數據裝到Grid里面去
scope.grid.reload.apply(scope.grid); //關鍵點!dtGrid的代碼里是使用this來取數據集的,但是這里的this並不是scope.grid,apply一下
} else {
//todo toast //錯誤處理還沒有寫啦啦啦,慢慢來
alert(data);
}
}
);
});
}
});
}
}
});
02.后台"實現"
exports.findCollectionData = function(req,res){ EasyMongo.find("meta",{_id:req.params.id},function(err,docs){ if(err) res.send(mapping.errorCode.basicServerError); else { if(docs.length == 0) { res.send(mapping.errorCode.paramError); } else if(docs.length > 1){ res.send(mapping.errorCode.dirtyDataError); } else { //todo option req.query.option
EasyMongo.find(docs[0].collectionName,req.query.where || {},{},function(err,data){ if(err) res.send(mapping.errorCode.paramError); else res.send(data); }); } } }); };
嘿嘿,是不是很少。少的原因是大把大把的配置在元數據的邏輯還沒有實現。。
先讀取元數據配置,再查一把就OK,參數的生成方式在Angular指令中完成的,可以適應在MongoDB中。
這里的EasyMongo是筆者封裝的一個MongoDB增刪改查的接口,目前連接池好像有點爆炸,還在找原因。沒有用Mongoose的原因是Mongoose其實是把數據接口hardcode在了Schema里面,而筆者想達到的效果是數據接口甚至業務邏輯本身也在數據庫里面,對於不同的需求,只需增加一條BSON,找個寫前端的,就完成了。把后端抽象出來,對於普通的CMS系統和較低復雜度系統是完全可以實現的。
11.這種才寫幾天的項目就不叫開源了,傳送門->
https://git.oschina.net/code2life/SuperTurtle.git
筆者在某家公司實習,由於實習期快到並且不打算留下來,老大提了一個需求,基本是我自己想怎么實現怎么實現了。這個項目算是半公半私吧。
具體的代碼在這里了,項目剛開始。歡迎添磚加碼。

