增加一个备忘录工具

This commit is contained in:
luchenqun 2017-05-04 17:55:59 +08:00
parent 84d633ebe1
commit 3a9fa90bbb
11 changed files with 338 additions and 3 deletions

View File

@ -942,4 +942,33 @@ db.hotBookmarks = function(date) {
}); });
}; };
db.addNote = function(note) {
var sql = "INSERT INTO `notes` (`user_id`, `content`, `tag_id`) VALUES ('"+ note.user_id +"', "+ client.escape(note.content) +", '"+ note.tag_id +"')";
console.log(sql);
return new Promise(function(resolve, reject) {
client.query(sql, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result.insertId);
}
});
});
};
db.getNotes = function(params) {
var sql = "SELECT notes.id, notes.content, notes.tag_id, DATE_FORMAT(notes.created_at, '%Y-%m-%d %H:%i:%s') as created_at, tags.name FROM `notes` LEFT JOIN tags ON tags.id = notes.tag_id WHERE notes.user_id = '"+params.user_id+"' ORDER BY `created_at` DESC";
console.log(sql);
return new Promise(function(resolve, reject) {
client.query(sql, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
};
module.exports = db; module.exports = db;

View File

@ -69,6 +69,7 @@
<script src="/scripts/controllers/search-controller.js"></script> <script src="/scripts/controllers/search-controller.js"></script>
<script src="/scripts/controllers/hot-controller.js"></script> <script src="/scripts/controllers/hot-controller.js"></script>
<script src="/scripts/controllers/praise-controller.js"></script> <script src="/scripts/controllers/praise-controller.js"></script>
<script src="/scripts/controllers/note-controller.js"></script>
<script src="/scripts/externe/semantic.min.js"></script> <script src="/scripts/externe/semantic.min.js"></script>
<script src="/scripts/externe/calendar.min.js"></script> <script src="/scripts/externe/calendar.min.js"></script>
<script src="/scripts/externe/jquery.uploadfile.min.js"></script> <script src="/scripts/externe/jquery.uploadfile.min.js"></script>

View File

@ -24,6 +24,11 @@ app.config(function($stateProvider, $urlRouterProvider, $httpProvider) {
templateUrl: '/views/praise.html', templateUrl: '/views/praise.html',
controller: 'praiseCtr' controller: 'praiseCtr'
}) })
.state('note', {
url: '/note',
templateUrl: '/views/note.html',
controller: 'noteCtr'
})
.state('search', { .state('search', {
url: '/search', url: '/search',
templateUrl: '/views/search.html', templateUrl: '/views/search.html',

View File

@ -34,6 +34,9 @@ app.controller('menuCtr', ['$scope', '$stateParams', '$state', '$window', '$time
}, { }, {
uiSref: 'praise', uiSref: 'praise',
title: '赞赏' title: '赞赏'
}, {
uiSref: 'note',
title: '备忘录'
}]; }];
// 未登陆显示的菜单数据 // 未登陆显示的菜单数据

View File

@ -0,0 +1,127 @@
app.controller('noteCtr', ['$scope', '$state', '$stateParams', '$filter', '$window', '$timeout', 'ngDialog', 'bookmarkService', 'pubSubService', function($scope, $state, $stateParams, $filter, $window, $timeout, ngDialog, bookmarkService, pubSubService) {
console.log("Hello noteCtr...", $stateParams);
$scope.loadBusy = false;
$scope.edit = false;
$scope.content = '';
$scope.notes = [];
bookmarkService.autoLogin()
.then((data) => {
var login = data.logined;
var index = login ? 6 : 1;
pubSubService.publish('Common.menuActive', {
login: login,
index: index
});
getNotes();
})
.catch((err) => {
console.log('autoLogin err', err)
});
$scope.showAddNote = function(){
$scope.edit = (!$scope.edit);
updateEditPos();
}
$scope.addNote = function(close){
$scope.edit = close;
var note = {
tag_id: -1,
content: $scope.content,
}
bookmarkService.addNote(note)
.then((data) => {
console.log(JSON.stringify(data));
$scope.content = '';
getNotes();
})
.catch((err) => {
console.log('addNote err', err)
});
}
$scope.copy = function(id, content){
console.log("copy note.....");
var showContent = content.length >= 180 ? content.substr(0, 180)+'...' : content;
var clipboard = new Clipboard("#noteid"+id, {
text: function() {
return content;
}
});
clipboard.on('success', function(e) {
toastr.success(showContent + '<br/>已复制到您的剪切板', "提示");
clipboard.destroy();
});
clipboard.on('error', function(e) {
toastr.error(showContent + '<br/>复制失败', "提示");
clipboard.destroy();
});
}
$scope.delNote = function(id){
toastr.warning('暂未实现', "提示");
}
$scope.editNote = function(id){
toastr.warning('暂未实现', "提示");
}
$scope.detailNote = function(id){
toastr.warning('暂未实现', "提示");
}
// $('.js-segment-praise').transition('hide');
function getNotes(){
var params = {};
bookmarkService.getNotes(params)
.then((data) => {
$scope.notes = data;
})
.catch((err) => {
$scope.notes = [];
});
}
function animation() {
var data = ['scale', 'fade', 'fade up', 'fade down', 'fade left', 'fade right', 'horizontal flip',
'vertical flip', 'drop', 'fly left', 'fly right', 'fly up', 'fly down',
'browse', 'browse right', 'slide down', 'slide up', 'slide left', 'slide right'
];
var t = data[parseInt(Math.random() * 1000) % data.length];
return t;
}
function transition() {
var className = 'js-note-card';
$('.' + className).transition('hide');
$('.' + className).transition({
animation: animation(),
duration: 500,
});
}
// TODO: 我要将编辑按钮固定在容器的右上角
$(window).resize(updateEditPos);
updateEditPos();
function updateEditPos() {
for (var i = 1; i <= 100; i += 10) {
setTimeout(function() {
var offset = $('.js-note-card').offset();
if (offset) {
var t = offset.top;
var l = offset.left;
var w = $('.js-note-card').width();
$('.js-note-add').offset({
top: t + 10,
left: l + w - 10,
})
}
}, 100 * i)
}
}
}]);

View File

@ -480,7 +480,7 @@ app.controller('tagsCtr', ['$scope', '$filter', '$window', '$stateParams', '$tim
var t = offset.top; var t = offset.top;
var l = offset.left; var l = offset.left;
var w = $('.js-tags').width(); var w = $('.js-tags').width();
$('.js-edit').offset({ $('.js-note-add').offset({
top: t + 10, top: t + 10,
left: l + w - 10, left: l + w - 10,
}) })

View File

@ -230,3 +230,52 @@ app.filter('searchType', function() {
return types[type]; return types[type];
} }
}); });
app.filter('characters', function () {
return function (input, chars, breakOnWord) {
if (isNaN(chars)) return input;
if (chars <= 0) return '';
if (input && input.length > chars) {
input = input.substring(0, chars);
if (!breakOnWord) {
var lastspace = input.lastIndexOf(' ');
//get last space
if (lastspace !== -1) {
input = input.substr(0, lastspace);
}
}else{
while(input.charAt(input.length-1) === ' '){
input = input.substr(0, input.length -1);
}
}
return input + '…';
}
return input;
};
})
.filter('splitcharacters', function() {
return function (input, chars) {
if (isNaN(chars)) return input;
if (chars <= 0) return '';
if (input && input.length > chars) {
var prefix = input.substring(0, chars/2);
var postfix = input.substring(input.length-chars/2, input.length);
return prefix + '...' + postfix;
}
return input;
};
})
.filter('words', function () {
return function (input, words) {
if (isNaN(words)) return input;
if (words <= 0) return '';
if (input) {
var inputWords = input.split(/\s+/);
if (inputWords.length > words) {
input = inputWords.slice(0, words).join(' ') + '…';
}
}
return input;
};
});

View File

@ -326,7 +326,7 @@ app.factory('bookmarkService', ['$http', '$q', function($http, $q) {
}); });
return def.promise; return def.promise;
}, },
getAdvices: function getAdvices(params) { getAdvices: function(params) {
var def = $q.defer(); var def = $q.defer();
$http.get('/api/advices/', { $http.get('/api/advices/', {
params: params params: params
@ -366,6 +366,32 @@ app.factory('bookmarkService', ['$http', '$q', function($http, $q) {
}); });
return def.promise; return def.promise;
}, },
addNote: function(params) {
var def = $q.defer();
$http.post('/api/addNote/', {
params: params
})
.success(function(data) {
def.resolve(data);
})
.error(function(data, status) {
def.reject('addNote error');
});
return def.promise;
},
getNotes: function(params) {
var def = $q.defer();
$http.get('/api/notes/', {
params: params
})
.success(function(data) {
def.resolve(data);
})
.error(function(data) {
def.reject('getNotes error');
});
return def.promise;
},
}; };
return service; return service;

42
public/views/note.html Normal file
View File

@ -0,0 +1,42 @@
<div class="ui segment js-note-card">
<div class="ui form" ng-show="edit">
<div class="required field">
<label>内容</label>
<textarea rows="4" placeholder="" ng-model="content"></textarea>
</div>
<div class="field">
<div class="actions">
<div class="ui cancel button" ng-click="edit=false;">取消</div>
<div class="ui green button" ng-click="addNote(false)">提交关闭</div>
<div class="ui green button" ng-click="addNote(true)">提交继续</div>
</div>
</div>
</div>
<div class="ui divider" ng-show="edit"></div>
<div class="ui five stackable cards" infinite-scroll='loadCardData()' infinite-scroll-immediate-check="false">
<div class="card" ng-repeat="note in notes" id="{{note.id}}">
<div class="content" id="noteid{{note.id}}" ng-click="copy(note.id, note.content)" style="max-height:200px;margin-bottom:10px;">
<div class="description" style="word-break:break-all; word-wrap:break-word;">
<p>{{ note.content | characters:200:false }}</p>
</div>
</div>
<div class="extra content" ng-show="!note.edit" style="height:50px;padding-right:2px;padding-left:8px;">
<span class="left floated like" style="margin-top:6px;">
<i class="add to calendar icon"></i>{{ note.created_at }}
</span>
<i class="ellipsis horizontal icon right floated" style="margin-top:8px;" ng-mouseover="note.edit=true;"></i>
</div>
<div class="extra content" ng-show="note.edit" ng-mouseleave="note.edit=false;" style="height:50px;">
<img class="ui mini spaced image" style="width:16px;height:16px;margin:0 8px;margin-top:8px;" ng-src="./images/delete.png" ng-click="delNote(note.id)" title="删除备忘">
<img class="ui mini spaced image" style="width:16px;height:16px;margin:0 8px;margin-top:8px;" ng-src="./images/edit-bookmark.png" ng-click="editNote(note.id)" title="编辑备忘">
<!-- <img class="ui mini spaced image" style="width:16px;height:16px;margin:0 8px;margin-top:8px;" ng-src="./images/copy.png" id="url{{bookmark.id}}" ng-click="copy(note.id, note.content)" title="复制备忘"> -->
<img class="ui mini spaced image" style="width:16px;height:16px;margin:0 8px;margin-top:8px;" ng-src="./images/detail.png" ng-click="detailNote(note)" title="备忘详情">
</div>
</div>
</div>
<div style="width:22px;height:22px;" class="js-note-add" ng-click="showAddNote()" data-tooltip="添加备忘" ng-show="!edit">
<img class="ui ui middle aligned tiny image" src="./images/edit.png" ng-show="!loadBusy">
</div>
</div>
<div class="ui massive text centered inline loader js-hot-loader" ng-class="{active:loadBusy, disabled:!loadBusy}">
正在加载中...</div>

View File

@ -1263,6 +1263,48 @@ api.getHotBookmarksByTimer = function() {
}, timeout); }, timeout);
} }
api.post('/addNote', function(req, res) {
console.log("addNote username = ", req.session.username);
if (!req.session.user) {
res.send(401);
return;
}
var params = req.body.params;
params.user_id = req.session.user.id;
db.addNote(params)
.then((affectedRows) => {
res.json({
retCode: 0,
msg: "添加备忘成功 ",
})
console.log('addNote affectedRows ', affectedRows)
})
.catch((err) => {
console.log('addNote error', err);
res.json({
retCode: 1,
msg: "添加备忘失败: " + JSON.stringify(err),
})
});
});
api.get('/notes', function(req, res) {
console.log("getNotes username = ", req.session.username);
if (!req.session.user) {
res.send(401);
return;
}
var params = req.query;
params.user_id = req.session.user.id;
db.getNotes(params)
.then((notes) => res.json(notes))
.catch((err) => console.log('notes', err));
});
function md5(str) { function md5(str) {
return crypto.createHash('md5').update(str).digest('hex'); return crypto.createHash('md5').update(str).digest('hex');
}; };

View File

@ -82,3 +82,14 @@ CREATE TABLE `hot_bookmarks` (
`status` tinyint(4) DEFAULT '0', -- 状态 `status` tinyint(4) DEFAULT '0', -- 状态
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
); );
-- 备忘录
drop table if exists notes;
CREATE TABLE `notes` (
`id` int(11) NOT NULL AUTO_INCREMENT, -- id
`user_id` int(11) NOT NULL, -- 用户id
`content` varchar(4096) DEFAULT NULL, -- 备忘内容
`tag_id` int(11) DEFAULT NULL, -- 分类id
`created_at` datetime DEFAULT now(), -- 创建时间
PRIMARY KEY (`id`)
);