diff --git a/client/components/Search/BaseList.js b/client/components/Search/BaseList.js index 9afc132..265d6e3 100644 --- a/client/components/Search/BaseList.js +++ b/client/components/Search/BaseList.js @@ -41,6 +41,7 @@ export default class BaseList { _props = { list: Object, search: Object, + extSearch: Object, genreMap: Object, }; @@ -68,6 +69,7 @@ export default class BaseList { tableData = []; created() { + this.isExtendedSearch = false; this.commit = this.$store.commit; this.api = this.$root.api; @@ -516,7 +518,8 @@ export default class BaseList { } getQuery() { - let newQuery = _.cloneDeep(this.search); + const search = (this.isExtendedSearch ? this.extSearch : this.search); + let newQuery = _.cloneDeep(search); newQuery = newQuery.setDefaults(newQuery); delete newQuery.setDefaults; diff --git a/client/components/Search/ExtendedList/ExtendedList.vue b/client/components/Search/ExtendedList/ExtendedList.vue new file mode 100644 index 0000000..d836118 --- /dev/null +++ b/client/components/Search/ExtendedList/ExtendedList.vue @@ -0,0 +1,128 @@ + + + + + diff --git a/client/components/Search/Search.vue b/client/components/Search/Search.vue index c1cacd9..31c6b5f 100644 --- a/client/components/Search/Search.vue +++ b/client/components/Search/Search.vue @@ -55,7 +55,7 @@ -
+
-
+
-
+
+{{ extendedParamsMessage }}
+ +
+ + + + + {{ extSearchNames }} + + + +
+ + + +
@@ -202,7 +232,7 @@
- +
@@ -224,6 +254,7 @@ +
@@ -234,6 +265,7 @@ import vueComponent from '../vueComponent.js'; import AuthorList from './AuthorList/AuthorList.vue'; import SeriesList from './SeriesList/SeriesList.vue'; import TitleList from './TitleList/TitleList.vue'; +import ExtendedList from './ExtendedList/ExtendedList.vue'; import PageScroller from './PageScroller/PageScroller.vue'; import SettingsDialog from './SettingsDialog/SettingsDialog.vue'; @@ -242,6 +274,7 @@ import SelectLangDialog from './SelectLangDialog/SelectLangDialog.vue'; import SelectLibRateDialog from './SelectLibRateDialog/SelectLibRateDialog.vue'; import SelectDateDialog from './SelectDateDialog/SelectDateDialog.vue'; import BookInfoDialog from './BookInfoDialog/BookInfoDialog.vue'; +import SelectExtSearchDialog from './SelectExtSearchDialog/SelectExtSearchDialog.vue'; import authorBooksStorage from './authorBooksStorage'; import DivBtn from '../share/DivBtn.vue'; @@ -252,11 +285,13 @@ import diffUtils from '../../share/diffUtils'; import _ from 'lodash'; +const maxLimit = 1000; + const route2component = { 'author': {component: 'AuthorList', label: 'Авторы'}, 'series': {component: 'SeriesList', label: 'Серии'}, 'title': {component: 'TitleList', label: 'Книги'}, - 'extended': {component: 'TitleList', label: 'Расширенный поиск'}, + 'extended': {component: 'ExtendedList', label: 'Расширенный поиск'}, }; const componentOptions = { @@ -264,6 +299,7 @@ const componentOptions = { AuthorList, SeriesList, TitleList, + ExtendedList, PageScroller, SettingsDialog, SelectGenreDialog, @@ -271,6 +307,7 @@ const componentOptions = { SelectLibRateDialog, SelectDateDialog, BookInfoDialog, + SelectExtSearchDialog, Dialog, DivBtn }, @@ -293,6 +330,12 @@ const componentOptions = { this.makeTitle(); this.updateRouteQueryFromSearch(); this.updateSearchDate(true); + + //extSearch + if (this.isExtendedSearch) { + this.extSearch.page = newValue.page; + this.extSearch.limit = newValue.limit; + } }, deep: true, }, @@ -363,6 +406,7 @@ class Search { selectLibRateDialogVisible = false; selectDateDialogVisible = false; bookInfoDialogVisible = false; + selectExtSearchDialogVisible = false; pageCount = 1; @@ -381,11 +425,21 @@ class Search { lang: search.lang || '', date: search.date || '', librate: search.librate || '', + page: search.page || 1, limit: search.limit || 50, }); }, - }; + }; + + extSearch = { + setDefaults(search) { + return Object.assign({}, search, { + page: search.page || 1, + limit: search.limit || 50, + }); + }, + }; searchDate = ''; prevManualDate = ''; @@ -429,6 +483,7 @@ class Search { this.api = this.$root.api; this.search = this.search.setDefaults(this.search); + this.extSearch = this.extSearch.setDefaults(this.extSearch); this.search.lang = this.langDefault; this.loadSettings(); @@ -550,6 +605,14 @@ class Search { return result.filter(s => s).join(', '); } + get isExtendedSearch() { + return this.selectedList === 'extended'; + } + + get extSearchNames() { + return ''; + } + inputBgColor(inp) { if (inp === this.selectedList) return 'white'; @@ -750,6 +813,14 @@ class Search { this.hideTooltip(); this.selectLibRateDialogVisible = true; } + + selectExtSearch() { + this.hideTooltip(); + this.selectExtSearchDialogVisible = true; + } + + clearExtSearch() { + } onScroll() { const curScrollTop = this.$refs.scroller.scrollTop; @@ -862,22 +933,35 @@ class Search { const query = to.query; - this.search = this.search.setDefaults( - Object.assign({}, this.search, { - author: query.author, - series: query.series, - title: query.title, - genre: query.genre, - lang: (typeof(query.lang) == 'string' ? query.lang : this.langDefault), - date: query.date, - librate: query.librate, - page: parseInt(query.page, 10), - limit: parseInt(query.limit, 10) || this.search.limit, - }) - ); + if (!this.isExtendedSearch) { + this.search = this.search.setDefaults( + Object.assign({}, this.search, { + author: query.author, + series: query.series, + title: query.title, + genre: query.genre, + lang: (typeof(query.lang) == 'string' ? query.lang : this.langDefault), + date: query.date, + librate: query.librate, - if (this.search.limit > 1000) - this.search.limit = 1000; + page: parseInt(query.page, 10), + limit: parseInt(query.limit, 10) || this.search.limit, + }) + ); + + if (this.search.limit > maxLimit) + this.search.limit = maxLimit; + } else { + this.extSearch = this.extSearch.setDefaults( + Object.assign({}, this.extSearch, { + page: parseInt(query.page, 10), + limit: parseInt(query.limit, 10) || this.search.limit, + }) + ); + + if (this.extSearch.limit > maxLimit) + this.extSearch.limit = maxLimit; + } } updateRouteQueryFromSearch() { @@ -887,16 +971,24 @@ class Search { this.routeUpdating = true; try { const oldQuery = this.$route.query; - const cloned = _.cloneDeep(this.search); + let query = {}; - delete cloned.setDefaults; + if (!this.isExtendedSearch) { + const cloned = _.cloneDeep(this.search); - const query = _.pickBy(cloned); + delete cloned.setDefaults; - if (this.search.lang == this.langDefault) { - delete query.lang; + query = _.pickBy(cloned); + + if (this.search.lang == this.langDefault) { + delete query.lang; + } else { + query.lang = this.search.lang; + } } else { - query.lang = this.search.lang; + const cloned = _.cloneDeep(this.extSearch); + delete cloned.setDefaults; + query = _.pickBy(cloned); } const diff = diffUtils.getObjDiff(oldQuery, query); diff --git a/client/components/Search/SelectExtSearchDialog/SelectExtSearchDialog.vue b/client/components/Search/SelectExtSearchDialog/SelectExtSearchDialog.vue new file mode 100644 index 0000000..5fb14fd --- /dev/null +++ b/client/components/Search/SelectExtSearchDialog/SelectExtSearchDialog.vue @@ -0,0 +1,67 @@ + + + + + \ No newline at end of file diff --git a/client/share/utils.js b/client/share/utils.js index 3607954..2e7fe96 100644 --- a/client/share/utils.js +++ b/client/share/utils.js @@ -36,14 +36,14 @@ export function keyEventToCode(event) { export function wordEnding(num, type = 0) { const endings = [ - ['ов', '', 'а', 'а', 'а', 'ов', 'ов', 'ов', 'ов', 'ов'], - ['й', 'я', 'и', 'и', 'и', 'й', 'й', 'й', 'й', 'й'], - ['о', '', 'о', 'о', 'о', 'о', 'о', 'о', 'о', 'о'], - ['ий', 'ие', 'ия', 'ия', 'ия', 'ий', 'ий', 'ий', 'ий', 'ий'], - ['о', 'а', 'о', 'о', 'о', 'о', 'о', 'о', 'о', 'о'], - ['ок', 'ка', 'ки', 'ки', 'ки', 'ок', 'ок', 'ок', 'ок', 'ок'], - ['ых', 'ое', 'ых', 'ых', 'ых', 'ых', 'ых', 'ых', 'ых', 'ых'], - ['о', 'о', 'о', 'о', 'о', 'о', 'о', 'о', 'о', 'о'], + ['ов', '', 'а', 'а', 'а', 'ов', 'ов', 'ов', 'ов', 'ов'],//0 + ['й', 'я', 'и', 'и', 'и', 'й', 'й', 'й', 'й', 'й'],//1 + ['о', '', 'о', 'о', 'о', 'о', 'о', 'о', 'о', 'о'],//2 + ['ий', 'ие', 'ия', 'ия', 'ия', 'ий', 'ий', 'ий', 'ий', 'ий'],//3 + ['о', 'а', 'о', 'о', 'о', 'о', 'о', 'о', 'о', 'о'],//4 + ['ок', 'ка', 'ки', 'ки', 'ки', 'ок', 'ок', 'ок', 'ок', 'ок'],//5 + ['ых', 'ое', 'ых', 'ых', 'ых', 'ых', 'ых', 'ых', 'ых', 'ых'],//6 + ['о', 'о', 'о', 'о', 'о', 'о', 'о', 'о', 'о', 'о'],//7 ]; const deci = num % 100; if (deci > 10 && deci < 20) { diff --git a/server/core/DbSearcher.js b/server/core/DbSearcher.js index 0260ab9..c706331 100644 --- a/server/core/DbSearcher.js +++ b/server/core/DbSearcher.js @@ -571,6 +571,8 @@ class DbSearcher { checks.push(filterBySearch(f.field, searchValue)); } if (f.type === 'N') { searchValue = parseInt(searchValue, 10); + if (isNaN(searchValue)) + throw new Error(`Wrong query param, ${f.field}=${searchValue}`); checks.push(`row.${f.field} === ${searchValue}`); } }