diff --git a/node_modules/db.js b/node_modules/db.js index 5cad0e6d..3625c64f 100644 --- a/node_modules/db.js +++ b/node_modules/db.js @@ -20,30 +20,36 @@ var db = { // 为全部用户共有的表初始化 initGlobal: function () { + var me = this; var dbNames = ['users', 'g']; - this._init(dbNames); + this.initIt(me, dbNames); }, // 为特定用户初始化自己的表 initDBForUser: function (userId) { + var me = this; var dbNames = ['notebooks', 'notes', 'tags', 'images', 'attachs', 'noteHistories']; - this._init(dbNames, userId); + this.initIt(me, dbNames, userId); }, // 过时 init: function () { + var me = this; var dbNames = ['users', 'notebooks', 'notes', 'tags', 'images', 'attachs', 'noteHistories', 'g']; - this._init(dbNames); + this.initIt(me, dbNames); }, // 过时 initForLogin: function () { + var me = this; // var dbNames = ['users']; var dbNames = ['users', 'notebooks', 'notes', 'tags', 'noteHistories']; - this._init(dbNames); + this.initIt(me, dbNames); }, - _init: function (dbNames, userId) { + // map, 最后的db设到map里 + // forceAutoload 是否强制加载 + initIt: function (map, dbNames, userId, forceAutoload) { var me = this; for(var i in dbNames) { var name = dbNames[i]; @@ -60,7 +66,8 @@ var db = { // console.log(dbFilepath); (function (name) { // 这部分非常慢!, 会卡界面 - me[name] = new Datastore({ filename: dbFilepath, autoload: name != 'noteHistories' , onload: function () { + var autoload = forceAutoload || name != 'noteHistories'; + map[name] = new Datastore({ filename: dbFilepath, autoload: autoload, onload: function () { console.log(userId + '/' + name + ' is loaded'); }}); })(name); @@ -73,11 +80,13 @@ var db = { Datastore.prototype.loadDB = function(callback) { var me = this; if (this.__loaded) { - callback(); + callback(me.__loadedSuccess); } else { this.loadDatabase(function (err) { me.__loaded = true; - callback(err); + console.log(err); + me.__loadedSuccess = !err; + callback(me.__loadedSuccess); }); } }; diff --git a/node_modules/note.js b/node_modules/note.js index cc354b67..4a884f35 100644 --- a/node_modules/note.js +++ b/node_modules/note.js @@ -206,7 +206,7 @@ var Note = { */ addNoteHistory: function(noteId, content) { var me = this; - db.noteHistories.loadDB(function () { + db.noteHistories.loadDB(function (ok) { // 先判断是否存在, 不存在则新建之 db.noteHistories.findOne({_id: noteId}, function(err, history) { // 新建之 @@ -217,6 +217,9 @@ var Note = { else { var histories = history.Histories; histories.push({Content: content, UpdatedTime: new Date()}); + + // 不能多了, 多了有麻烦 + db.noteHistories.update({_id: noteId}, {$set: {Histories: histories}}); } }); @@ -231,7 +234,11 @@ var Note = { // 获取笔记历史记录 getNoteHistories: function(noteId, callback) { var me = this; - db.noteHistories.loadDB(function () { + db.noteHistories.loadDB(function (ok) { + if (!ok) { + callback(false); + return; + } db.noteHistories.findOne({_id: noteId}, function(err, doc) { if(err || !doc) { callback(false); diff --git a/node_modules/user.js b/node_modules/user.js index 225e751d..fa9dc13a 100644 --- a/node_modules/user.js +++ b/node_modules/user.js @@ -383,7 +383,23 @@ User = { } return callback && callback(users); }); - } + }, + + // 通过id得到用户 + getUser: function (userId, callback) { + db.users.findOne({_id: userId}, function(err, user) { + if(err) { + return callback && callback(false); + } + return callback && callback(user); + }); + }, + + setUserHasDB: function (userId, callback) { + db.users.update({_id: userId}, {$set: {HasDB: true}}, function(err, cnt) { + callback(); + }); + }, }; module.exports = User; diff --git a/public/config.js b/public/config.js index 8003bf53..44571e1d 100644 --- a/public/config.js +++ b/public/config.js @@ -7,7 +7,8 @@ var Config = { "export_html", "export_leanote", "export_evernote", - "langs" + "langs", + "accounts" ], "langs": [ { @@ -23,6 +24,6 @@ var Config = { "name": "繁体中文" } ], - "lang": "en-us", + "lang": "zh-cn", "theme": "" }; \ No newline at end of file diff --git a/public/js/app/api.js b/public/js/app/api.js index 7d69be39..ca46b042 100644 --- a/public/js/app/api.js +++ b/public/js/app/api.js @@ -14,6 +14,7 @@ var Api = { fileService: FileService, noteService: NoteService, userService: UserService, + dbService: db, // 得到当前版本 getCurVersion: function (callback) { diff --git a/public/js/common.js b/public/js/common.js index 415c2bd0..7996c55c 100644 --- a/public/js/common.js +++ b/public/js/common.js @@ -1641,8 +1641,10 @@ var Loading = { setProgress: function (rate) { this.$progressBar.width(rate + '%'); }, - hide: function() { - $('#loadingDialog').modal('hide'); + hide: function(timeout) { + setTimeout(function () { + $('#loadingDialog').modal('hide'); + }, timeout ? timeout : 0); } }; diff --git a/public/plugins/accounts/plugin.js b/public/plugins/accounts/plugin.js new file mode 100644 index 00000000..e2163575 --- /dev/null +++ b/public/plugins/accounts/plugin.js @@ -0,0 +1,338 @@ +/** + * + * 帐户管理 + * + */ +var async; + +define(function() { + var setLang = { + langs: { + 'en-us': { + 'Accounts': 'Accounts', + }, + 'zh-cn': { + 'Accounts': '帐户管理', + "Username": "用户名", + "Is Local": "本地帐户", + "Yes": "是", + "No": "否", + "DB Optimization": "数据库优化", + "Open DB Dir": "打开数据库目录", + "Open Images/Attachs Dir": "打开图片附件目录", + "Delete": "删除", + "Options": "操作", + "Current": "当前" + }, + 'zh-hk': { + 'Accounts': '帐户管理', + } + }, + + _tpl: ` + + + `, + + getMsg: function(txt, data) { + return Api.getMsg(txt, 'plugin.accounts', data) + }, + + // 初始化dialog + _inited: false, + init: function () { + var me = this; + if (me._inited) { + return; + } + me._inited = true; + $('body').append(me._tpl); + me.dialog = $("#accountsDialog"); + + me.dialog.find('.lang').each(function() { + var txt = $.trim($(this).text()); + $(this).text(me.getMsg(txt)); + }); + + me.tbody = me.dialog.find('tbody'); + + var op2Func = { + db: function (userId) { + me.dbOptimization(userId); + }, + 'open-db-dir': '', + 'open-files-dir': '', + 'delete': '' + }; + + // 事件 + me.tbody.on('click', 'button', function () { + var $this = $(this); + var userId = $this.closest('tr').data('id'); + var option = $this.data('op'); + + var func = op2Func[option]; + if (func) { + func(userId); + } + }); + }, + + renderUser: function(user) { + var me = this; + var username = user.Username; + if (user.IsActive) { + username += ' ' + me.getMsg('Current') + ''; + } + if (user.Email) { + username += '
' + user.Email + ''; + } + var tr = '' + username + ''; + tr += '' + (user.IsLocal ? me.getMsg('Yes') : me.getMsg('No')) + ''; + + var disabled = user.IsActive ? 'disabled="disabled"' : ''; + + var options = '
' + + '' + + '' + + '' + + '' + + '
'; + tr += '' + options + ''; + return tr; + }, + + renderUsers: function (users) { + var me = this; + var tbody = ''; + for (var i = 0; i < users.length; ++i) { + var user = users[i]; + tbody += me.renderUser(user); + } + me.tbody.html(tbody); + }, + + openModal: function () { + var me = this; + me.dialog.modal('show'); + + Api.userService.getAllUsers(function (users) { + me.renderUsers(users); + }); + }, + + // 打开前要执行的 + onOpen: function() { + var me = this; + var gui = Api.gui; + + var menu = new gui.MenuItem({ + label: me.getMsg('Accounts'), + click: function () { + me.init(); + me.openModal(); + } + }); + + // 设置 + Api.addMoreMenu(menu); + }, + // 打开后 + onOpenAfter: function() { + var me = this; + }, + // 关闭时需要运行的 + onClose: function() { + }, + + // 数据库优化 + // 1. 将数据库迁移到独立的目录 + // 2. 将数据库读写合并 + dbOptimization: function (userId) { + var me = this; + Api.loading.show(); + Api.userService.getUser(userId, function (user) { + if (!user) { + alert('Error'); + Api.loading.hide(); + return; + } + + // 已经存在 + if (user.HasDB) { + Api.loading.hide(3000); + Api.loading.setMsg('优化完成'); + return; + } + + if (!async) { + async = require('async'); + } + + me.migrateAllDBs(userId, function (ok) { + // 迁移成功后, 更新HasDB + Api.userService.setUserHasDB(userId, function () { + Api.loading.setMsg('优化完成'); + Api.loading.hide(2000); + }); + }, function (msg) { + Api.loading.setMsg(msg); + }); + + }); + }, + + // 迁移历史记录 + migrateNoteHistories: function (noteId, sDB, dDB, callback) { + var me = this; + // 加载DB, 如果成功 + sDB.loadDB(function (ok) { + if (ok) { + sDB.findOne({_id: noteId}, function (err, doc) { + dDB.insert(doc, function(err, retDoc) { + callback(); + }); + }); + } + else { + callback(); + } + }); + }, + + migrateEach: function (userId, sourceDb, distDb, name, callback) { + var me = this; + + var sDB = sourceDb[name]; + var dDB = distDb[name]; + + var query = {UserId: userId}; + sDB.find(query, function(err, docs) { + if(err) { + return callback && callback(false); + } + + if (name === 'notes') { + me._notes = docs; + } + + async.eachSeries(docs, function(doc, cb) { + dDB.insert(doc, function(err, retDoc) { + if (retDoc) { + console.log(name + ' ok ' + retDoc._id); + + // 如果是笔记, 则迁移它的笔记历史记录 + if (name === 'notes') { + me.migrateNoteHistories( + doc.NoteId, + sourceDb['noteHistories'], + distDb['noteHistories'], + function () { + cb(); + }); + } + else { + cb(); + } + } + else { + console.log(name + ' NO '); + cb(); + } + }); + }, function () { + callback(true); + }); + }); + + }, + // 迁移到独立目录 + migrateAllDBs: function (userId, callback, msgCallbac) { + var me = this; + var names = ['notebooks', 'notes', 'tags', 'images', 'attachs', 'noteHistories']; + // notes, notebooks, tags, attachs, images, noteHistories + // 判断当前db是否是全局的, 如果不是, 则初始化全局的 + var sourceDb = {}; + if (Api.userService.hasDB) { + Api.dbService.initIt(sourceDb, names, '', false); + } + else { + sourceDb = Api.dbService; + } + + // 如果dist数据存在, 则删除之, 不用删除, 大不了插入失败 + + // 初始化dist + var distDb = {}; + Api.dbService.initIt(distDb, names, userId, true); + + // OK, 为每个表进行迁移 + async.eachSeries(names, function(name, cb) { + msgCallbac('正在优化 ' + name); + console.log('正在优化 ' + name); + + if (name === 'noteHistories') { + cb(); + return; + } + + me.migrateEach(userId, sourceDb, distDb, name, function(ok) { + if (ok) { + console.log(name + ' Over'); + msgCallbac(name + ' 优化完成'); + } + else { + console.log(name + ' 迁移失败'); + } + cb(); + }); + }, function () { + callback(); + }); + } + }; + + return setLang; + +}); diff --git a/public/plugins/accounts/plugin.json b/public/plugins/accounts/plugin.json new file mode 100644 index 00000000..79cc45b5 --- /dev/null +++ b/public/plugins/accounts/plugin.json @@ -0,0 +1,16 @@ +{ + "name": "langs", + "author": "life", + "authorUrl": "http://life.leanote.com", + "desc": "语言", + "langs": { + "en-us": { + "pluginName": "Langs", + "pluginDesc": "" + }, + "zh-cn": { + "pluginName": "设置语言", + "pluginDesc": "" + } + } +} \ No newline at end of file diff --git a/public/themes/default.css b/public/themes/default.css index 2f6b5188..f709961c 100644 --- a/public/themes/default.css +++ b/public/themes/default.css @@ -2764,6 +2764,9 @@ background-position:-1px -670px border-top: 1px dashed #eee; padding: 5px 0; } +#loadingDialog { + z-index: 999999; +} #loading { display: inline-block; width: 20px; diff --git a/public/themes/default.less b/public/themes/default.less index 3c691cb9..2bd2faea 100644 --- a/public/themes/default.less +++ b/public/themes/default.less @@ -758,6 +758,9 @@ background-position:-1px -670px } } +#loadingDialog { + z-index: 999999; +} #loading { display: inline-block; width: 20px;