From 845fc737981e091991c619a4f79140a580d1bc37 Mon Sep 17 00:00:00 2001
From: luchenqun
Date: Sun, 25 Jun 2017 15:24:23 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=B9=A6=E7=AD=BE=E7=9A=84?=
=?UTF-8?q?=E5=AF=BC=E5=87=BA=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 9 ++-
database/db.js | 34 ++++++---
package.json | 1 +
public/index.html | 2 +-
.../controllers/settings-controller.js | 11 ++-
public/views/home.html | 6 +-
public/views/settings.html | 9 ++-
routes/api.js | 73 ++++++++++++++++---
8 files changed, 108 insertions(+), 37 deletions(-)
diff --git a/README.md b/README.md
index 26611ed..86f0e5d 100644
--- a/README.md
+++ b/README.md
@@ -27,11 +27,11 @@
- [x] 可以导入Chrome的书签导出文件,暂时做在设置里面。
- [x] 书签可以作为公有或者私有,公有可供所有人搜索。
- [x] 可以将搜索到其他用户的书签转存为自己的书签。
-- [ ] 可以将书签导出来,然后导入到浏览器。
+- [x] 可以将书签导出来,然后导入到浏览器。
- [x] 在热门标签里面,有在网上找的热门书签。可以转存收藏到自己书签里面,快捷键R随机查看热门书签。
- [x] 新增备忘录功能,有时候随手要做点纪录,就方便了。任意界面按快捷键A增加备忘录。双击备忘录可查看详情!
- [x] 在设置的全局链接,可设置快捷键,用来在任何页面,快速打开设置的链接。
-- [ ] 适配手机平板。
+- [ ] 适配手机平板(无限搁置)。
4 主要用到的模块说明
------------------
@@ -142,18 +142,19 @@ my-bookmark/
```
"body-parser": bodyParser用于解析客户端请求的body中的内容,内部使用JSON编码处理
"connect-mongo": 用于将session存入MongoDB
-"cheerio": 用于后端的jQuery
+"cheerio": 用于后端的jQuery,解析从浏览器导出来上传到服务器的书签html文件
"cookie-parser": 处理每一个请求的cookie
"crypto": 加密模块,主要用来加密用户的密码
"debug": 这个好像没用到,看名字好像调试的。
"download": 主要用来下载书签的favicon文件
"express": Web 应用程序框架
"express-session": session模块
-"jsdom": 用来解析从浏览器导出来上传到服务器的书签html文件
+"js-beautify": 用来格式化导出的书签的html文件
"morgan": 一个Node.js关于http请求的日志中间件
"multer": 文件上传模块
"mysql": sql数据库操作模块
"node-readability": 获取网页title(添加书签用到)跟内容(书签详情用到)模块。
+"path": 路径处理模块。
"request": http请求模块。主要用来获取热门书签数据。
"supervisor": 文件改变监视文件,开发使用。
"webshot": 网页截图模块。
diff --git a/database/db.js b/database/db.js
index 77844f2..0d6c92b 100644
--- a/database/db.js
+++ b/database/db.js
@@ -546,13 +546,13 @@ db.getBookmarksNavigate = function(tags) {
// var sql = "SELECT t.id as tag_id, t.name as tag_name, b.* FROM `tags` as t LEFT OUTER JOIN tags_bookmarks as tb ON t.id = tb.tag_id LEFT OUTER JOIN bookmarks as b ON tb.bookmark_id = b.id WHERE t.user_id='" + user_id + "' ORDER BY t.id ASC, b.click_count DESC";
var sql = "";
tags.forEach((tag, index) => {
- var t = 't' + tag.id;
- if (index >= 1) {
- sql += " UNION "
- }
- sql += "(SELECT * FROM ((SELECT t.id AS tag_id, t.`name` as tag_name, t.sort, b.* FROM `tags` as t, `bookmarks`as b, `tags_bookmarks` as tb WHERE t.id = tb.tag_id AND b.id = tb.bookmark_id AND t.id = " + tag.id + " ORDER BY b.click_count DESC LIMIT 0, 16) UNION (SELECT t.id AS tag_id, t.`name` as tag_name, t.sort, b.* FROM `tags` as t, `bookmarks`as b, `tags_bookmarks` as tb WHERE t.id = tb.tag_id AND b.id = tb.bookmark_id AND t.id = " + tag.id + " ORDER BY b.created_at DESC LIMIT 0, 16)) as " + t + " ORDER BY " + t + ".click_count DESC, " + t + ".created_at DESC)";
- })
- // console.log('getBookmarksNavigate ', sql);
+ var t = 't' + tag.id;
+ if (index >= 1) {
+ sql += " UNION "
+ }
+ sql += "(SELECT * FROM ((SELECT t.id AS tag_id, t.`name` as tag_name, t.sort, b.* FROM `tags` as t, `bookmarks`as b, `tags_bookmarks` as tb WHERE t.id = tb.tag_id AND b.id = tb.bookmark_id AND t.id = " + tag.id + " ORDER BY b.click_count DESC LIMIT 0, 16) UNION (SELECT t.id AS tag_id, t.`name` as tag_name, t.sort, b.* FROM `tags` as t, `bookmarks`as b, `tags_bookmarks` as tb WHERE t.id = tb.tag_id AND b.id = tb.bookmark_id AND t.id = " + tag.id + " ORDER BY b.created_at DESC LIMIT 0, 16)) as " + t + " ORDER BY " + t + ".click_count DESC, " + t + ".created_at DESC)";
+ })
+ // console.log('getBookmarksNavigate ', sql);
return new Promise(function(resolve, reject) {
client.query(sql, (err, result) => {
@@ -568,9 +568,9 @@ db.getBookmarksNavigate = function(tags) {
db.getBookmarksCostomTag = function(user_id, perPageItems) {
console.log('getBookmarksCostomTag', user_id, perPageItems);
perPageItems = perPageItems || 50;
- var sql1 = "(SELECT id, user_id, title, description, url, public, click_count, DATE_FORMAT(created_at, '%Y-%m-%d %H:%i:%s') as created_at, DATE_FORMAT(last_click, '%Y-%m-%d %H:%i:%s') as last_click FROM `bookmarks` WHERE `user_id` = '" + user_id + "' ORDER BY `click_count` DESC LIMIT 0, "+ perPageItems +")";
- var sql2 = "(SELECT id, user_id, title, description, url, public, click_count, DATE_FORMAT(created_at, '%Y-%m-%d %H:%i:%s') as created_at, DATE_FORMAT(last_click, '%Y-%m-%d %H:%i:%s') as last_click FROM `bookmarks` WHERE `user_id` = '" + user_id + "' ORDER BY `created_at` DESC LIMIT 0, "+ perPageItems +")";
- var sql3 = "(SELECT id, user_id, title, description, url, public, click_count, DATE_FORMAT(created_at, '%Y-%m-%d %H:%i:%s') as created_at, DATE_FORMAT(last_click, '%Y-%m-%d %H:%i:%s') as last_click FROM `bookmarks` WHERE `user_id` = '" + user_id + "' ORDER BY `last_click` DESC LIMIT 0, "+ perPageItems +")";
+ var sql1 = "(SELECT id, user_id, title, description, url, public, click_count, DATE_FORMAT(created_at, '%Y-%m-%d %H:%i:%s') as created_at, DATE_FORMAT(last_click, '%Y-%m-%d %H:%i:%s') as last_click FROM `bookmarks` WHERE `user_id` = '" + user_id + "' ORDER BY `click_count` DESC LIMIT 0, " + perPageItems + ")";
+ var sql2 = "(SELECT id, user_id, title, description, url, public, click_count, DATE_FORMAT(created_at, '%Y-%m-%d %H:%i:%s') as created_at, DATE_FORMAT(last_click, '%Y-%m-%d %H:%i:%s') as last_click FROM `bookmarks` WHERE `user_id` = '" + user_id + "' ORDER BY `created_at` DESC LIMIT 0, " + perPageItems + ")";
+ var sql3 = "(SELECT id, user_id, title, description, url, public, click_count, DATE_FORMAT(created_at, '%Y-%m-%d %H:%i:%s') as created_at, DATE_FORMAT(last_click, '%Y-%m-%d %H:%i:%s') as last_click FROM `bookmarks` WHERE `user_id` = '" + user_id + "' ORDER BY `last_click` DESC LIMIT 0, " + perPageItems + ")";
var sql = sql1 + " UNION " + sql2 + " UNION " + sql3;
return new Promise(function(resolve, reject) {
@@ -751,6 +751,20 @@ db.getBookmarksByTag = function(params) {
})
}
+db.getExportBookmarksByTag = function(tag_id) {
+ var sql = "SELECT tags_bookmarks.tag_id, bookmarks.title, bookmarks.url, DATE_FORMAT(bookmarks.created_at, '%Y-%m-%d %H:%i:%s') as created_at, DATE_FORMAT(bookmarks.last_click, '%Y-%m-%d %H:%i:%s') as last_click FROM `tags_bookmarks`, `bookmarks` WHERE tags_bookmarks.tag_id = '" + tag_id + "' AND tags_bookmarks.bookmark_id = bookmarks.id ORDER BY bookmarks.click_count DESC";
+
+ return new Promise(function(resolve, reject) {
+ client.query(sql, (err, result) => {
+ if (err) {
+ reject(err);
+ } else {
+ resolve(result);
+ }
+ });
+ })
+}
+
db.getBookmarksSearch = function(params) {
var sql = "SELECT id, user_id, title, description, url, public, click_count, DATE_FORMAT(created_at, '%Y-%m-%d %H:%i:%s') as created_at, DATE_FORMAT(last_click, '%Y-%m-%d %H:%i:%s') as last_click FROM `bookmarks` WHERE 1=1";
diff --git a/package.json b/package.json
index 44894ca..936ff33 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"download": "^5.0.3",
"express": "~4.13.4",
"express-session": "^1.14.1",
+ "js-beautify": "^1.6.14",
"morgan": "^1.8.1",
"multer": "^1.3.0",
"mysql": "^2.11.1",
diff --git a/public/index.html b/public/index.html
index 35758c1..7b4b688 100644
--- a/public/index.html
+++ b/public/index.html
@@ -38,7 +38,7 @@
diff --git a/public/scripts/controllers/settings-controller.js b/public/scripts/controllers/settings-controller.js
index 304c48a..f15dc62 100644
--- a/public/scripts/controllers/settings-controller.js
+++ b/public/scripts/controllers/settings-controller.js
@@ -205,9 +205,14 @@ app.controller('settingsCtr', ['$scope', '$stateParams', '$filter', '$state', '$
}
$scope.exportBookmark = function() {
- toastr.warning('功能正在开发中,敬请期待......', '提示');
- return;
- $window.open("api/download?fileName=lcq-20170304213023.html");
+ var userId = $scope.user && $scope.user.id;
+ if (userId) {
+ // toastr.warning('功能正在开发中,敬请期待......', '提示');
+ // return;
+ $window.open("api/download?userId=" + userId + "&type=exportbookmark");
+ } else {
+ toastr.warning('用户信息无法获取到,请尝试按刷新网页再尝试!', '提示');
+ }
}
function updateShowStyle(showStyle) {
diff --git a/public/views/home.html b/public/views/home.html
index 3bad919..ff575b3 100644
--- a/public/views/home.html
+++ b/public/views/home.html
@@ -11,15 +11,15 @@
7、如果公用一台电脑,如何区分我收藏的跟别人收藏的书签?
在线书签管理工具,帮助你快速记录你喜欢的网站,并可以随时随地查看这些站点,而不必拘泥于使用的浏览器。无论在什么地方,只要能接入网络,就能打开属于你自己的网络书签,看到自己收藏的页面网址。
- 1、需要注册账号用户。(初步完成)
+ 1、需要注册账号用户。(完成)
2、网站展示有三种展示方式:导航,标签,列表,卡片。其中导航以分类展示,分类顺序可以在书签分类下面拖动编辑。按照点击的次数从高到低在每个分类里面提取16个书签,再按照最近添加的书签提取前面的16个书签,然后合并起来。标签是一个快捷方式。列表以表格展示,显示书签详细类容,按照点击次数优先显示,点击次数相同,则按添加顺序优先。卡片以卡片方式显示,按照最近添加优先显示。这几种展示方式,可以在设置里面默认一种你常用的方式。(完成)
3、在书签分类里面,可以更新分类,删除分类,新增分类,对分类显示进行排序。分类的标签默认按照添加日期展示,但是可以点击表格的标题,按照点击次数,添加日期,最后点击从大到小进行排序。(完成)
4、可以按照指定添加时间段,指定分类目录,指定网址关键字等进行查询。(完成)
5、添加书签的时候,会自动获取title,供用户编辑。其中:Insert键打开添加页面,再次按Insert键保存书签,Esc取消添加。(完成)
6、可以导入Chrome的书签导出文件,暂时做在设置里面。(完成)
7、书签可以作为公有或者私有,公有可供所有人搜索。(完成)
- 8、可以将搜索到其他用户的书签转存为自己的书签。(已完成)
- 9、可以将书签导出来,然后导入到浏览器。(未完成)
+ 8、可以将搜索到其他用户的书签转存为自己的书签。(完成)
+ 9、可以将书签导出来,然后导入到浏览器。(完成)
10、在热门标签里面,有在网上找的热门书签。可以转存收藏到自己书签里面。快捷键R随机查看热门书签。(完成)
11、新增备忘录功能,有时候随手要做点纪录,就方便了。任意界面按快捷键A增加备忘录。双击备忘录可查看详情!(完成)
12、在设置的全局链接,可设置快捷键,用来在任何页面,快速打开设置的链接。(完成)
diff --git a/public/views/settings.html b/public/views/settings.html
index 55d9049..6b753b6 100644
--- a/public/views/settings.html
+++ b/public/views/settings.html
@@ -6,7 +6,7 @@
我的信息
- 上传或导出书签
+ 上传导出
网站说明
@@ -123,6 +123,7 @@
4、导入的文件不能超过10M
5、如果重复导入,新的会覆盖旧的信息。
+ 6、注意:从浏览器导入进系统的书签,没有浏览器目录的树形结构,在浏览器没有目录的标签,统统转入系统未分类目录下面。
@@ -139,15 +140,15 @@
7、如果公用一台电脑,如何区分我收藏的跟别人收藏的书签?
在线书签管理工具,帮助你快速记录你喜欢的网站,并可以随时随地查看这些站点,而不必拘泥于使用的浏览器。无论在什么地方,只要能接入网络,就能打开属于你自己的网络书签,看到自己收藏的页面网址。
- 1、需要注册账号用户。(初步完成)
+ 1、需要注册账号用户。(完成)
2、网站展示有三种展示方式:导航,标签,列表,卡片。其中导航以分类展示,分类顺序可以在书签分类下面拖动编辑。按照点击的次数从高到低在每个分类里面提取16个书签,再按照最近添加的书签提取前面的16个书签,然后合并起来。标签是一个快捷方式。列表以表格展示,显示书签详细类容,按照点击次数优先显示,点击次数相同,则按添加顺序优先。卡片以卡片方式显示,按照最近添加优先显示。这几种展示方式,可以在设置里面默认一种你常用的方式。(完成)
3、在书签分类里面,可以更新分类,删除分类,新增分类,对分类显示进行排序。分类的标签默认按照添加日期展示,但是可以点击表格的标题,按照点击次数,添加日期,最后点击从大到小进行排序。(完成)
4、可以按照指定添加时间段,指定分类目录,指定网址关键字等进行查询。(完成)
5、添加书签的时候,会自动获取title,供用户编辑。其中:Insert键打开添加页面,再次按Insert键保存书签,Esc取消添加。(完成)
6、可以导入Chrome的书签导出文件,暂时做在设置里面。(完成)
7、书签可以作为公有或者私有,公有可供所有人搜索。(完成)
- 8、可以将搜索到其他用户的书签转存为自己的书签。(已完成)
- 9、可以将书签导出来,然后导入到浏览器。(未完成)
+ 8、可以将搜索到其他用户的书签转存为自己的书签。(完成)
+ 9、可以将书签导出来,然后导入到浏览器。(完成)
10、在热门标签里面,有在网上找的热门书签。可以转存收藏到自己书签里面。快捷键R随机查看热门书签。(完成)
11、新增备忘录功能,有时候随手要做点纪录,就方便了。任意界面按快捷键A增加备忘录。双击备忘录可查看详情!(完成)
12、在设置的全局链接,可设置快捷键,用来在任何页面,快速打开设置的链接。(完成)
diff --git a/routes/api.js b/routes/api.js
index ecc7efb..45a6a34 100644
--- a/routes/api.js
+++ b/routes/api.js
@@ -10,7 +10,8 @@ var webshot = require('webshot');
var fs = require('fs');
var request = require('request');
var cheerio = require('cheerio');
-const path = require('path');
+var path = require('path');
+var beautify_html = require('js-beautify').html;
var storage = multer.diskStorage({
destination: function(req, file, cb) {
@@ -19,7 +20,7 @@ var storage = multer.diskStorage({
filename: function(req, file, cb) {
var now = new Date().format('yyyyMMddhhmmss')
if (req.session.user) {
- cb(null, req.session.username + '-' + now + '.html')
+ cb(null, 'importbookmark-' + req.session.username + '-' + now + '.html')
} else {
cb(null, "UnknowUser" + '-' + now + '.html')
}
@@ -1446,16 +1447,64 @@ api.post('/updateNote', function(req, res) {
// 实现文件下载
api.get('/download', function(req, res) {
- var fileName = req.query.fileName;
- var filePath = path.join(path.resolve(__dirname, '..'), 'uploads', fileName);
- console.log('download fileName = ', fileName, ', download filePath = ' + filePath);
- res.download(filePath, function(err) {
- if (err) {
- console.log(err);
- } else {
- console.log('download filePath[ ' + filePath + ' ]success!');
- }
- });
+ console.log("download username = ", req.session.username);
+
+ var userId = req.query.userId;
+ var type = req.query.type;
+ if (!req.session.user || req.session.user.id != userId) {
+ res.send(401);
+ return;
+ }
+ if (type == 'exportbookmark' && userId) {
+ db.getTags(userId)
+ .then((tags) => {
+ var meta = '';
+ var init = 'BookmarksBookmarks
';
+ var $ = cheerio.load(init, {
+ decodeEntities: false,
+ xmlMode: true,
+ });
+
+ tags.forEach((tag, tagIndex) => {
+ $('#0').append('' + tag.name + '
'); // 增加文件夹
+ db.getExportBookmarksByTag(tag.id)
+ .then((bookmarks) => {
+ bookmarks.forEach((bookmark) => {
+ $('#' + bookmark.tag_id).append('' + bookmark.title + '');
+ });
+ if (tagIndex == tags.length - 1) {
+ console.log('export bookmarks document construct end...');
+ var now = new Date().format('yyyyMMddhhmmss')
+ var fileName = 'exportbookmark-' + req.session.username + '-' + now + '.html';
+ var filePath = path.join(path.resolve(__dirname, '..'), 'uploads', fileName);
+ fs.writeFile(filePath, beautify_html($.xml(), {
+ indent_size: 4,
+ }), function(err) {
+ if (err) {
+ console.log(err);
+ } else {
+ res.download(filePath, function(err) {
+ if (err) {
+ console.log(err);
+ } else {
+ console.log('download filePath[ ' + filePath + ' ]success!');
+ }
+ });
+ }
+ })
+ }
+ })
+ .catch((err) => {
+ console.log('getExportBookmarksByTag err', err);
+ })
+ })
+ })
+ .catch((err) => {
+ console.log('exportbookmark err', err);
+ });
+ } else {
+ res.send(401);
+ }
});
function md5(str) {