同步笔记本

This commit is contained in:
life
2015-01-21 20:45:29 +08:00
parent 8a989b3726
commit 1674b9f91d
9 changed files with 326 additions and 85 deletions

View File

@@ -62,6 +62,8 @@ html, body {
<script src="public/js/jquery-1.9.0.min.js"></script>
<script src="public/js/bootstrap.js"></script>
<script src="public/js/app/service.js"></script>
<script src="public/js/common.js"></script>
<script>
$(function() {
@@ -96,31 +98,19 @@ $(function() {
return;
}
}
if(needCaptcha && !captcha) {
showMsg("请输入验证码", "captcha");
return;
}
$("#loginBtn").html("正在登录...").addClass("disabled");
$.post("/doLogin", {email: email, pwd: pwd, captcha: $("#captcha").val()}, function(e) {
$("#loginBtn").html("登录").removeClass("disabled");
if(e.Ok) {
$("#loginBtn").html("登录成功, 正在跳转...");
var from = $("#from").val() || "http:\/\/leanote.com\/note" || "/note";
location.href = from;
$("#loginBtn").html("loading...").addClass("disabled");
ApiService.auth(email, pwd, function(ret) {
$("#loginBtn").html("Sign in").removeClass("disabled");
if(ret.Ok) {
$("#loginBtn").html("Success...");
location.href = 'index.html';
} else {
if(e.Item && $.trim($("#captchaContainer").text()) == "") {
$("#captchaContainer").html($("#tCaptcha").html());
needCaptcha = true
showMsg(ret.Msg);
}
showMsg(e.Msg);
}
});
});
});
</script>
</body>

BIN
m/Traffic_lights_dark.psd Normal file

Binary file not shown.

BIN
m/Traffic_lights_light.psd Normal file

Binary file not shown.

61
node_modules/api.js generated vendored
View File

@@ -5,26 +5,51 @@ var Tags = db.tags;
var needle = require('needle');
var fs = require('fs');
var log = console.log;
function log(o) {
console.log(o);
}
// 远程数据服务
var Api = {
baseUrl: 'http://localhost:9000/api',
getUrl: function(url) {
return this.baseUrl + '/' + url;
getUrl: function(url, param) {
var url = this.baseUrl + '/' + url;
if(param) {
var paramStr = '';
for(var i in param) {
paramStr += i + '=' + param[i] + '&';
}
}
if(url.indexOf('?') >= 0) {
return url + '&' + paramStr;
}
return url + '?' + paramStr;
},
isOk: function(ret) {
return typeof ret == 'object' && ret.Ok;
// 数组
if(length in ret) {
return true;
}
if(ret == 'object') {
if(!ret.Ok) { // 指明了Ok
return false;
}
return true;
}
return false;
},
// 登录
auth: function(email, pwd, callback) {
var me = this;
needle.get(this.getUrl('auth/login'), {emai: email, pwd: pwd}, function(error, response) {
log({emai: email, pwd: pwd});
needle.get(this.getUrl('auth/login', {email: email, pwd: pwd}), function(error, response) {
// needle.get('http://localhost/phpinfo.php?email=xx', {emai: email, pwd: pwd}, function(error, response) {
var ret = response.body;
// 登录成功, 保存token
if(me.isOk(ret)) {
User.setCurUser(ret);
log(ret);
if(me.isOk(ret)) {
ret.Pwd = pwd;
User.setCurUser(ret);
callback && callback(ret);
} else {
log('log failed');
@@ -66,6 +91,28 @@ var Api = {
needle.post('http://localhost/phpinfo.php', data, { multipart: true }, function(err, resp, body) {
// needle will read the file and include it in the form-data as binary
});
},
getSyncNotebooks: function(afterUsn, maxEntry, callback) {
var me = this;
needle.get(this.getUrl('notebook/getSyncNotebooks', {afterUsn: afterUsn, maxEntry: maxEntry}), function(error, response) {
var ret = response.body;
if(me.isOk(ret)) {
callback && callback(ret);
} else {
callback && callback(false);
}
});
},
getSyncNotes: function(afterUsn, maxEntry, callback) {
var me = this;
needle.get(this.getUrl('note/getSyncNotes', {afterUsn: afterUsn, maxEntry: maxEntry}), function(error, response) {
var ret = response.body;
if(me.isOk(ret)) {
callback && callback(ret);
} else {
callback && callback(false);
}
});
}
};
module.exports = Api;

194
node_modules/sync.js generated vendored Normal file
View File

@@ -0,0 +1,194 @@
var db = require('db');
var Common = require('common');
var User = require('user');
var Tags = db.tags;
var needle = require('needle');
var fs = require('fs');
var Api = require('api');
var Notebook = require('notebook');
function log(o) {
console.log(o);
}
// 同步服务
var Sync = {
// 同步的信息, 返回给调用者
_syncInfo: {
notebook: {adds: [], deletes: [], updates: []},
note: {adds: [], deletes: [], updates: [], conflicts: []},
tag: {}
},
_syncNotebookIsLastChunk: false,
_totalSyncNotebookNum: 0, // 需要同步的数量
_tocalHasSyncNotebookNum: 0, // 已同步的数量
_notebookMaxEntry: 1000,
_initSyncInfo: function() {
var me = this;
me._syncNotebookIsLastChunk = false;
me._totalSyncNotebookNum = 0;
me._tocalHasSyncNotebookNum = 0;
me._lockNotebook = 1;
me._syncInfo = {
notebook: {adds: [], deletes: [], updates: []},
note: {adds: [], deletes: [], updates: [], conflicts: []},
tag: {}
};
},
// 增加, 有锁
_lockNotebook: 1,
_addSyncNotebookNum: function() {
if(me._lock) {
me._lockNotebook = 0;
me._tocalHasSyncNotebookNum++;
me._lockNotebook = 1;
} else {
me._addSyncNotebookNum();
}
},
// 同步笔记本
_syncNotebookToLocal: function(notebooks, callback) {
function canCall() {
// 是最后一块, 且
me._addSyncNotebookNum();
if(me._syncNotebookIsLastChunk && me._tocalHasSyncNotebookNum == me._tocalSyncNotebookNum) {
callback && callback(true);
}
}
if(!notebooks || notebooks.length == 0) {
return canCall();
}
for(var i in notebooks) {
var notebook = notebooks[i];
// 得到本地的, 与之对比
var usn = notebook.Usn;
var notebookId = notebook.NotebookId;
// 1) 服务器端删除了, 本地肯定删除
if(!notebook.CreatedTime) {
// TODO
Notebook.deleteNotebookForce(notebookId, function() {
// TODO 添加到信息
canCall();
});
return;
}
// 2) 查看本地的, 与本地合并
Notebook.GetNotebook(notebookId, function(notebookLocal) {
// 2.1 本地没有, 表示是新建
if(!notebookLocal) {
// TODO
Notebook.addNotebookForce(notebook, function() {
// TODO 添加到信息
canCall();
});
} else {
// 2.2 本地是否修改了, 需要合并, 使用服务端的数据
if(notebook.isDirty) {
// 2.3 服务器是最新的, 用服务器的
} else {
}
// 这里都是用服务器端的数据, 不处理冲突
notebook.UpdateNotebookForce(notebookId, notebook.Title, notebook.ParentNotebookId, function() {
// TODO 添加到信息
canCall();
})
}
});
callback && callback(true);
}
},
syncNotebook: function(afterUsn, callback) {
var me = this;
Api.getSyncNotebooks(afterUsn, me._notebookMaxEntry, function(notebooks) {
if(notebooks) {
me._tocalSyncNotebookNum += notebooks.length;
// 证明可能还有要同步的
if(notebooks.length == me._notebookMaxEntry) {
me._syncNotebookToLocal(notebooks);
var last = notebooks[notebooks.length-1];
me.syncNotebook(last.Usn, callback);
} else {
me._syncNotebookIsLastChunk = true;
me._syncNotebookToLocal(notebooks, callback);
}
} else {
// 同步失败
me._syncInfo.notebook.ok = false;
me._syncInfo.notebook.msg = "cann't get all chunks";
callback && callback(false);
}
});
},
// 同步笔记
syncNote: function(afterUsn, callback) {
callback && callback(true);
},
// 同步标签
syncTag: function(afterUsn, callback) {
callback && callback(true);
},
// 全量同步
fullSync: function(callback) {
var me = this;
me._initSyncInfo();
// 同步笔记本
me.syncNotebook(-1, function(ok) {
if(ok) {
// 同步笔记
me.syncNote(-1, function(ok) {
if(ok) {
// 同步标签
me.syncTag(-1, function() {
callback && callback(me._syncInfo);
});
} else {
callback && callback(me._syncInfo);
}
});
} else {
callback && callback(me._syncInfo);
}
});
},
// 增量同步
incrSync: function() {
var me = this;
me._initSyncInfo();
// 得到当前LastSyncUsn
User.getLastSyncInfo(function(lastSyncUsn, lastSyncTime) {
// 同步笔记本
me.syncNotebook(-1, function() {
// 同步笔记
me.syncNote(-1, function() {
// 同步标签
me.syncTag(-1, function() {
callback && callback(me._syncInfo);
});
});
});
});
},
// 发送改变
sendChanges: function() {
}
};
module.exports = Sync

8
node_modules/user.js generated vendored
View File

@@ -1,6 +1,10 @@
var Evt = require('evt');
var db = require('db');
function log(o) {
console.log(o);
}
/**
UserId (主键)
Email
@@ -18,12 +22,14 @@ var User = {
username: '',
// 登录后保存当前
setCurUser: function(user) {
if(user) {
this.token = user.Token;
this.userId = user.UserId;
this.email = user.Email;
this.username = user.Username;
// 保存到数据库中
this.saveCurUser(user);
}
},
saveCurUser: function(user, callback) {
// 当前用户是否在数据库中
@@ -55,7 +61,7 @@ var User = {
init: function(callback) {
var me = this;
db.users.findOne({IsActive: true}, function(err, doc) {
if(err) {
if(err || !doc) {
log('不存在');
callback && callback(false);
} else {

View File

@@ -1294,9 +1294,16 @@ LeaAce = {
}
};
// 全量同步
function fullSync() {
}
// note.html调用
// 实始化页面
// 判断是否登录
function initPage() {
function _init() {
$(function() {
// 获取笔记本
Service.notebookService.getNotebooks(function(notebooks) {
@@ -1327,4 +1334,15 @@ function initPage() {
// initSlimScroll();
LeaAce.handleEvent();
});
};
// 判断是否登录
UserService.init(function(userInfo) {
if(userInfo) {
UserInfo = userInfo;
_init();
} else {
location.href = 'login.html';
}
});
}

View File

@@ -6,10 +6,19 @@ var Service = {
noteService: require('note'),
tagService: require('tag'),
userService: require('user'),
tagService: require('tag')
tagService: require('tag'),
apiService: require('api'),
syncServie: require('sync');
};
// 全局变量
var ApiService = Service.apiService;
var UserService = Service.userService;
var SyncService = Service.syncService;
// 分发服务
// route = /note/notebook
// 过时
Service.dispatch = function(router, param, callback) {
var me = this;
router = $.trim(router);
@@ -27,28 +36,7 @@ Service.dispatch = function(router, param, callback) {
}
};
/*
var db = openDatabase('leanote', '1.0', 'my first database', 2 * 1024 * 1024);
db.transaction(function (tx) {
log(tx);
tx.executeSql('CREATE TABLE IF NOT EXISTS users (id unique, text)');
tx.executeSql('INSERT INTO users (id, text) VALUES (1, "synergies")');
tx.executeSql('INSERT INTO users (id, text) VALUES (2, "luyao")');
alert(30);
});
// Query out the data
db.transaction(function (tx) {
tx.executeSql('SELECT * FROM users', [], function (tx, results) {
var len = results.rows.length, i;
for (i = 0; i < len; i++) {
alert(results.rows.item(i).text);
}
});
});
*/
// clipbord
// 右键菜单
$(document).on('contextmenu', function (e) {
e.preventDefault();
var $target = $(e.target);
@@ -100,6 +88,4 @@ Menu.prototype.popup = function (x, y) {
this.menu.popup(x, y);
};
var menu = new Menu();
var FS = require('fs');

View File

@@ -14,4 +14,4 @@ Notebook.addNotebook("4", "life2", "1");
// Notebook.reCountNotebookNumberNotes('54bb2e89c596f2239a000000');
Api.uploadImage();
Api.auth('c@a.com', 'abc123');