diff --git a/docs/api.yml b/docs/api.yml deleted file mode 100644 index e69de29..0000000 diff --git a/docs/swagger.yml b/docs/swagger.yml index 1b544ce..faa5a7f 100644 --- a/docs/swagger.yml +++ b/docs/swagger.yml @@ -1,35 +1,22 @@ openapi: "3.0.0" +servers: +- url: http://192.168.31.161:3000/v1 + description: 测试服务器 info: title: 书签同步助手后端接口 - version: 0.0.1 + version: 1.0.0 tags: - - name: User - description: 用户管理 + - name: Version + description: 接口版本号 - name: Bookmark description: 书签管理 paths: - /user/login: - post: - operationId: userLogin - summary: 用户登录 + /version: + get: + operationId: getVersion + summary: 获得接口版本号 tags: - - User - requestBody: - description: 登录信息。 - required: true - content: - application/json: - schema: - type: object - properties: - account: - description: 账号 - type: string - example: 'admin' - password: - description: 密码 - type: string - example: 'secret' + - Version responses: '200': description: 200 response @@ -43,36 +30,15 @@ paths: message: type: string description: 响应信息,响应码为非20000时表示错误信息 - examples: - 20000: - value: { - "code": 20000, - "message": "OK" - } - /user/logout: - post: - operationId: userLogout - summary: 登录注销 - tags: - - User - responses: - '200': - description: 200 response - content: - application/json: - schema: - type: object - properties: - code: - $ref: '#/components/schemas/ResponseCode' - message: + data: type: string - description: 响应信息,响应码为非20000时表示错误信息 + description: 版本号信息 examples: 20000: value: { "code": 20000, - "message": "OK" + "message": "OK", + "data": "1.0.0" } /bookmark: get: @@ -110,7 +76,7 @@ paths: tags: - Bookmark requestBody: - description: 需要添加的职工信息,注意 employeeId 字段是无效的。 + description: 书签列表 required: true content: application/json: @@ -137,19 +103,16 @@ paths: "code": 20000, "message": "OK" } + components: schemas: ResponseCode: type: integer enum: - 20000 - - 40000 - - 40100 description: > 响应码: * `20000` - 表明调用成功 - * `40000` - 用户名或密码错误 - * `40001` - token已过期 Bookmark: type: object properties: @@ -159,12 +122,6 @@ components: parentId: description: 父节点的ID,根节点没有此属性 type: string - dateAdded: - description: 书签节点创建时的时间戳 - type: integer - dateGroupModified: - description: 书签文件夹内容的最后更新时间戳,书签节点没有此属性 - type: integer index: description: 书签在父节点中的索引,根节点没有此属性 type: integer diff --git a/extension/popup.js b/extension/js/popup.js similarity index 58% rename from extension/popup.js rename to extension/js/popup.js index 970ed87..ae56979 100644 --- a/extension/popup.js +++ b/extension/js/popup.js @@ -1,11 +1,12 @@ let api = {}; +let serverApi = {}; // chrome bookmark api wrapper -(function(api) { +(function (api) { /** * 获得整个书签树 */ const getTree = () => { - return new Promise(resolve => { + return new Promise((resolve) => { chrome.bookmarks.getTree(resolve); }); }; @@ -18,12 +19,12 @@ let api = {}; * 返回的书签数组中是不包含children字段的,即不包含子节点以下的节点 * @param {String} id 父书签组id */ - const getChildren = id => { - return new Promise(resolve => { + const getChildren = (id) => { + return new Promise((resolve) => { chrome.bookmarks.getChildren(id, resolve); }); }; - const getChildrenAsync = async id => { + const getChildrenAsync = async (id) => { return await getChildren(id); }; @@ -32,12 +33,12 @@ let api = {}; * 返回的书签数组中包含children字段,即包含子节点以下的节点 * @param {String} id 父书签组id */ - const getSubTree = id => { - return new Promise(resolve => { + const getSubTree = (id) => { + return new Promise((resolve) => { chrome.bookmarks.getSubTree(id, resolve); }); }; - const getSubTreeAsync = async id => { + const getSubTreeAsync = async (id) => { return await getSubTree(id); }; @@ -45,12 +46,12 @@ let api = {}; * 删除指定id的书签 * @param {String} id 需要删除的书签的id */ - const remove = id => { - return new Promise(resolve => { + const remove = (id) => { + return new Promise((resolve) => { chrome.bookmarks.remove(id, resolve); }); }; - const removeAsync = async id => { + const removeAsync = async (id) => { return await remove(id); }; @@ -58,12 +59,12 @@ let api = {}; * 删除指定id的空书签组,如果书签组下有子书签或子书签组,删除将失败 * @param {String} id 需要删除的书签文件夹id */ - const removeTree = id => { - return new Promise(resolve => { + const removeTree = (id) => { + return new Promise((resolve) => { chrome.bookmarks.removeTree(id, resolve); }); }; - const removeTreeAsync = async id => { + const removeTreeAsync = async (id) => { await removeTree(id); }; @@ -75,12 +76,12 @@ let api = {}; * string (optional) title * string (optional) url 如果为NULL或者不填,则代表一个书签组文件夹 */ - const create = bookmark => { - return new Promise(resolve => { + const create = (bookmark) => { + return new Promise((resolve) => { chrome.bookmarks.create(bookmark, resolve); }); }; - const createAsync = async bookmark => { + const createAsync = async (bookmark) => { return await create(bookmark); }; @@ -92,6 +93,65 @@ let api = {}; api.createAsync = createAsync; })(api); +// backend server api wrapper +(function (api) { + const API_VERSION = "v1"; + let serverAddress = ""; + + const setServerAddress = (address) => { + serverAddress = address; + }; + + const getServerAddress = () => { + return serverAddress; + }; + + const getVersion = () => { + return new Promise((resolve, reject) => { + $.getJSON(`${serverAddress}/${API_VERSION}/version`, (response) => { + const { code, message, data } = response; + if (code === 20000) { + resolve(data); + } else { + reject(new Error(message)); + } + }); + }); + }; + + const uploadBookmarks = data => { + return new Promise((resolve, reject) => { + $.post(`${serverAddress}/${API_VERSION}/bookmark`, data, (response) => { + const { code, message, data } = response; + if (code === 20000) { + resolve(data); + } else { + reject(new Error(message)); + } + }, 'json'); + }); + }; + + const downloadBookmarks = () => { + return new Promise((resolve, reject) => { + $.getJSON(`${serverAddress}/${API_VERSION}/bookmark`, (response) => { + const { code, message, data } = response; + if (code === 20000) { + resolve(data); + } else { + reject(new Error(message)); + } + }); + }); + }; + + api.setServerAddress = setServerAddress; + api.getServerAddress = getServerAddress; + api.getVersion = getVersion; + api.uploadBookmarks = uploadBookmarks; + api.downloadBookmarks = downloadBookmarks; +})(serverApi); + function Node() { /** * id ( string ) @@ -105,11 +165,11 @@ function Node() { /** * 书签节点创建时的时间戳 */ - this.dateAdded = 0; + this.dateAdded = undefined; /** * 书签文件夹内容的最后更新时间戳,书签节点没有此属性 */ - this.dateGroupModified = 0; + this.dateGroupModified = undefined; /** * 书签在父节点中的索引,根节点没有此属性 */ @@ -143,7 +203,7 @@ let BookmarkTreeNodeList = []; const BOOKMARK = 0; const BOOKEMARK_FOLDER = 1; const PROTO = "http"; -const SERVER_ADDRESS = "127.0.0.1"; +const SERVER_ADDRESS = "192.168.31.161"; const SERVER_PORT = "3000"; const SERVER_URL = `${PROTO}://${SERVER_ADDRESS}:${SERVER_PORT}`; @@ -162,8 +222,6 @@ async function getBookmarkMap() { let bookmarkNode = new Node(); bookmarkNode.id = node.id; bookmarkNode.parentId = node.parentId; - // bookmarkNode.dateAdded = node.dateAdded; - // bookmarkNode.dateGroupModified = node.dateGroupModified; bookmarkNode.index = node.index; bookmarkNode.title = node.title; bookmarkNode.url = node.url; @@ -200,76 +258,84 @@ async function getBookmarkMap() { return localMap; } -/** - * 获得浏览器书签的数组 - */ -async function getBookmarkList() { - let localTree = await api.getTreeAsync(); - let localList = []; - - async function addToList(localTree) { - for (let i = 0; i < localTree.length; i++) { - let node = localTree[i]; - - let bookmarkNode = new Node(); - bookmarkNode.id = node.id; - bookmarkNode.parentId = node.parentId; - // bookmarkNode.dateAdded = node.dateAdded; - // bookmarkNode.dateGroupModified = node.dateGroupModified; - bookmarkNode.index = node.index; - bookmarkNode.title = node.title; - bookmarkNode.url = node.url; - bookmarkNode.type = - typeof node.dateGroupModified === "undefined" - ? BOOKMARK - : BOOKEMARK_FOLDER; - bookmarkNode.root = typeof node.parentId === "undefined"; - // 根节点没有 dateGroupModified 属性,但是应该是个书签组类型 - if (bookmarkNode.root) { - bookmarkNode.type = BOOKEMARK_FOLDER; +function tree2List(tree) { + let cacheMap = {}; + function add2Map(tree) { + for (let item of tree) { + // 给书签文件创建group属性 + if (item.id === "0" || item.id === "1" || item.id === "2" || typeof item.dateGroupModified === 'number') { + item.group = true } + cacheMap[item.id] = item; + if (Array.isArray(item.children)) { + add2Map(item.children); + } + } + } + add2Map(tree); - localList.push(bookmarkNode); - - if (Array.isArray(node.children) && node.children.length > 0) { - await addToList(node.children) + for (let key in cacheMap) { + let item = cacheMap[key]; + if (typeof item.parentId === "string") { + if (!Array.isArray(cacheMap[item.parentId].nodes)) { + cacheMap[item.parentId].nodes = []; } + cacheMap[item.parentId].nodes.push(item.id); } } - await addToList(localTree); - return localList; + let list = []; + for (let key in cacheMap) { + const item = cacheMap[key]; + list.push({ + id: item.id, + parentId: item.parentId, + title: item.title, + url: item.url, + index: item.index, + group: item.group, + nodes: item.nodes, + }); + } + + return list; +} +/** + * 获得浏览器书签的数组 + */ +async function getBookmarkList() { + let localTree = await api.getTreeAsync(); + return tree2List(localTree); } /** * 数组转map表 - * @param {Object} bookmarkList + * @param {Object} bookmarkList */ function listToMap(bookmarkList) { - let map = {} - for(let i = 0; i < bookmarkList.length; i++) { - let bookmark = bookmarkList[i] - map[bookmark.id] = bookmark + let map = {}; + for (let i = 0; i < bookmarkList.length; i++) { + let bookmark = bookmarkList[i]; + map[bookmark.id] = bookmark; } - function getDepth(bookmark, depth) { - if (parseInt(bookmark.id) === 0) { - return depth - } else { - return getDepth(map[bookmark.parentId], depth + 1) - } + if (parseInt(bookmark.id) === 0) { + return depth; + } else { + return getDepth(map[bookmark.parentId], depth + 1); + } } - let finalMap = {} - for(let i = 0; i < bookmarkList.length; i++) { - let bookmark = bookmarkList[i] - let finalDepth = getDepth(bookmark, 0) - if (!Array.isArray(finalMap[finalDepth])) { - finalMap[finalDepth] = [] - } - finalMap[finalDepth].push(bookmark) + let finalMap = {}; + for (let i = 0; i < bookmarkList.length; i++) { + let bookmark = bookmarkList[i]; + let finalDepth = getDepth(bookmark, 0); + if (!Array.isArray(finalMap[finalDepth])) { + finalMap[finalDepth] = []; + } + finalMap[finalDepth].push(bookmark); } - return finalMap + return finalMap; } async function removeAllBookmarks() { @@ -304,7 +370,7 @@ async function restore(remoteBookmarkArray) { parentId: getNewbookmarkId(array[depth - 1], bookmark.parentId), index: bookmark.index, title: bookmark.title, - url: bookmark.url + url: bookmark.url, }); bookmark.newId = newBookmark.id; console.log( @@ -319,30 +385,25 @@ async function restore(remoteBookmarkArray) { $("#upload").on("click", async () => { let bookmarkArray = await getBookmarkList(); - $.ajax({ - type: "POST", - url: `${SERVER_URL}/bookmarks`, - contentType: "application/json;charset=utf-8", - dataType: "json", - data: JSON.stringify(bookmarkArray), - success: function() {}, - error: function() {} + console.log(bookmarkArray) + serverApi.uploadBookmarks({ + bookmarks: bookmarkArray }); }); -$("#download").on("click", function() { - $.ajax({ - type: "GET", - url: `${SERVER_URL}/bookmarks`, - success: function(result) { - if (result.code === 0) { - restore(result.data); - } - } - }); +$("#download").on("click", async () => { + const bookmarkArray = await serverApi.downloadBookmarks(); + console.log(bookmarkArray); }); $("#test").on("click", async () => { let array = await getBookmarkList(); console.log(array); }); + +$("#connect").on("click", async () => { + const serverAddress = $("#server").val() || SERVER_URL; + serverApi.setServerAddress(serverAddress); + const version = await serverApi.getVersion(); + $("#version").html(version); +}); diff --git a/extension/popup.html b/extension/popup.html index 5b63458..93714cf 100644 --- a/extension/popup.html +++ b/extension/popup.html @@ -7,9 +7,15 @@