-
-
-
-
-
-
+
+
+
+
+ Только этот автор
+
+
-
- {{ 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