From 1bfdd28428f1973436abfa457bb051f3785d2800 Mon Sep 17 00:00:00 2001 From: luchenqun Date: Sun, 26 Feb 2017 20:39:00 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=B9=A6=E7=AD=BE=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E7=BC=96=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- database/db.js | 79 +++++++++- public/css/externe/ngDialog-theme-default.css | 146 ++++++++++++++++++ public/css/externe/ngDialog-theme-plain.css | 112 ++++++++++++++ public/css/externe/ngDialog.css | 87 +++++++++++ public/css/style.css | 2 +- public/index.html | 5 + public/scripts/app-angular.js | 2 +- public/scripts/controllers/tags-controller.js | 88 ++++++++++- .../externe/angular-sortable-view.min.js | 5 + public/scripts/externe/ngDialog.min.js | 2 + public/scripts/services/bookmark-service.js | 32 +++- public/views/dialog-del-tag.html | 13 ++ public/views/tags.html | 10 +- routes/api.js | 88 ++++++++++- 14 files changed, 647 insertions(+), 24 deletions(-) create mode 100644 public/css/externe/ngDialog-theme-default.css create mode 100644 public/css/externe/ngDialog-theme-plain.css create mode 100644 public/css/externe/ngDialog.css create mode 100644 public/scripts/externe/angular-sortable-view.min.js create mode 100644 public/scripts/externe/ngDialog.min.js create mode 100644 public/views/dialog-del-tag.html diff --git a/database/db.js b/database/db.js index c6a4a9a..b3cca0a 100644 --- a/database/db.js +++ b/database/db.js @@ -153,6 +153,58 @@ db.delBookmarkTags = function(bookmard_id) { }); } +db.getBookmarkIdsByTagId = function(tagId) { + var sql = "SELECT bookmark_id FROM `tags_bookmarks` WHERE `tag_id` = '" + tagId + "'"; + return new Promise(function(resolve, reject) { + client.query(sql, (err, result) => { + if (err) { + reject(err); + } else { + resolve(result); + } + }); + }); +} + +db.delTag = function(tagId) { + var sql = "DELETE FROM `tags` WHERE (`id`='" + tagId + "')"; + return new Promise(function(resolve, reject) { + client.query(sql, (err, result) => { + if (err) { + reject(err); + } else { + resolve(result.affectedRows); + } + }); + }); +} + +db.delTagBookmarks = function(tagId) { + var sql = "DELETE FROM `tags_bookmarks` WHERE (`tag_id`='" + tagId + "')"; + return new Promise(function(resolve, reject) { + client.query(sql, (err, result) => { + if (err) { + reject(err); + } else { + resolve(result.affectedRows); + } + }); + }); +} + +db.delBookmarks = function(bookmarkIds) { + var sql = "DELETE FROM `bookmarks` WHERE id IN (" + (bookmarkIds.toString() || ("-1")) + ")"; + return new Promise(function(resolve, reject) { + client.query(sql, (err, result) => { + if (err) { + reject(err); + } else { + resolve(result.affectedRows); + } + }); + }); +} + db.addTagsBookmarks = function(tags, bookmard_id) { sql = "INSERT INTO `tags_bookmarks` (`tag_id`, `bookmark_id`) VALUES"; for (var i = 0; i < tags.length; i++) { @@ -312,8 +364,8 @@ db.getTags = function(user_id) { }); }; -db.updateTag = function(tag) { - console.log('updateTag'); +db.updateTagName = function(tag) { + console.log('updateTagName'); var sql = "UPDATE `tags` SET `name`='" + tag.name + "' WHERE (`id`='" + tag.id + "')"; console.log(sql); return new Promise(function(resolve, reject) { @@ -327,6 +379,27 @@ db.updateTag = function(tag) { }); }; +db.updateTagsIndex = function(tagsIndex) { + console.log('updateTagsIndex'); + var sql = "UPDATE tags SET sort = CASE id "; + tagsIndex.forEach((tagIndex) => { + sql += "WHEN " + tagIndex.id + " THEN " + tagIndex.index + " "; + }) + var tagsId = tagsIndex.map((item) => item.id); + sql += "END WHERE id IN (" + tagsId.toString() + ")"; + + console.log(sql); + return new Promise(function(resolve, reject) { + client.query(sql, (err, result) => { + if (err) { + reject(err); + } else { + resolve(result.affectedRows); + } + }); + }); +}; + db.getTagsByIds = function(tagIds) { var sql = "SELECT * FROM `tags` WHERE id in(" + (tagIds.toString() || ("-1")) + ") GROUP BY id"; // 如果是空的,那查一个不存在的就行了。 console.log('db getTagsByIds = ', sql); @@ -417,7 +490,7 @@ db.getBookmarksNavigate = function(tags) { if (index >= 1) { sql += " UNION " } - sql += "(SELECT * FROM ((SELECT t.id AS tag_id, t.`name` as tag_name, 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, 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)"; + 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(sql); diff --git a/public/css/externe/ngDialog-theme-default.css b/public/css/externe/ngDialog-theme-default.css new file mode 100644 index 0000000..742c1bd --- /dev/null +++ b/public/css/externe/ngDialog-theme-default.css @@ -0,0 +1,146 @@ +@keyframes ngdialog-flyin { + 0% { + opacity: 0; + transform: translateY(-40px); + } + + 100% { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes ngdialog-flyout { + 0% { + opacity: 1; + transform: translateY(0); + } + + 100% { + opacity: 0; + transform: translateY(-40px); + } +} + +.ngdialog.ngdialog-theme-default { + padding-bottom: 160px; + padding-top: 160px; +} + +.ngdialog.ngdialog-theme-default.ngdialog-closing .ngdialog-content { + animation: ngdialog-flyout .5s; +} + +.ngdialog.ngdialog-theme-default .ngdialog-content { + animation: ngdialog-flyin .5s; + background: #f0f0f0; + border-radius: 5px; + color: #444; + font-family: 'Helvetica',sans-serif; + font-size: 1.1em; + line-height: 1.5em; + margin: 0 auto; + max-width: 100%; + padding: 1em; + position: relative; + width: 450px; +} + +.ngdialog.ngdialog-theme-default .ngdialog-close { + border-radius: 5px; + cursor: pointer; + position: absolute; + right: 0; + top: 0; +} + +.ngdialog.ngdialog-theme-default .ngdialog-close:before { + background: transparent; + border-radius: 3px; + color: #bbb; + content: '\00D7'; + font-size: 26px; + font-weight: 400; + height: 30px; + line-height: 26px; + position: absolute; + right: 3px; + text-align: center; + top: 3px; + width: 30px; +} + +.ngdialog.ngdialog-theme-default .ngdialog-close:hover:before,.ngdialog.ngdialog-theme-default .ngdialog-close:active:before { + color: #777; +} + +.ngdialog.ngdialog-theme-default .ngdialog-message { + margin-bottom: .5em; +} + +.ngdialog.ngdialog-theme-default .ngdialog-input { + margin-bottom: 1em; +} + +.ngdialog.ngdialog-theme-default .ngdialog-input textarea,.ngdialog.ngdialog-theme-default .ngdialog-input input[type="text"],.ngdialog.ngdialog-theme-default .ngdialog-input input[type="password"],.ngdialog.ngdialog-theme-default .ngdialog-input input[type="email"],.ngdialog.ngdialog-theme-default .ngdialog-input input[type="url"] { + background: #fff; + border: 0; + border-radius: 3px; + font-family: inherit; + font-size: inherit; + font-weight: inherit; + margin: 0 0 .25em; + min-height: 2.5em; + padding: .25em .67em; + width: 100%; +} + +.ngdialog.ngdialog-theme-default .ngdialog-input textarea:focus,.ngdialog.ngdialog-theme-default .ngdialog-input input[type="text"]:focus,.ngdialog.ngdialog-theme-default .ngdialog-input input[type="password"]:focus,.ngdialog.ngdialog-theme-default .ngdialog-input input[type="email"]:focus,.ngdialog.ngdialog-theme-default .ngdialog-input input[type="url"]:focus { + box-shadow: inset 0 0 0 2px #8dbdf1; + outline: none; +} + +.ngdialog.ngdialog-theme-default .ngdialog-buttons { + *zoom: 1; +} + +.ngdialog.ngdialog-theme-default .ngdialog-buttons:after { + content: ''; + display: table; + clear: both; +} + +.ngdialog.ngdialog-theme-default .ngdialog-button { + border: 0; + border-radius: 3px; + cursor: pointer; + float: right; + font-family: inherit; + font-size: .8em; + letter-spacing: .1em; + line-height: 1em; + margin: 0 0 0 .5em; + padding: .75em 2em; + text-transform: uppercase; +} + +.ngdialog.ngdialog-theme-default .ngdialog-button:focus { + animation: ngdialog-pulse 1.1s infinite; + outline: none; +} + +@media (max-width: 568px) { + .ngdialog.ngdialog-theme-default .ngdialog-button:focus { + animation: none; + } +} + +.ngdialog.ngdialog-theme-default .ngdialog-button.ngdialog-button-primary { + background: #3288e6; + color: #fff; +} + +.ngdialog.ngdialog-theme-default .ngdialog-button.ngdialog-button-secondary { + background: #e0e0e0; + color: #777; +} diff --git a/public/css/externe/ngDialog-theme-plain.css b/public/css/externe/ngDialog-theme-plain.css new file mode 100644 index 0000000..2b101f4 --- /dev/null +++ b/public/css/externe/ngDialog-theme-plain.css @@ -0,0 +1,112 @@ +.ngdialog.ngdialog-theme-plain { + padding-bottom: 160px; + padding-top: 160px; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-content { + background: #fff; + color: #444; + font-family: 'Helvetica Neue',sans-serif; + font-size: 1.1em; + line-height: 1.5em; + margin: 0 auto; + max-width: 100%; + padding: 1em; + position: relative; + width: 450px; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-content h1,.ngdialog.ngdialog-theme-plain .ngdialog-content h2,.ngdialog.ngdialog-theme-plain .ngdialog-content h3,.ngdialog.ngdialog-theme-plain .ngdialog-content h4,.ngdialog.ngdialog-theme-plain .ngdialog-content h5,.ngdialog.ngdialog-theme-plain .ngdialog-content h6,.ngdialog.ngdialog-theme-plain .ngdialog-content p,.ngdialog.ngdialog-theme-plain .ngdialog-content ul,.ngdialog.ngdialog-theme-plain .ngdialog-content li { + color: inherit; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-close { + cursor: pointer; + position: absolute; + right: 0; + top: 0; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-close:before { + background: transparent; + color: #bbb; + content: "\00D7"; + font-size: 26px; + font-weight: 400; + height: 30px; + line-height: 26px; + position: absolute; + right: 3px; + text-align: center; + top: 3px; + width: 30px; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-close:hover:before,.ngdialog.ngdialog-theme-plain .ngdialog-close:active:before { + color: #777; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-message { + margin-bottom: .5em; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-input { + margin-bottom: 1em; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-input textarea,.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="text"],.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="password"],.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="email"],.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="url"] { + background: #f0f0f0; + border: 0; + font-family: inherit; + font-size: inherit; + font-weight: inherit; + margin: 0 0 .25em; + min-height: 2.5em; + padding: .25em .67em; + width: 100%; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-input textarea:focus,.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="text"]:focus,.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="password"]:focus,.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="email"]:focus,.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="url"]:focus { + box-shadow: inset 0 0 0 2px rgba(0,0,0,0.2); + outline: none; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-buttons:after { + clear: both; + content: ''; + display: table; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-button { + border: 0; + cursor: pointer; + float: right; + font-family: inherit; + font-size: .8em; + letter-spacing: .1em; + line-height: 1em; + margin: 0 0 0 .5em; + padding: .75em 2em; + text-transform: uppercase; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-button:focus { + animation: ngdialog-pulse 1.1s infinite; + outline: none; +} + +@media (max-width: 568px) { + .ngdialog.ngdialog-theme-plain .ngdialog-button:focus { + animation: none; + } +} + +.ngdialog.ngdialog-theme-plain .ngdialog-button.ngdialog-button-primary { + background: #3288e6; + color: #fff; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-button.ngdialog-button-secondary { + background: #e0e0e0; + color: #777; +} diff --git a/public/css/externe/ngDialog.css b/public/css/externe/ngDialog.css new file mode 100644 index 0000000..5b3485c --- /dev/null +++ b/public/css/externe/ngDialog.css @@ -0,0 +1,87 @@ +@keyframes ngdialog-fadeout { + 0% { + opacity: 1; + } + 100% { + opacity: 0; + } +} + +@keyframes ngdialog-fadein { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} + +.ngdialog { + box-sizing: border-box; +} + +.ngdialog *, +.ngdialog *:before, +.ngdialog *:after { + box-sizing: inherit; +} + +.ngdialog { + position: fixed; + overflow: auto; + -webkit-overflow-scrolling: touch; + z-index: 10000; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +.ngdialog.ngdialog-disabled-animation, +.ngdialog.ngdialog-disabled-animation .ngdialog-overlay, +.ngdialog.ngdialog-disabled-animation .ngdialog-content { + animation: none!important; +} + +.ngdialog-overlay { + position: fixed; + background: rgba(0, 0, 0, 0.4); + top: 0; + right: 0; + bottom: 0; + left: 0; + -webkit-backface-visibility: hidden; + animation: ngdialog-fadein 0.5s; +} + +.ngdialog-no-overlay { + pointer-events: none; +} + +.ngdialog.ngdialog-closing .ngdialog-overlay { + -webkit-backface-visibility: hidden; + animation: ngdialog-fadeout 0.5s; +} + +.ngdialog-content { + background: white; + -webkit-backface-visibility: hidden; + animation: ngdialog-fadein 0.5s; + pointer-events: all; +} + +.ngdialog.ngdialog-closing .ngdialog-content { + -webkit-backface-visibility: hidden; + animation: ngdialog-fadeout 0.5s; +} + +.ngdialog-close:before { + font-family: 'Helvetica', Arial, sans-serif; + content: '\00D7'; + cursor: pointer; +} + +html.ngdialog-open, +body.ngdialog-open { + overflow: hidden; +} diff --git a/public/css/style.css b/public/css/style.css index 28363e1..c504312 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -54,7 +54,7 @@ code { -o-text-overflow: ellipsis; overflow: hidden; color: #212121; - cursor: move; + cursor: default; border: 1px dashed #3388FF; } .img-fixed-size { diff --git a/public/index.html b/public/index.html index 2caffa5..a612e24 100644 --- a/public/index.html +++ b/public/index.html @@ -11,6 +11,9 @@ + + + @@ -61,5 +64,7 @@ + + diff --git a/public/scripts/app-angular.js b/public/scripts/app-angular.js index 38de50e..55a4666 100644 --- a/public/scripts/app-angular.js +++ b/public/scripts/app-angular.js @@ -1,4 +1,4 @@ -var app = angular.module('bookmarkApp', ['ui.router', 'ngCookies', 'infinite-scroll']); +var app = angular.module('bookmarkApp', ['ui.router', 'ngCookies', 'infinite-scroll', 'angular-sortable-view', 'ngDialog']); app.config(function($stateProvider, $urlRouterProvider, $httpProvider) { $httpProvider.interceptors.push('httpInterceptor'); diff --git a/public/scripts/controllers/tags-controller.js b/public/scripts/controllers/tags-controller.js index b1cdb1c..6055e35 100644 --- a/public/scripts/controllers/tags-controller.js +++ b/public/scripts/controllers/tags-controller.js @@ -1,10 +1,12 @@ -app.controller('tagsCtr', ['$scope', '$filter', '$window', '$stateParams', '$timeout', 'bookmarkService', 'pubSubService', function($scope, $filter, $window, $stateParams, $timeout, bookmarkService, pubSubService) { +app.controller('tagsCtr', ['$scope', '$filter', '$window', '$stateParams', '$timeout', 'ngDialog', 'bookmarkService', 'pubSubService', function($scope, $filter, $window, $stateParams, $timeout, ngDialog, bookmarkService, pubSubService) { console.log("Hello tagsCtr...", $stateParams); getTags({}); const perPageItems = 20; + var dialog = null; $scope.loadBookmarks = false; $scope.tags = []; // 书签数据 + $scope.tagsIndex = []; // 书签索引 $scope.bookmarkClicked = false; $scope.bookmarks = []; $scope.bookmarkCount = 0; @@ -13,6 +15,7 @@ app.controller('tagsCtr', ['$scope', '$filter', '$window', '$stateParams', '$tim $scope.inputPage = ''; $scope.currentTagId = ($stateParams && $stateParams.tagId) || ''; $scope.edit = false; + $scope.waitDelTag = {}; pubSubService.subscribe('MenuCtr.tags', $scope, function(event, data) { console.log('subscribe MenuCtr.tags', data); @@ -136,7 +139,7 @@ app.controller('tagsCtr', ['$scope', '$filter', '$window', '$stateParams', '$tim name: tag.name, } - bookmarkService.updateTag(params) + bookmarkService.updateTagName(params) .then((data) => { if (data.retCode == 0) { toastr.success(tag.name + ' 更新成功!', "提示"); @@ -152,10 +155,36 @@ app.controller('tagsCtr', ['$scope', '$filter', '$window', '$stateParams', '$tim } $scope.delTag = function(tag) { - if (tag.name == "未分类") { - toastr.warning('这个是系统默认分类,暂时不允许删除!', "警告"); - return; + console.log('delTag..........') + $scope.waitDelTag = $.extend(true, {}, tag); // 利用jQuery执行深度拷贝 + dialog = ngDialog.open({ + template: './views/dialog-del-tag.html', + className: 'ngdialog-theme-default', + scope: $scope + }); + } + + $scope.confirmDelTag = function(tagId, tagName) { + console.log(tagId); + ngDialog.close(dialog); + var params = { + del: tagName == '未分类' ? false : true, + id: tagId, } + bookmarkService.delTag(params) + .then((data) => { + if (data.retCode == 0) { + toastr.success('分类删除成功!将自动更新分类信息', "提示"); + getTags({}); + } else { + toastr.error('分类删除失败!', "提示"); + getTags({}); + } + }) + .catch((err) => { + toastr.error('分类删除失败!错误提示:' + JSON.stringify(err), "提示"); + getTags({}); + }); } $scope.backTag = function(tag) { @@ -163,16 +192,63 @@ app.controller('tagsCtr', ['$scope', '$filter', '$window', '$stateParams', '$tim tag.name = tag.oldName; } + $scope.storeTagIndex = function() { + $scope.tagsIndex = []; + $scope.tags.forEach((tag, index) => { + $scope.tagsIndex[index] = { + id: tag.id, + index: index, + } + }) + console.log('storeTagIndex'); + } + + $scope.updateTagIndex = function() { + // 要开个timer,因为释放鼠标模型还没更新 + setTimeout(function() { + var needUpdate = false; + for (var i = 0; i < $scope.tags.length; i++) { + if ($scope.tags[i].id != $scope.tagsIndex[i].id) { + needUpdate = true; + } + $scope.tagsIndex[i] = { + id: $scope.tags[i].id, + index: i, + } + } + if (needUpdate) { + bookmarkService.updateTagsIndex($scope.tagsIndex) + .then((data) => { + if (data.retCode == 0) { + toastr.success('分类排序更新成功!', "提示"); + } else { + toastr.error('分类排序更新失败!', "提示"); + getTags({}); + } + }) + .catch((err) => { + toastr.error('分类排序更新失败!错误提示:' + JSON.stringify(err), "提示"); + getTags({}); + }); + } + console.log('updateTagIndex needUpdate = ' + needUpdate) + }, 300) + } + function getTags(params) { bookmarkService.getTags(params) .then((data) => { $scope.tags = [] + var find = false; data.forEach((tag) => { tag.edit = false; tag.oldName = tag.name; $scope.tags.push(tag); + if (tag.id == $scope.currentTagId) { + find = true; // 如果是删了分类返回来,那么要重新默认选中第一个分类 + } }) - + if (!find) $scope.currentTagId = null; if (!$scope.currentTagId && $scope.tags.length > 0) { $scope.currentTagId = $scope.tags[0].id; $scope.tags[0].bookmarkClicked = true; diff --git a/public/scripts/externe/angular-sortable-view.min.js b/public/scripts/externe/angular-sortable-view.min.js new file mode 100644 index 0000000..549a37c --- /dev/null +++ b/public/scripts/externe/angular-sortable-view.min.js @@ -0,0 +1,5 @@ +/* + Copyright Kamil Pękala http://github.com/kamilkp + angular-sortable-view v0.0.13 2015/01/13 +*/ +!function(a,b){"use strict";function c(a){if(!("clientX"in a||"clientY"in a)){var b=a.touches||a.originalEvent.touches;b&&b.length&&(a.clientX=b[0].clientX,a.clientY=b[0].clientY),a.preventDefault()}}function d(a){if(a=a[0],a.previousElementSibling)return b.element(a.previousElementSibling);for(var c=a.previousSibling;null!=c&&1!=c.nodeType;)c=c.previousSibling;return b.element(c)}function e(a,b){var c=d(a);c.length>0?c.after(b):a.parent().prepend(b)}function f(a,c){return a instanceof b.element&&(a=a[0]),null!==i?a[i](c):void 0}var g=b.module("angular-sortable-view",[]);g.directive("svRoot",[function(){function a(a,b,c){return c?a.x-b.x<0:a.y-b.y<0}function b(a){return g[a]}function c(a){delete g[a]}var d,g=Object.create(null);return{restrict:"A",controller:["$scope","$attrs","$interpolate","$parse",function(h,i,j,k){var l=j(i.svRoot)(h)||h.$id;g[l]||(g[l]=[]);var m,n,o,p,q,r,s=!1,t=k(i.svOnSort);i.svOnStart=i.$$element[0].attributes["sv-on-start"],i.svOnStart=i.svOnStart&&i.svOnStart.value,i.svOnStop=i.$$element[0].attributes["sv-on-stop"],i.svOnStop=i.svOnStop&&i.svOnStop.value;var u=k(i.svOnStart),v=k(i.svOnStop);if(this.sortingInProgress=function(){return d},i.svGrid){if(s="true"===i.svGrid?!0:"false"===i.svGrid?!1:null,null===s)throw"Invalid value of sv-grid attribute"}else h.$watchCollection(function(){return b(l)},function(a){s=!1;var b=a.filter(function(a){return!a.container}).map(function(a){return{part:a.getPart().id,y:a.element[0].getBoundingClientRect().top}}),c=Object.create(null);b.forEach(function(a){c[a.part]?c[a.part].push(a.y):c[a.part]=[a.y]}),Object.keys(c).forEach(function(a){c[a].sort(),c[a].forEach(function(b,d){d0&&b===c[a][d+1]&&(s=!0)})})});this.$moveUpdate=function(c,g,i,j,k,t,v){var w=i[0].getBoundingClientRect();"element"===c.tolerance&&(g={x:~~(w.left+w.width/2),y:~~(w.top+w.height/2)}),d=!0,m=[],n||(k?(n=k.clone(),n.removeClass("ng-hide")):(n=j.clone(),n.addClass("sv-visibility-hidden"),n.addClass("sv-placeholder"),n.css({height:w.height+"px",width:w.width+"px"})),j.after(n),j.addClass("ng-hide"),q=j,o=c,p=i,u(h,{$helper:{element:p},$part:t.model(t.scope),$index:v,$item:t.model(t.scope)[v]}),h.$root&&h.$root.$$phase||h.$apply()),p[0].reposition({x:g.x+document.body.scrollLeft-g.offset.x*w.width,y:g.y+document.body.scrollTop-g.offset.y*w.height}),b(l).forEach(function(b){if(null==c.containment||f(b.element,c.containment)||f(b.element,c.containment+" *")){var d=b.element[0].getBoundingClientRect(),e={x:~~(d.left+d.width/2),y:~~(d.top+d.height/2)};b.container||!b.element[0].scrollHeight&&!b.element[0].scrollWidth||m.push({element:b.element,q:(e.x-g.x)*(e.x-g.x)+(e.y-g.y)*(e.y-g.y),view:b.getPart(),targetIndex:b.getIndex(),after:a(e,g,s)}),b.container&&!b.element[0].querySelector("[sv-element]:not(.sv-placeholder):not(.sv-source)")&&m.push({element:b.element,q:(e.x-g.x)*(e.x-g.x)+(e.y-g.y)*(e.y-g.y),view:b.getPart(),targetIndex:0,container:!0})}});var x=n[0].getBoundingClientRect(),y={x:~~(x.left+x.width/2),y:~~(x.top+x.height/2)};m.push({q:(y.x-g.x)*(y.x-g.x)+(y.y-g.y)*(y.y-g.y),element:n,placeholder:!0}),m.sort(function(a,b){return a.q-b.q}),m.forEach(function(a,b){0!==b||a.placeholder||a.container?0===b&&a.container?(r=a,a.element.append(n)):a.element.removeClass("sv-candidate"):(r=a,a.element.addClass("sv-candidate"),a.after?a.element.after(n):e(a.element,n))})},this.$drop=function(a,b,c){function e(){if(d=!1,n.remove(),p.remove(),q.removeClass("ng-hide"),m=void 0,n=void 0,c=void 0,p=void 0,q=void 0,v(h,{$part:a.model(a.scope),$index:b,$item:a.model(a.scope)[b]}),r){r.element.removeClass("sv-candidate");var e=a.model(a.scope).splice(b,1),f=r.targetIndex;r.view===a&&r.targetIndex>b&&f--,r.after&&f++,r.view.model(r.view.scope).splice(f,0,e[0]),(r.view!==a||b!==f)&&t(h,{$partTo:r.view.model(r.view.scope),$partFrom:a.model(a.scope),$item:e[0],$indexTo:f,$indexFrom:b})}r=void 0,h.$root&&h.$root.$$phase||h.$apply()}if(n)if(c.revert){var f=n[0].getBoundingClientRect(),g=p[0].getBoundingClientRect(),i=Math.sqrt(Math.pow(g.top-f.top,2)+Math.pow(g.left-f.left,2)),j=+c.revert*i/200;j=Math.min(j,+c.revert),["-webkit-","-moz-","-ms-","-o-",""].forEach(function(a){"undefined"!=typeof p[0].style[a+"transition"]&&(p[0].style[a+"transition"]="all "+j+"ms ease")}),setTimeout(e,j),p.css({top:f.top+document.body.scrollTop+"px",left:f.left+document.body.scrollLeft+"px"})}else e()},this.addToSortableElements=function(a){b(l).push(a)},this.removeFromSortableElements=function(a){var d=b(l),e=d.indexOf(a);e>-1&&(d.splice(e,1),0===d.length&&c(l))}}]}}]),g.directive("svPart",["$parse",function(a){return{restrict:"A",require:"^svRoot",controller:["$scope",function(a){a.$ctrl=this,this.getPart=function(){return a.part},this.$drop=function(b,c){a.$sortableRoot.$drop(a.part,b,c)}}],scope:!0,link:function(b,c,d,e){if(!d.svPart)throw new Error("no model provided");var f=a(d.svPart);if(!f.assign)throw new Error("model not assignable");b.part={id:b.$id,element:c,model:f,scope:b},b.$sortableRoot=e;var g={element:c,getPart:b.$ctrl.getPart,container:!0};e.addToSortableElements(g),b.$on("$destroy",function(){e.removeFromSortableElements(g)})}}}]),g.directive("svElement",["$parse",function(a){return{restrict:"A",require:["^svPart","^svRoot"],controller:["$scope",function(a){a.$ctrl=this}],link:function(d,e,f,g){function h(h){function i(a){c(a),n||(e.parent().prepend(q),n=!0),g[1].$moveUpdate(k,{x:a.clientX,y:a.clientY,offset:t},q,e,m,g[0].getPart(),d.$index)}if(c(h),!g[1].sortingInProgress()&&(0==h.button||"mousedown"!==h.type)){n=!1;var k=a(f.svElement)(d);if(k=b.extend({},{tolerance:"pointer",revert:200,containment:"html"},k),k.containment)var p=j.call(e,k.containment)[0].getBoundingClientRect();var q,r=e,s=e[0].getBoundingClientRect();l||(l=g[0].helper),m||(m=g[0].placeholder),l?(q=l.clone(),q.removeClass("ng-hide"),q.css({left:s.left+document.body.scrollLeft+"px",top:s.top+document.body.scrollTop+"px"}),r.addClass("sv-visibility-hidden")):(q=r.clone(),q.addClass("sv-helper").css({left:s.left+document.body.scrollLeft+"px",top:s.top+document.body.scrollTop+"px",width:s.width+"px"})),q[0].reposition=function(a){var b=a.x,c=a.y,d=q[0].getBoundingClientRect(),e=document.body;p&&(cp.top+e.scrollTop+p.height&&(c=p.top+e.scrollTop+p.height-d.height),bp.left+e.scrollLeft+p.width&&(b=p.left+e.scrollLeft+p.width-d.width)),this.style.left=b-e.scrollLeft+"px",this.style.top=c-e.scrollTop+"px"};var t={x:(h.clientX-s.left)/s.width,y:(h.clientY-s.top)/s.height};o.addClass("sv-sorting-in-progress"),o.on("mousemove touchmove",i).on("mouseup touchend touchcancel",function u(){o.off("mousemove touchmove",i),o.off("mouseup touchend touchcancel",u),o.removeClass("sv-sorting-in-progress"),n&&g[0].$drop(d.$index,k),e.removeClass("sv-visibility-hidden")})}}var i={element:e,getPart:g[0].getPart,getIndex:function(){return d.$index}};g[1].addToSortableElements(i),d.$on("$destroy",function(){g[1].removeFromSortableElements(i)});var k=e;k.on("mousedown touchstart",h),d.$watch("$ctrl.handle",function(a){a&&(k.off("mousedown touchstart",h),k=a,k.on("mousedown touchstart",h))});var l;d.$watch("$ctrl.helper",function(a){a&&(l=a)});var m;d.$watch("$ctrl.placeholder",function(a){a&&(m=a)});var n,o=(b.element(document.body),b.element(document.documentElement))}}}]),g.directive("svHandle",function(){return{require:"?^svElement",link:function(a,b,c,d){d&&(d.handle=b.add(d.handle))}}}),g.directive("svHelper",function(){return{require:["?^svPart","?^svElement"],link:function(a,b,c,d){b.addClass("sv-helper").addClass("ng-hide"),d[1]?d[1].helper=b:d[0]&&(d[0].helper=b)}}}),g.directive("svPlaceholder",function(){return{require:["?^svPart","?^svElement"],link:function(a,b,c,d){b.addClass("sv-placeholder").addClass("ng-hide"),d[1]?d[1].placeholder=b:d[0]&&(d[0].placeholder=b)}}}),b.element(document.head).append([""].join(""));var h=document.documentElement,i=h.matches?"matches":h.matchesSelector?"matchesSelector":h.webkitMatches?"webkitMatches":h.webkitMatchesSelector?"webkitMatchesSelector":h.msMatches?"msMatches":h.msMatchesSelector?"msMatchesSelector":h.mozMatches?"mozMatches":h.mozMatchesSelector?"mozMatchesSelector":null;if(null==i)throw"This browser doesn't support the HTMLElement.matches method";var j=b.element.prototype.closest||function(a){for(var c=this[0].parentNode;c!==document.documentElement&&!c[i](a);)c=c.parentNode;return c[i](a)?b.element(c):b.element()};"function"!=typeof b.element.prototype.add&&(b.element.prototype.add=function(a){var c,d=b.element();for(a=b.element(a),c=0;c0)return void e[0].focus();var f=B.filterVisibleElements(b.querySelectorAll("h1,h2,h3,h4,h5,h6,p,span"));if(f.length>0){var g=f[0];c(g).attr("tabindex","-1").css("outline","0"),g.focus()}}},getFocusableElements:function(a){var b=a[0],c=b.querySelectorAll(h),d=B.filterTabbableElements(c);return B.filterVisibleElements(d)},filterTabbableElements:function(a){for(var b=[],d=0;d0||d.offsetHeight>0)&&b.push(d)}return b},getActiveDialog:function(){var a=document.querySelectorAll(".ngdialog");return 0===a.length?null:c(a[a.length-1])},applyAriaAttributes:function(a,b){if(b.ariaAuto){if(!b.ariaRole){var c=B.getFocusableElements(a).length>0?"dialog":"alertdialog";b.ariaRole=c}b.ariaLabelledBySelector||(b.ariaLabelledBySelector="h1,h2,h3,h4,h5,h6"),b.ariaDescribedBySelector||(b.ariaDescribedBySelector="article,section,p")}b.ariaRole&&a.attr("role",b.ariaRole),B.applyAriaAttribute(a,"aria-labelledby",b.ariaLabelledById,b.ariaLabelledBySelector),B.applyAriaAttribute(a,"aria-describedby",b.ariaDescribedById,b.ariaDescribedBySelector)},applyAriaAttribute:function(a,b,d,e){if(d&&a.attr(b,d),e){var f=a.attr("id"),g=a[0].querySelector(e);if(!g)return;var h=f+"-"+b;return c(g).attr("id",h),a.attr(b,h),h}},detectUIRouter:function(){try{return a.module("ui.router"),!0}catch(b){return!1}},getRouterLocationEventName:function(){return B.detectUIRouter()?"$stateChangeStart":"$locationChangeStart"}},C={__PRIVATE__:B,open:function(f){function g(b,c){var c=c||{};return c.headers=c.headers||{},a.extend(c.headers,{Accept:"text/html"}),v.$broadcast("ngDialog.templateLoading",b),u.get(b,c).then(function(a){return v.$broadcast("ngDialog.templateLoaded",b),a.data||""})}function h(b){return b?a.isString(b)&&q.plain?b:"boolean"!=typeof q.cache||q.cache?g(b,{cache:r}):g(b,{cache:!1}):"Empty template"}var j=null;if(f=f||{},!(n&&f.name&&(j=f.name.toLowerCase().replace(/\s/g,"-")+"-dialog",this.isOpen(j)))){var q=a.copy(b),D=++e;j=j||"ngdialog"+D,l.push(j),"undefined"!=typeof q.data&&("undefined"==typeof f.data&&(f.data={}),f.data=a.merge(a.copy(q.data),f.data)),a.extend(q,f);var E;p[j]=E=t.defer();var F;k[j]=F=a.isObject(q.scope)?q.scope.$new():v.$new();var G,H,I,J=a.extend({},q.resolve);return a.forEach(J,function(b,c){J[c]=a.isString(b)?z.get(b):z.invoke(b,null,null,c)}),t.all({template:h(q.template||q.templateUrl),locals:t.all(J)}).then(function(b){var e=b.template,f=b.locals;q.showClose&&(e+='
');var g=q.overlay?"":" ngdialog-no-overlay";if(G=c('
'),G.html(q.overlay?'
'+e+"
":'
'+e+"
"),G.data("$ngDialogOptions",q),F.ngDialogId=j,q.data&&a.isString(q.data)){var h=q.data.replace(/^\s*/,"")[0];F.ngDialogData="{"===h||"["===h?a.fromJson(q.data):new String(q.data),F.ngDialogData.ngDialogId=j}else q.data&&a.isObject(q.data)&&(F.ngDialogData=q.data,F.ngDialogData.ngDialogId=j);if(q.className&&G.addClass(q.className),q.appendClassName&&G.addClass(q.appendClassName),q.width&&(I=G[0].querySelector(".ngdialog-content"),a.isString(q.width)?I.style.width=q.width:I.style.width=q.width+"px"),q.height&&(I=G[0].querySelector(".ngdialog-content"),a.isString(q.height)?I.style.height=q.height:I.style.height=q.height+"px"),q.disableAnimation&&G.addClass(i),H=q.appendTo&&a.isString(q.appendTo)?a.element(document.querySelector(q.appendTo)):A.body,B.applyAriaAttributes(G,q),q.preCloseCallback){var k;a.isFunction(q.preCloseCallback)?k=q.preCloseCallback:a.isString(q.preCloseCallback)&&F&&(a.isFunction(F[q.preCloseCallback])?k=F[q.preCloseCallback]:F.$parent&&a.isFunction(F.$parent[q.preCloseCallback])?k=F.$parent[q.preCloseCallback]:v&&a.isFunction(v[q.preCloseCallback])&&(k=v[q.preCloseCallback])),k&&G.data("$ngDialogPreCloseCallback",k)}if(F.closeThisDialog=function(a){B.closeDialog(G,a)},q.controller&&(a.isString(q.controller)||a.isArray(q.controller)||a.isFunction(q.controller))){var l;q.controllerAs&&a.isString(q.controllerAs)&&(l=q.controllerAs);var n=y(q.controller,a.extend(f,{$scope:F,$element:G}),!0,l);q.bindToController&&a.extend(n.instance,{ngDialogId:F.ngDialogId,ngDialogData:F.ngDialogData,closeThisDialog:F.closeThisDialog,confirm:F.confirm}),"function"==typeof n?G.data("$ngDialogControllerController",n()):G.data("$ngDialogControllerController",n)}if(w(function(){var a=document.querySelectorAll(".ngdialog");B.deactivateAll(a),s(G)(F);var b=x.innerWidth-A.body.prop("clientWidth");A.html.addClass(q.bodyClassName),A.body.addClass(q.bodyClassName);var c=b-(x.innerWidth-A.body.prop("clientWidth"));c>0&&B.setBodyPadding(c),H.append(G),B.activate(G),q.trapFocus&&B.autoFocus(G),q.name?v.$broadcast("ngDialog.opened",{dialog:G,name:q.name}):v.$broadcast("ngDialog.opened",G)}),m||(A.body.bind("keydown",B.onDocumentKeydown),m=!0),q.closeByNavigation){var p=B.getRouterLocationEventName();v.$on(p,function(a){B.closeDialog(G)===!1&&a.preventDefault()})}if(q.preserveFocus&&G.data("$ngDialogPreviousFocus",document.activeElement),d=function(a){var b=!!q.closeByDocument&&c(a.target).hasClass("ngdialog-overlay"),d=c(a.target).hasClass("ngdialog-close");(b||d)&&C.close(G.attr("id"),d?"$closeButton":"$document")},"undefined"!=typeof x.Hammer){var r=F.hammerTime=x.Hammer(G[0]);r.on("tap",d)}else G.bind("click",d);return o+=1,C}),{id:j,closePromise:E.promise,close:function(a){B.closeDialog(G,a)}}}},openConfirm:function(d){var e=t.defer(),f=a.copy(b);d=d||{},"undefined"!=typeof f.data&&("undefined"==typeof d.data&&(d.data={}),d.data=a.merge(a.copy(f.data),d.data)),a.extend(f,d),f.scope=a.isObject(f.scope)?f.scope.$new():v.$new(),f.scope.confirm=function(a){e.resolve(a);var b=c(document.getElementById(g.id));B.performCloseDialog(b,a)};var g=C.open(f);if(g)return g.closePromise.then(function(a){return a?e.reject(a.value):e.reject()}),e.promise},isOpen:function(a){var b=c(document.getElementById(a));return b.length>0},close:function(a,b){var d=c(document.getElementById(a));if(d.length)B.closeDialog(d,b);else if("$escape"===a){var e=l[l.length-1];d=c(document.getElementById(e)),d.data("$ngDialogOptions").closeByEscape&&B.closeDialog(d,"$escape")}else C.closeAll(b);return C},closeAll:function(a){for(var b=document.querySelectorAll(".ngdialog"),d=b.length-1;d>=0;d--){var e=b[d];B.closeDialog(c(e),a)}},getOpenDialogs:function(){return l},getDefaults:function(){return b}};return a.forEach(["html","body"],function(a){if(A[a]=q.find(a),j[a]){var b=B.getRouterLocationEventName();v.$on(b,function(){A[a]=q.find(a)})}}),C}]}),b.directive("ngDialog",["ngDialog",function(b){return{restrict:"A",scope:{ngDialogScope:"="},link:function(c,d,e){d.on("click",function(d){d.preventDefault();var f=a.isDefined(c.ngDialogScope)?c.ngDialogScope:"noScope";a.isDefined(e.ngDialogClosePrevious)&&b.close(e.ngDialogClosePrevious);var g=b.getDefaults();b.open({template:e.ngDialog,className:e.ngDialogClass||g.className,appendClassName:e.ngDialogAppendClass,controller:e.ngDialogController,controllerAs:e.ngDialogControllerAs,bindToController:e.ngDialogBindToController,disableAnimation:e.ngDialogDisableAnimation,scope:f,data:e.ngDialogData,showClose:"false"!==e.ngDialogShowClose&&("true"===e.ngDialogShowClose||g.showClose),closeByDocument:"false"!==e.ngDialogCloseByDocument&&("true"===e.ngDialogCloseByDocument||g.closeByDocument),closeByEscape:"false"!==e.ngDialogCloseByEscape&&("true"===e.ngDialogCloseByEscape||g.closeByEscape),overlay:"false"!==e.ngDialogOverlay&&("true"===e.ngDialogOverlay||g.overlay),preCloseCallback:e.ngDialogPreCloseCallback||g.preCloseCallback,bodyClassName:e.ngDialogBodyClass||g.bodyClassName})})}}}]),b}); \ No newline at end of file diff --git a/public/scripts/services/bookmark-service.js b/public/scripts/services/bookmark-service.js index 3e9e4bc..ea9865a 100644 --- a/public/scripts/services/bookmark-service.js +++ b/public/scripts/services/bookmark-service.js @@ -221,16 +221,42 @@ app.factory('bookmarkService', ['$http', '$q', function($http, $q) { }); return def.promise; }, - updateTag: function(params) { + updateTagName: function(params) { var def = $q.defer(); - $http.post('/api/updateTag/', { + $http.post('/api/updateTagName/', { params: params }) .success(function(data) { def.resolve(data); }) .error(function(data) { - def.reject('updateTag error'); + def.reject('updateTagName error'); + }); + return def.promise; + }, + updateTagsIndex: function(params) { + var def = $q.defer(); + $http.post('/api/updateTagsIndex/', { + params: params + }) + .success(function(data) { + def.resolve(data); + }) + .error(function(data) { + def.reject('updateTagsIndex error'); + }); + return def.promise; + }, + delTag: function(params) { + var def = $q.defer(); + $http.post('/api/delTag/', { + params: params + }) + .success(function(data) { + def.resolve(data); + }) + .error(function(data) { + def.reject('delTag error'); }); return def.promise; }, diff --git a/public/views/dialog-del-tag.html b/public/views/dialog-del-tag.html new file mode 100644 index 0000000..e5b6e7c --- /dev/null +++ b/public/views/dialog-del-tag.html @@ -0,0 +1,13 @@ +
+

删除提示

+

您确认要删除分类: + {{ waitDelTag.name }}吗? +

+

如果删除该分类,那么该分类下的所有书签都会删掉哦!

+

+ 未分类为系统默认分类,只允许删除该分类下面的书签,不允许删除该分类信息

+
+
+ + +
diff --git a/public/views/tags.html b/public/views/tags.html index 4cf3dbd..502eb97 100644 --- a/public/views/tags.html +++ b/public/views/tags.html @@ -9,10 +9,10 @@ -
+

操作说明:拖拽分类即可进行排序(正在开发中...)

-
-
+
+
{{ tag.name }}
@@ -21,9 +21,9 @@
-
+
-

书签:{{ tag.cnt }}个

+

书签:{{ tag.cnt || 0 }}个

{{ tag.last_use }}

diff --git a/routes/api.js b/routes/api.js index 747bafd..e560f0a 100644 --- a/routes/api.js +++ b/routes/api.js @@ -233,6 +233,7 @@ api.get('/bookmarks', function(req, res) { var tag = { id: result && result[0] && result[0].tag_id, name: result && result[0] && result[0].tag_name, + sort: result && result[0] && result[0].sort, click: 0, bookmarks: [] }; @@ -241,11 +242,13 @@ api.get('/bookmarks', function(req, res) { data.push({ id: tag.id, name: tag.name, + sort: tag.sort, click: tag.click, bookmarks: tag.bookmarks }); tag.id = bookmark.tag_id; tag.name = bookmark.tag_name; + tag.sort = bookmark.sort; tag.click = 0; tag.bookmarks = []; } @@ -255,8 +258,18 @@ api.get('/bookmarks', function(req, res) { if (result && result.length > 0) { data.push(tag); } - data.sort((a, b) => b.click - a.click); - // console.log(JSON.stringify(data)); + data.sort((a, b) => { + if (a.sort == b.sort) return b.click - a.click; + return a.sort - b.sort; + }); + var temp = data.map(item => { + return { + name: item.name, + sort: item.sort, + click: item.click, + } + }) + console.log(JSON.stringify(temp)); res.json(data); }) .catch((err) => console.log('bookmarks navigate err', err)); @@ -614,8 +627,8 @@ api.post('/addTags', function(req, res) { .catch((err) => console.log('addTags err', err)); }); -api.post('/updateTag', function(req, res) { - console.log('hello updateTag', JSON.stringify(req.query), JSON.stringify(req.body)); +api.post('/updateTagName', function(req, res) { + console.log('hello updateTagName', JSON.stringify(req.query), JSON.stringify(req.body)); if (!req.session.user) { res.send(401); return; @@ -630,7 +643,7 @@ api.post('/updateTag', function(req, res) { return Promise.resolve(-1); } } - return db.updateTag(tag); + return db.updateTagName(tag); }) .then((affectedRows) => { var msg = ""; @@ -657,6 +670,71 @@ api.post('/updateTag', function(req, res) { }); }); +api.post('/updateTagsIndex', function(req, res) { + console.log('hello updateTagsIndex', JSON.stringify(req.query), JSON.stringify(req.body)); + if (!req.session.user) { + res.send(401); + return; + } + var tagsIndex = req.body.params; + + db.updateTagsIndex(tagsIndex) + .then((affectedRows) => { + var msg = ""; + if (affectedRows == tagsIndex.length) { + msg = " 排序更新成功"; + } else { + msg += " 排序更新失败"; + } + res.json({ + retCode: (affectedRows == tagsIndex.length) ? 0 : 1, + msg: msg, + }) + }) + .catch((err) => { + console.log('updateTagsIndex err', err); + res.json({ + retCode: 1, + msg: "排序更新失败: " + JSON.stringify(err), + }) + }); +}); + +api.post('/delTag', function(req, res) { + console.log('hello delTag', JSON.stringify(req.query), JSON.stringify(req.body)); + if (!req.session.user) { + res.send(401); + return; + } + var tag = req.body.params; + var needDelTag = tag.del || false; + var bookmarksId = [] + db.getBookmarkIdsByTagId(tag.id) + .then((_bookmarksId) => { + bookmarksId = _bookmarksId.map((item) => item.bookmark_id); + return db.delTagBookmarks(tag.id); // 先删掉分类跟书签的映射 + }) + .then((affectedRows) => db.delBookmarks(bookmarksId)) // 再删掉该分类下面的书签 + .then((affectedRows) => { + if (needDelTag) { + return db.delTag(tag.id); + } + return Promise.resolve(1); + }) // 再删掉分类 + .then((affectedRows) => { + res.json({ + retCode: affectedRows == 1 ? 0 : 1, + }) + }) // 再删掉该分类下面的书签 + .catch((err) => { + console.log('delTag err', err); + res.json({ + retCode: 1, + msg: "删除分类失败: " + JSON.stringify(err), + }) + }); +}); + api.post('/getArticle', function(req, res) { var params = req.body.params; var url = params.url;