diff --git a/client/components/Api/Api.vue b/client/components/Api/Api.vue
index e3e597a..7b34ed3 100644
--- a/client/components/Api/Api.vue
+++ b/client/components/Api/Api.vue
@@ -239,6 +239,10 @@ class Api {
return await this.request({action: 'get-author-book-list', authorId});
}
+ async getAuthorSeriesList(authorId) {
+ return await this.request({action: 'get-author-series-list', authorId});
+ }
+
async getSeriesBookList(series) {
return await this.request({action: 'get-series-book-list', series});
}
diff --git a/client/components/Search/AuthorList/AuthorList.vue b/client/components/Search/AuthorList/AuthorList.vue
index bc7718f..2f5892a 100644
--- a/client/components/Search/AuthorList/AuthorList.vue
+++ b/client/components/Search/AuthorList/AuthorList.vue
@@ -56,7 +56,7 @@
- {{ getSeriesBookCount(book) }}
+ {{ getSeriesBookCount(item, book) }}
@@ -188,15 +188,17 @@ class AuthorList extends BaseList {
return `(${result})`;
}
- getSeriesBookCount(book) {
+ getSeriesBookCount(item, book) {
let result = '';
if (!this.showCounts || book.type != 'series')
return result;
let count = book.seriesBooks.length;
result = `${count}`;
- if (book.allBooksLoaded) {
- result += `/${book.allBooksLoaded.length}`;
+ if (item.seriesLoaded) {
+ const rec = item.seriesLoaded[book.series];
+ const totalCount = (this.showDeleted ? rec.bookCount + rec.bookDelCount : rec.bookCount);
+ result += `/${totalCount}`;
}
return `(${result})`;
@@ -227,6 +229,19 @@ class AuthorList extends BaseList {
}
}
+ async getAuthorSeries(item) {
+ if (item.seriesLoaded)
+ return;
+
+ const series = await this.loadAuthorSeries(item.key);
+ const loaded = {};
+ for (const s of series) {
+ loaded[s.series] = {bookCount: s.bookCount, bookDelCount: s.bookDelCount};
+ }
+
+ item.seriesLoaded = loaded;
+ }
+
async getAuthorBooks(item) {
if (item.books) {
if (item.count > this.maxItemCount) {
@@ -328,6 +343,7 @@ class AuthorList extends BaseList {
}
item.booksLoaded = books;
+ this.getAuthorSeries(item);//no await
this.showMore(item);
await this.$nextTick();
@@ -360,6 +376,7 @@ class AuthorList extends BaseList {
name: rec.author.replace(/,/g, ', '),
count,
booksLoaded: false,
+ seriesLoaded: false,
books: false,
bookLoading: false,
showMore: false,
diff --git a/client/components/Search/BaseList.js b/client/components/Search/BaseList.js
index 180d556..0082d58 100644
--- a/client/components/Search/BaseList.js
+++ b/client/components/Search/BaseList.js
@@ -259,6 +259,29 @@ export default class BaseList {
}
}
+ async loadAuthorSeries(authorId) {
+ try {
+ let result;
+
+ if (this.abCacheEnabled) {
+ const key = `author-${authorId}-series-${this.list.inpxHash}`;
+ const data = await authorBooksStorage.getData(key);
+ if (data) {
+ result = JSON.parse(data);
+ } else {
+ result = await this.api.getAuthorSeriesList(authorId);
+ await authorBooksStorage.setData(key, JSON.stringify(result));
+ }
+ } else {
+ result = await this.api.getAuthorSeriesList(authorId);
+ }
+
+ return result.series;
+ } catch (e) {
+ this.$root.stdDialog.alert(e.message, 'Ошибка');
+ }
+ }
+
async loadSeriesBooks(series) {
try {
let result;
diff --git a/server/controllers/WebSocketController.js b/server/controllers/WebSocketController.js
index eea3c01..73344b4 100644
--- a/server/controllers/WebSocketController.js
+++ b/server/controllers/WebSocketController.js
@@ -89,6 +89,8 @@ class WebSocketController {
await this.search(req, ws); break;
case 'get-author-book-list':
await this.getAuthorBookList(req, ws); break;
+ case 'get-author-series-list':
+ await this.getAuthorSeriesList(req, ws); break;
case 'get-series-book-list':
await this.getSeriesBookList(req, ws); break;
case 'get-genre-tree':
@@ -169,6 +171,12 @@ class WebSocketController {
this.send(result, req, ws);
}
+ async getAuthorSeriesList(req, ws) {
+ const result = await this.webWorker.getAuthorSeriesList(req.authorId);
+
+ this.send(result, req, ws);
+ }
+
async getSeriesBookList(req, ws) {
const result = await this.webWorker.getSeriesBookList(req.series);
diff --git a/server/core/DbSearcher.js b/server/core/DbSearcher.js
index 8ee01ce..fe3012f 100644
--- a/server/core/DbSearcher.js
+++ b/server/core/DbSearcher.js
@@ -599,7 +599,7 @@ class DbSearcher {
throw new Error('DbSearcher closed');
if (!authorId && !author)
- return {author: '', books: ''};
+ return {author: '', books: []};
this.searchFlag++;
@@ -638,12 +638,58 @@ class DbSearcher {
}
}
+ async getAuthorSeriesList(authorId) {
+ if (this.closed)
+ throw new Error('DbSearcher closed');
+
+ if (!authorId)
+ return {author: '', series: []};
+
+ this.searchFlag++;
+
+ try {
+ const db = this.db;
+
+ //выборка книг автора по authorId
+ const bookList = await this.getAuthorBookList(authorId);
+ const books = bookList.books;
+ const seriesSet = new Set();
+ for (const book of books) {
+ if (book.series)
+ seriesSet.add(book.series.toLowerCase());
+ }
+
+ let series = [];
+ if (seriesSet.size) {
+ //выборка серий по названиям
+ series = await db.select({
+ table: 'series',
+ map: `(r) => ({id: r.id, series: r.name, bookCount: r.bookCount, bookDelCount: r.bookDelCount})`,
+ where: `
+ const seriesArr = ${db.esc(Array.from(seriesSet))};
+ const ids = new Set();
+ for (const value of seriesArr) {
+ for (const id of @dirtyIndexLR('value', value, value))
+ ids.add(id);
+ }
+
+ return ids;
+ `
+ });
+ }
+
+ return {author: bookList.author, series};
+ } finally {
+ this.searchFlag--;
+ }
+ }
+
async getSeriesBookList(series) {
if (this.closed)
throw new Error('DbSearcher closed');
if (!series)
- return {books: ''};
+ return {books: []};
this.searchFlag++;
diff --git a/server/core/WebWorker.js b/server/core/WebWorker.js
index 7a1e6c9..50a89e4 100644
--- a/server/core/WebWorker.js
+++ b/server/core/WebWorker.js
@@ -279,6 +279,12 @@ class WebWorker {
return await this.dbSearcher.getAuthorBookList(authorId, author);
}
+ async getAuthorSeriesList(authorId) {
+ this.checkMyState();
+
+ return await this.dbSearcher.getAuthorSeriesList(authorId);
+ }
+
async getSeriesBookList(series) {
this.checkMyState();