teamsalt任務(wù)管理系統(tǒng)
teamsalt
什么是teamsalt?
teamsalt是一個在線的團隊寫作任務(wù)管理系統(tǒng)。
teamsalt是team+salt(鹽),寓意就是作為鹽一樣,成為團隊中不可缺少的系統(tǒng)。
系統(tǒng)設(shè)計參考了teambition、tower、worktile、fengcheco等。
長什么樣呢?
http://teamsalt.duapp.com/
user: admin
password: 1
搭建在bae上面,使用bae2.0,可能訪問不太穩(wěn)定,打算遷移到其他平臺上面。
技術(shù)選型
后臺
jfinal 基本可以負擔(dān)后臺
前臺
部署打包
grunt 使用grunt完成壓縮、合并等。
數(shù)據(jù)庫
mysql
后臺開發(fā)說明
后臺使用jfinal進行開發(fā),具體開發(fā),請查看jfinal開發(fā)手冊,30分鐘就可以閱讀完了。
目錄結(jié)構(gòu)
. ├── com │ └── teamsalt │ ├── common │ │ ├── Message.java // 請求返回 json 對象封裝類 │ │ ├── TeamsaltConfig.java // jfinal 配置 │ │ └── TeamsaltConstants.java // 常量類 │ ├── controller │ │ ├── CommentController.java // 評論 controller │ │ ├── IndexController.java // 首頁 controller │ │ ├── InviteController.java // 邀請用戶 controller │ │ ├── ProjectController.java // 項目 controller │ │ ├── TaskController.java // 任務(wù) controller │ │ ├── TasklistController.java // 任務(wù)列表 controller │ │ └── UserController.java // 用戶 controller │ ├── filter │ │ ├── MainFilter.java // 使用Filter過濾main.html頁面,解決jfinal無法過濾靜態(tài)html的問題 │ │ └── xss // XSS 過濾攔截 │ │ ├── CrossScriptingFilter.java │ │ ├── HTMLFilter.java │ │ └── RequestWrapper.java │ ├── interceptor │ │ ├── CheckLoginInterceptor.java // 當(dāng)訪問/login頁面的時候,判斷是否已經(jīng)登錄,已經(jīng)登錄,則跳轉(zhuǎn)到/home │ │ └── GlobalLoginInterceptor.java // 全局用戶登錄攔截器 │ ├── kit // 常用的一些工具類 │ │ ├── ConfigKit.java │ │ ├── ContextKit.java │ │ ├── CookieKit.java │ │ ├── DateKit.java │ │ ├── HtmlTagKit.java │ │ ├── PwdKit.java │ │ └── UuidKit.java │ └── model // model 層的各種對象 │ ├── Comment.java │ ├── Invite.java │ ├── InviteUser.java │ ├── Project.java │ ├── ProjectTasklist.java │ ├── ProjectUser.java │ ├── Task.java │ ├── Tasklist.java │ ├── TasklistTask.java │ └── User.java ├── log4j.properties // log4j 配置 └── S.java // 采用 jetty 的啟動類
代碼開發(fā)比較簡單,具體查看jfinal手冊就能進行代碼開發(fā)了。
前臺開發(fā)說明
前臺采用單頁面應(yīng)用程序(SPA)的開發(fā)方式,完全可以和后臺分離出來,部署在不同的服務(wù)器上面,而且可以將前臺用 phonegap 之類的工具,打包成android、ios、winPhone等的應(yīng)用,起初也就是這么設(shè)計的。
js 文件的代碼路徑是在teamsalt/WebContent/js中,具體說明如下。
js 目錄結(jié)構(gòu)
. ├── app // 這個是壓縮代碼后產(chǎn)生的文件地方 │ ├── common │ ├── model │ ├── object │ ├── router │ ├── ui-component │ ├── view │ └── widget ├── dist // 這個是壓縮時候的臨時文件 │ ├── common │ ├── model │ ├── object │ ├── router │ ├── ui-component │ ├── view │ └── widget ├── gallery // 這個是需要的插件包 │ ├── backbone │ ├── bootbox │ ├── bootstrap │ ├── contextmenu │ ├── datepicker │ ├── dropdownx │ ├── notify │ ├── perfect-scrollbar │ ├── popbox │ ├── select │ ├── tags │ ├── template │ ├── underscore │ └── xdate ├── jquery // jquery │ └── jquery ├── node_modules // 使用 grunt 需要的插件,已經(jīng)提供 │ ├── grunt │ ├── grunt-cmd-concat │ ├── grunt-cmd-transport │ ├── grunt-contrib-clean │ └── grunt-contrib-uglify ├── seajs // seajs │ ├── 1.3.1 │ ├── plugin-log │ ├── seajs │ └── seajs-text └── src // 這個是程序的源代碼了 ├── common // 公共工具 ├── model // model 層 ├── object // 自定義的一個 map 對象 ├── router // 路由器 ├── ui-component // 自定義的 ui 組件 ├── view // view 層 └── widget // 自定義的 widget 組件
js 開發(fā)
采用 seajs 和 backbone 進行代碼架構(gòu),同后臺同樣的 mvc 模式開發(fā)。
model 層
user.js
define(function(require, exports, module) {
var $ = require('jquery');
var _ = require('underscore');
var Backbone = require('backbone');
var User = Backbone.Model.extend({
getUser : function(params, success) {
var url = '/user/profile/';
var self = this;
Util.query.g(url, '', function(result) {
success(result.other, params);
});
},
getUsersByProjectIdAndTaskId : function(params, success, error) {
this.fetch({
url : '/data/' + Util.curProjectId + '-users.json',
success : function(model, response, options) {
success(response);
},
error : function(XMLHttpRequest, textStatus, errorThrown) {
error(arguments);
}
});
},
getUsersByProject : function(params, success, error) {
var url = '/user/getProjectUsers';
Util.query.g(url, params, function(result) {
success(result.other);
});
},
// 得到所有用戶
getAllUser : function(params, success) {
var url = '/user/getAllUser';
Util.query.g(url, '', function(result) {
success(result.other);
});
}
});
module.exports = User;
})
control 層
雖然叫做 view 但是在架構(gòu)上面,擔(dān)任的是 contro 層的功能。
layout.js
/**
* @author zhaopeng
* @datetime 2013-08-27
* @description 程序任務(wù)主界面入口
*/
define(function(require, exports, module){
var $ = require('jquery');
var _ = require('underscore');
var Backbone = require('backbone');
var Bootstrap = require('bootstrap');
// 布局模板
var layoutHtml = require('./tpl/layout.html');
// 模板
var ProjectBar = require('./header/projectBar');// header左側(cè)項目切換bar
var UserinfoBar = require('./header/userinfoBar');// header右側(cè)用戶信息bar
var SidebarTasklist = require('./sidebar/sidebar-tasklist');// 左側(cè)側(cè)邊欄
var SidebarUser = require('./sidebar/sidebar-user');// 左側(cè)側(cè)邊欄
var ListPanel = require('./container/listPanel');// container左側(cè)列表
var DetailPanel = require('./container/detailPanel');// container右側(cè)詳情
var CommonView = require('./commonView');// 公共組件VIEW
//模型
var Comment = require('../model/comment');
var Project = require('../model/project');
var Task = require('../model/task');
var Tasklist = require('../model/tasklist');
var User = require('../model/user');
var Laoyout = Backbone.View.extend({
el: 'body',
events:{
'updateCommon #sidebar':'updateCommon',
'updateCommon #list-panel':'updateCommon',
'updateCommon #detail-panel':'updateCommon',
'deleteTask #detail-panel':'deleteTask',
'updateTask #detail-panel':'updateTask'
},
initialize: function() {
this.$el.html(Util.tpl.t(layoutHtml,{})).hide().show('1000');
// 初始化模型,全部記載到map中
this.comment = new Comment();
this.project = new Project();
this.task = new Task();
this.tasklist = new Tasklist();
this.user = new User();
Util.Models.put('comment',this.comment);
Util.Models.put('project',this.project);
Util.Models.put('task',this.task);
Util.Models.put('tasklist',this.tasklist);
Util.Models.put('user',this.user);
// 初始化布局界面
this.projectBar = new ProjectBar();
this.userinfoBar = new UserinfoBar();
this.sidebarTasklist = new SidebarTasklist();
this.sidebarUser = new SidebarUser();
this.listPanel = new ListPanel();
this.detailPanel = new DetailPanel();
Util.Views.put('projectBar',this.projectBar);
Util.Views.put('userinfoBar',this.userinfoBar);
Util.Views.put('sidebarTasklist',this.sidebarTasklist);
Util.Views.put('sidebarUser',this.sidebarUser);
Util.Views.put('listPanel',this.listPanel);
Util.Views.put('detailPanel',this.detailPanel);
},
updateCommon:function(e){
CommonView.init();
},
//刪除任務(wù)后,同步刪除列表中的數(shù)據(jù)
deleteTask:function(e,result){
this.listPanel.deleteTask(result.uuid);
},
//更新任務(wù)后,同步更新列表中的數(shù)據(jù)
updateTask:function(e,result){
this.listPanel.updateTask(result);
}
});
module.exports = Laoyout;
})
view 層
使用 artTemplate 模板引擎,模板文件都存放在對應(yīng)的tpl文件夾下。
layout.html
<nav id="header" class="navbar navbar-default navbar-inverse navbar-static-top navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse navbar-ex1-collapse"> <ul id="project-bar" class="nav navbar-nav"> </ul> <a class="navbar-brand" href="#" style="margin-left: 40%;">teamsalt</a> <ul id="userinfo-bar" class="nav navbar-nav navbar-right"> </ul> </div><!-- /.navbar-collapse --> </nav> <aside id="sidebar"> <section id="sidebar-tasklist" class="sidebar-menu"> </section> <section id="sidebar-user" class="sidebar-menu"> </section> </aside> <div id="container" > <div id="list-panel" class="bor-r"> </div> <div id="detail-panel"> </div> </div> <div class="notifications top-right"></div>
使用 grunt 打包文件項目
1. 安裝nodejs
根據(jù)系統(tǒng)到 http://nodejs.org/ 下載安裝對應(yīng)的 nodejs。我用的是 linux 編譯后的版本,在.bashrc將 nodejs 添加到環(huán)境變量就好了。 如果是 windows 直接安裝就可以了。
2. 安裝grunt命令行工具grunt-cli
使用-g全局安裝,這樣可以在任何一個目錄里使用了。命令:npm install -g grunt-cli
需要注意的是在 linux 或 mac 下有時會報沒有權(quán)限的錯誤,這時須在前面加一個sudo
3. 安裝grunt
代碼中已經(jīng)包含了 grunt 需要的插件,所有只需要安裝 grunt 就可以了。
進入目錄,使用命令:npm install grunt --save-dev
至此,安裝完畢。
4. 打包 js 文件
在 Gruntfile.js 中提供了一下幾個命令。
grunt build-t // 執(zhí)行 transport grunt build-c // 執(zhí)行 concat grunt build-u // 執(zhí)行 uglify grunt build-min // 執(zhí)行壓縮 grunt build-all // 執(zhí)行以上所有命令 grunt // 執(zhí)行 clean, 刪除 app 和 dist 目錄
壓縮提醒
壓縮合并后的代碼是放在teamsalt/WebContent/js/app/,如果部署只需要將app.js上傳到服務(wù)器就可以了。
-
在本地如何切換開發(fā)環(huán)境何生產(chǎn)環(huán)境的js代碼。
// For development if (location.href.indexOf("?pro") > 0) { seajs.use("app/app"); } // For production else { seajs.use("src/app"); }
未來計劃
對目前此系統(tǒng)暫停開發(fā),全心專注進行第二個版本的開發(fā),第二個版本具有更好的架構(gòu)設(shè)計,更輕快的開發(fā)速度,更多的功能特性。在基本版本完成之后,同樣也會選擇開源的方式進行發(fā)布。
