From 705fce73f7baf1f41554f8fdc701fb33da085716 Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Sun, 21 Aug 2022 21:10:56 +0700 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20=D0=BD?= =?UTF-8?q?=D0=B0=D0=B4=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=BE=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/components/Api/Api.vue | 10 ++++ client/components/Search/Search.vue | 73 ++++++++++++++++------- client/components/share/DivBtn.vue | 54 +++++++++++++++++ client/quasar.js | 4 +- server/controllers/WebSocketController.js | 13 +++- server/core/DbSearcher.js | 38 +++++++++++- server/core/WebWorker.js | 8 ++- 7 files changed, 172 insertions(+), 28 deletions(-) create mode 100644 client/components/share/DivBtn.vue diff --git a/client/components/Api/Api.vue b/client/components/Api/Api.vue index bdb90c0..8244677 100644 --- a/client/components/Api/Api.vue +++ b/client/components/Api/Api.vue @@ -54,6 +54,16 @@ class Api { return response; } + async getBookList(authorId) { + const response = await this.request({action: 'get-book-list', authorId}); + + if (response.error) { + throw new Error(response.error); + } + + return response; + } + async getConfig() { const response = await this.request({action: 'get-config'}); diff --git a/client/components/Search/Search.vue b/client/components/Search/Search.vue index 2c34b9e..e19de60 100644 --- a/client/components/Search/Search.vue +++ b/client/components/Search/Search.vue @@ -83,23 +83,30 @@
-
-
-
- -
-
- -
+
+
+ + + Только этот автор + +
-
- {{ item.name }} +
+
+ +
+
+ +
+
+ {{ item.name }} +
- {{ item.books[0] }} + {{ item.books }}
@@ -118,6 +125,8 @@ import vueComponent from '../vueComponent.js'; const { reactive } = require('@vue/reactivity'); import PageScroller from './PageScroller/PageScroller.vue'; +import DivBtn from '../share/DivBtn.vue'; + import * as utils from '../../share/utils'; import _ from 'lodash'; @@ -125,6 +134,7 @@ import _ from 'lodash'; const componentOptions = { components: { PageScroller, + DivBtn }, watch: { config() { @@ -301,7 +311,7 @@ class Search { this.page = 1; } - authorClick(author) { + selectAuthor(author) { this.author = `=${author}`; } @@ -309,11 +319,11 @@ class Search { return this.expanded.indexOf(item.author) >= 0; } - expandAuthor(item, expand = true) { + expandAuthor(item) { const expanded = _.cloneDeep(this.expanded); const author = item.author; - if (expand) { + if (!this.isExpanded(item)) { if (expanded.indexOf(author) < 0) { expanded.push(author); @@ -334,26 +344,39 @@ class Search { } } - async loadBooks() { + async loadBooks(authorId) { + let inSearch = true; + (async() => { + await utils.sleep(500); + if (inSearch) + this.loadingMessage = 'Загрузка списка книг...'; + })(); + + try { + const result = await this.api.getBookList(authorId); + + return result; + } catch (e) { + this.$root.stdDialog.alert(e.message, 'Ошибка'); + return; + } finally { + inSearch = false; + this.loadingMessage = ''; + } } async getBooks(item) { if (item.books) return; - - await utils.sleep(1000); - item.books = [{name: 'book1'}]; + + item.books = await this.loadBooks(item.key); } async updateTableData() { let result = []; - const authors = this.searchResult.author; - if (authors.length == 1) { - this.expandAuthor(authors[0]); - } - const expandedSet = new Set(this.expanded); + const authors = this.searchResult.author; let num = 0; for (const rec of authors) { @@ -373,6 +396,10 @@ class Search { result.push(item); } + if (result.length == 1 && !this.isExpanded(result[0])) { + this.expandAuthor(result[0]); + } + this.tableData = result; } diff --git a/client/components/share/DivBtn.vue b/client/components/share/DivBtn.vue new file mode 100644 index 0000000..54c7f57 --- /dev/null +++ b/client/components/share/DivBtn.vue @@ -0,0 +1,54 @@ + + + + + \ No newline at end of file diff --git a/client/quasar.js b/client/quasar.js index 3a3a20b..670858d 100644 --- a/client/quasar.js +++ b/client/quasar.js @@ -21,7 +21,7 @@ import {QIcon} from 'quasar/src/components/icon'; //import {QSeparator} from 'quasar/src/components/separator'; //import {QList} from 'quasar/src/components/item'; //import {QItem, QItemSection, QItemLabel} from 'quasar/src/components/item'; -//import {QTooltip} from 'quasar/src/components/tooltip'; +import {QTooltip} from 'quasar/src/components/tooltip'; import {QSpinner} from 'quasar/src/components/spinner'; //import {QTable, QTh, QTr, QTd} from 'quasar/src/components/table'; //import {QCheckbox} from 'quasar/src/components/checkbox'; @@ -52,7 +52,7 @@ const components = { //QSeparator, //QList, //QItem, QItemSection, QItemLabel, - //QTooltip, + QTooltip, QSpinner, //QTable, QTh, QTr, QTd, //QCheckbox, diff --git a/server/controllers/WebSocketController.js b/server/controllers/WebSocketController.js index 3078920..af5d496 100644 --- a/server/controllers/WebSocketController.js +++ b/server/controllers/WebSocketController.js @@ -4,7 +4,7 @@ const _ = require('lodash'); const WorkerState = require('../core/WorkerState');//singleton const WebWorker = require('../core/WebWorker');//singleton const log = new (require('../core/AppLogger'))().log;//singleton -//const utils = require('../core/utils'); +const utils = require('../core/utils'); const cleanPeriod = 1*60*1000;//1 минута const closeSocketOnIdle = 5*60*1000;//5 минут @@ -68,6 +68,8 @@ class WebSocketController { await this.getWorkerState(req, ws); break; case 'search': await this.search(req, ws); break; + case 'get-book-list': + await this.getBookList(req, ws); break; default: throw new Error(`Action not found: ${req.action}`); @@ -122,6 +124,15 @@ class WebSocketController { this.send(result, req, ws); } + + async getBookList(req, ws) { + if (!utils.hasProp(req, 'authorId')) + throw new Error(`authorId is empty`); + + const result = await this.webWorker.getBookList(req.authorId); + + this.send(result, req, ws); + } } module.exports = WebSocketController; diff --git a/server/core/DbSearcher.js b/server/core/DbSearcher.js index d555a2b..713001d 100644 --- a/server/core/DbSearcher.js +++ b/server/core/DbSearcher.js @@ -193,7 +193,7 @@ class DbSearcher { //сначала попробуем найти в кеше const q = query; const keyArr = [q.author, q.series, q.title, q.genre, q.lang]; - const keyStr = keyArr.join(''); + const keyStr = `query-${keyArr.join('')}`; if (!keyStr) {//пустой запрос if (db.searchCache.authorIdsAll) @@ -262,6 +262,42 @@ class DbSearcher { } } + async getBookList(authorId) { + if (this.closed) + throw new Error('DbSearcher closed'); + + this.searchFlag++; + + try { + const db = this.db; + + //выборка автора по authorId + const rows = await db.select({ + table: 'author', + map: `(r) => ({author: r.author, bookId: r.bookId})`, + where: `@@id(${db.esc(authorId)})` + }); + + let author = ''; + let result = []; + + if (rows.length) { + author = rows[0].author; + + //выборка книг по bookId + result = await db.select({ + table: 'book', + //map: `(r) => ({})`, + where: `@@id(${db.esc(rows[0].bookId)})`, + }); + } + + return {author, books: result}; + } finally { + this.searchFlag--; + } + } + async periodicCleanCache() { this.timer = null; const cleanInterval = 5*1000;//this.config.cacheCleanInterval*60*1000; diff --git a/server/core/WebWorker.js b/server/core/WebWorker.js index 1cfd38c..714fb89 100644 --- a/server/core/WebWorker.js +++ b/server/core/WebWorker.js @@ -195,7 +195,13 @@ class WebWorker { totalFound: result.totalFound, inpxHash: (config.inpxHash ? config.inpxHash : ''), }; - } + } + + async getBookList(authorId) { + this.checkMyState(); + + return await this.dbSearcher.getBookList(authorId); + } async logServerStats() { while (1) {// eslint-disable-line