diff --git a/client/components/Search/AuthorList/AuthorList.vue b/client/components/Search/AuthorList/AuthorList.vue index 739cf50..c26f469 100644 --- a/client/components/Search/AuthorList/AuthorList.vue +++ b/client/components/Search/AuthorList/AuthorList.vue @@ -75,16 +75,16 @@
-
+
- + Показать еще (~{{ showMoreCount }}) - + Показать все ({{ (book.allBooksLoaded && book.allBooksLoaded.length) || '?' }})
@@ -162,6 +162,18 @@ class AuthorList extends BaseList { return `+${this.hiddenCount} результат${utils.wordEnding(this.hiddenCount)} скрыт${utils.wordEnding(this.hiddenCount, 2)}`; } + get foundCountMessage() { + return `Найден${utils.wordEnding(this.list.totalFound, 2)} ${this.list.totalFound} автор${utils.wordEnding(this.list.totalFound)}`; + } + + isFoundSeriesBook(seriesItem, seriesBook) { + if (!seriesItem.booksSet) { + seriesItem.booksSet = new Set(seriesItem.seriesBooks.map(b => b.id)); + } + + return seriesItem.booksSet.has(seriesBook.id); + } + getBookCount(item) { let result = ''; if (!this.showCounts || item.count === undefined) @@ -183,14 +195,6 @@ class AuthorList extends BaseList { return `(${result})`; } - isFoundSeriesBook(seriesItem, seriesBook) { - if (!seriesItem.booksSet) { - seriesItem.booksSet = new Set(seriesItem.seriesBooks.map(b => b.id)); - } - - return seriesItem.booksSet.has(seriesBook.id); - } - async expandAuthor(item) { const expanded = _.cloneDeep(this.expandedAuthor); const key = item.author; @@ -263,13 +267,13 @@ class AuthorList extends BaseList { if (index === undefined) { index = books.length; books.push(reactive({ - key: `${item.author}-${book.series}`, + key: book.series, type: 'series', series: book.series, - allBooksLoaded: null, - allBooks: null, + allBooksLoaded: false, + allBooks: false, showAllBooks: false, - showMore: false, + showMoreAll: false, seriesBooks: [], })); diff --git a/client/components/Search/BaseList.js b/client/components/Search/BaseList.js index 2f1537e..ced73a1 100644 --- a/client/components/Search/BaseList.js +++ b/client/components/Search/BaseList.js @@ -296,20 +296,21 @@ export default class BaseList { } async getSeriesBooks(seriesItem) { - //асинхронно подгружаем все книги серии, блокируем повторный вызов - if (seriesItem.allBooksLoaded === null) { - seriesItem.allBooksLoaded = undefined; - (async() => { - seriesItem.allBooksLoaded = await this.loadSeriesBooks(seriesItem.series); + //блокируем повторный вызов + if (seriesItem.seriesBookLoading) + return; + seriesItem.seriesBookLoading = true; - if (seriesItem.allBooksLoaded) { - seriesItem.allBooksLoaded = seriesItem.allBooksLoaded.filter(book => (this.showDeleted || !book.del)); - this.sortSeriesBooks(seriesItem.allBooksLoaded); - this.showMoreSeries(seriesItem); - } else { - seriesItem.allBooksLoaded = null; - } - })(); + try { + seriesItem.allBooksLoaded = await this.loadSeriesBooks(seriesItem.series); + + if (seriesItem.allBooksLoaded) { + seriesItem.allBooksLoaded = seriesItem.allBooksLoaded.filter(book => (this.showDeleted || !book.del)); + this.sortSeriesBooks(seriesItem.allBooksLoaded); + this.showMoreAll(seriesItem); + } + } finally { + seriesItem.seriesBookLoading = false; } } @@ -423,7 +424,7 @@ export default class BaseList { } } - showMoreSeries(seriesItem, all = false) { + showMoreAll(seriesItem, all = false) { if (seriesItem.allBooksLoaded) { const currentLen = (seriesItem.allBooks ? seriesItem.allBooks.length : 0); let books; @@ -433,7 +434,7 @@ export default class BaseList { books = seriesItem.allBooksLoaded.slice(0, currentLen + this.showMoreCount); } - seriesItem.showMore = (books.length < seriesItem.allBooksLoaded.length); + seriesItem.showMoreAll = (books.length < seriesItem.allBooksLoaded.length); seriesItem.allBooks = books; } } @@ -446,5 +447,4 @@ export default class BaseList { return (dserno ? dserno : (dtitle ? dtitle : dext)); }); } - } \ No newline at end of file diff --git a/client/components/Search/Search.vue b/client/components/Search/Search.vue index 8683597..b5ac537 100644 --- a/client/components/Search/Search.vue +++ b/client/components/Search/Search.vue @@ -101,7 +101,7 @@
- {{ foundAuthorsMessage }} + {{ foundCountMessage }}
Ничего не найдено @@ -115,7 +115,7 @@
- +
@@ -251,8 +251,10 @@ const componentOptions = { handler(newValue) { this.updateGenreTreeIfNeeded(); - if (this.prevList.totalFound != newValue.totalFound) + if (this.prevList.totalFound != newValue.totalFound) { this.updatePageCount(); + this.foundCountMessage = this.$refs.list.foundCountMessage; + } this.prevList = _.cloneDeep(newValue); }, @@ -278,6 +280,8 @@ class Search { collection = ''; projectName = ''; + foundCountMessage = ''; + settingsDialogVisible = false; selectGenreDialogVisible = false; selectLangDialogVisible = false; @@ -667,10 +671,6 @@ class Search { this.lastScrollTop = 0; } - get foundAuthorsMessage() { - return `Найден${utils.wordEnding(this.list.totalFound, 2)} ${this.list.totalFound} автор${utils.wordEnding(this.list.totalFound)}`; - } - updatePageCount() { const prevPageCount = this.pageCount; diff --git a/client/components/Search/SeriesList/SeriesList.vue b/client/components/Search/SeriesList/SeriesList.vue index 4b556b9..8b90b78 100644 --- a/client/components/Search/SeriesList/SeriesList.vue +++ b/client/components/Search/SeriesList/SeriesList.vue @@ -8,9 +8,9 @@
-
+
-
+
@@ -19,8 +19,8 @@
-
- {{ item.name }} +
+ Серия: {{ item.series }}
@@ -35,82 +35,57 @@
-
-
- -
-
-
-
-
- -
-
- -
-
-
- -
- Серия: {{ book.series }} -
-
- -
-
- -
-
- -
- -
-
- - - Показать еще (~{{ showMoreCount }}) - - - Показать все ({{ (book.allBooksLoaded && book.allBooksLoaded.length) || '?' }}) - -
- -
- - Только найденные книги -
-
- - Все книги серии -
-
-
-
- - +
+
+ +
+
+
-
- - По каждому из заданных критериев у этой серии были найдены разные книги, но нет полного совпадения +
+
+ + + Показать еще (~{{ showMoreCount }}) + + + Показать все ({{ (item.allBooksLoaded && item.allBooksLoaded.length) || '?' }}) + +
+ +
+ + Только найденные книги +
+
+ + Все книги серии +
-
+
+ + По каждому из заданных критериев у этой серии были найдены разные книги, но нет полного совпадения +
+ +
Показать еще (~{{ showMoreCount }}) @@ -141,6 +116,67 @@ import * as utils from '../../../share/utils'; import _ from 'lodash'; class SeriesList extends BaseList { + get foundCountMessage() { + return `Найден${utils.wordEnding(this.list.totalFound, 4)} ${this.list.totalFound} сери${utils.wordEnding(this.list.totalFound, 1)}`; + } + + isFoundSeriesBook(seriesItem, seriesBook) { + if (!seriesItem.booksSet) { + seriesItem.booksSet = new Set(seriesItem.books.map(b => b.id)); + } + + return seriesItem.booksSet.has(seriesBook.id); + } + + getBookCount(item) { + let result = ''; + if (!this.showCounts || item.count === undefined) + return result; + + if (item.books) { + result = `${item.books.length}/${item.count}`; + } else + result = `#/${item.count}`; + + return `(${result})`; + } + + async getSeriesBooks(seriesItem) { + if (seriesItem.count > this.maxItemCount) { + seriesItem.bookLoading = true; + await this.$nextTick(); + } + + try { + await super.getSeriesBooks(seriesItem); + + if (seriesItem.allBooksLoaded) { + const prepareBook = (book) => { + return Object.assign( + { + key: book.id, + type: 'book', + }, + book + ); + }; + + const filtered = this.filterBooks(seriesItem.allBooksLoaded); + + //объединение по сериям + const books = []; + for (const book of filtered) { + books.push(prepareBook(book)); + } + + seriesItem.booksLoaded = books; + this.showMore(seriesItem); + } + } finally { + seriesItem.bookLoading = false; + } + } + async updateTableData() { let result = []; @@ -148,47 +184,44 @@ class SeriesList extends BaseList { const series = this.searchResult.series; if (!series) return; -/* - let num = 0; - this.hiddenCount = 0; - for (const rec of authors) { - this.cachedAuthors[rec.author] = rec; + let num = 0; + for (const rec of series) { const count = (this.showDeleted ? rec.bookCount + rec.bookDelCount : rec.bookCount); - if (!count) { - this.hiddenCount++; - continue; - } const item = reactive({ - key: rec.id, + key: rec.series, + series: rec.series, num, - author: rec.author, - name: rec.author.replace(/,/g, ', '), count, + bookLoading: false, + + allBooksLoaded: false, + allBooks: false, + showAllBooks: false, + showMoreAll: false, + booksLoaded: false, books: false, - bookLoading: false, showMore: false, }); num++; - if (expandedSet.has(item.author)) { - if (authors.length > 1 || item.count > this.maxItemCount) - this.getBooks(item);//no await + if (expandedSet.has(item.series)) { + if (series.length > 1 || item.count > this.maxItemCount) + this.getSeriesBooks(item);//no await else - await this.getBooks(item); + await this.getSeriesBooks(item); } result.push(item); } - if (result.length == 1 && !this.isExpandedAuthor(result[0])) { - this.expandAuthor(result[0]); + if (result.length == 1 && !this.isExpandedSeries(result[0])) { + this.expandSeries(result[0]); } this.tableData = result; -*/ } async refresh() { diff --git a/client/share/utils.js b/client/share/utils.js index 807ec8c..0b497d9 100644 --- a/client/share/utils.js +++ b/client/share/utils.js @@ -38,7 +38,8 @@ export function wordEnding(num, type = 0) { ['ов', '', 'а', 'а', 'а', 'ов', 'ов', 'ов', 'ов', 'ов'], ['й', 'я', 'и', 'и', 'и', 'й', 'й', 'й', 'й', 'й'], ['о', '', 'о', 'о', 'о', 'о', 'о', 'о', 'о', 'о'], - ['ий', 'ие', 'ия', 'ия', 'ия', 'ий', 'ий', 'ий', 'ий', 'ий'] + ['ий', 'ие', 'ия', 'ия', 'ия', 'ий', 'ий', 'ий', 'ий', 'ий'], + ['о', 'а', 'о', 'о', 'о', 'о', 'о', 'о', 'о', 'о'], ]; const deci = num % 100; if (deci > 10 && deci < 20) { diff --git a/server/controllers/WebSocketController.js b/server/controllers/WebSocketController.js index 2c3ba0e..7ff4f9f 100644 --- a/server/controllers/WebSocketController.js +++ b/server/controllers/WebSocketController.js @@ -163,7 +163,7 @@ class WebSocketController { } async getSeriesBookList(req, ws) { - const result = await this.webWorker.getSeriesBookList(req.series, req.seriesId); + const result = await this.webWorker.getSeriesBookList(req.series); this.send(result, req, ws); } diff --git a/server/core/DbSearcher.js b/server/core/DbSearcher.js index 161cf34..a146ba2 100644 --- a/server/core/DbSearcher.js +++ b/server/core/DbSearcher.js @@ -483,11 +483,11 @@ class DbSearcher { } } - async getSeriesBookList(series, seriesId) { + async getSeriesBookList(series) { if (this.closed) throw new Error('DbSearcher closed'); - if (!series && !seriesId) + if (!series) return {books: ''}; this.searchFlag++; @@ -500,15 +500,16 @@ class DbSearcher { //выборка серии по названию серии let rows = await db.select({ table: 'series', - where: `@@dirtyIndexLR('value', ${db.esc(series)}, ${db.esc(series)})` + rawResult: true, + where: `return Array.from(@dirtyIndexLR('value', ${db.esc(series)}, ${db.esc(series)}))` }); let books; - if (rows.length) { + if (rows.length && rows[0].rawResult.length) { //выборка книг серии rows = await db.select({ table: 'series_book', - where: `@@id(${rows[0].id})` + where: `@@id(${rows[0].rawResult[0]})` }); if (rows.length) diff --git a/server/core/WebWorker.js b/server/core/WebWorker.js index 20bf116..bb44c57 100644 --- a/server/core/WebWorker.js +++ b/server/core/WebWorker.js @@ -277,10 +277,10 @@ class WebWorker { return await this.dbSearcher.getAuthorBookList(authorId); } - async getSeriesBookList(series, seriesId) { + async getSeriesBookList(series) { this.checkMyState(); - return await this.dbSearcher.getSeriesBookList(series, seriesId); + return await this.dbSearcher.getSeriesBookList(series); } async getGenreTree() {