Работа над расширенным поиском

This commit is contained in:
Book Pauk
2022-12-07 15:36:54 +07:00
parent 5b6ef8202f
commit 85007f3e91
4 changed files with 122 additions and 99 deletions

View File

@@ -21,13 +21,16 @@ const componentOptions = {
this.loadSettings(); this.loadSettings();
}, },
search: { search: {
handler(newValue) { handler() {
this.limit = newValue.limit; if (!this.isExtendedSearch)
this.refresh();
if (this.pageCount > 1) },
this.prevPage = this.search.page; deep: true,
},
this.refresh(); extSearch: {
handler() {
if (this.isExtendedSearch)
this.refresh();
}, },
deep: true, deep: true,
}, },
@@ -519,9 +522,8 @@ export default class BaseList {
getQuery() { getQuery() {
const search = (this.isExtendedSearch ? this.extSearch : this.search); const search = (this.isExtendedSearch ? this.extSearch : this.search);
let newQuery = _.cloneDeep(search); const newQuery = {};
newQuery = newQuery.setDefaults(newQuery); search.setDefaults(newQuery, search);
delete newQuery.setDefaults;
//дата //дата
if (newQuery.date) { if (newQuery.date) {
@@ -532,8 +534,8 @@ export default class BaseList {
newQuery.offset = (newQuery.page - 1)*newQuery.limit; newQuery.offset = (newQuery.page - 1)*newQuery.limit;
//del //del
if (!this.showDeleted) if (!newQuery.del && !this.showDeleted)
newQuery.del = 0; newQuery.del = '0';
return newQuery; return newQuery;
} }

View File

@@ -339,6 +339,13 @@ const componentOptions = {
}, },
deep: true, deep: true,
}, },
extSearch: {
handler() {
this.makeTitle();
this.updateRouteQueryFromSearch();
},
deep: true,
},
extendedParams(newValue) { extendedParams(newValue) {
this.setSetting('extendedParams', newValue); this.setSetting('extendedParams', newValue);
}, },
@@ -415,31 +422,8 @@ class Search {
inputDebounce = 200; inputDebounce = 200;
//search fields //search fields
search = { search = {};
setDefaults(search) { extSearch = {};
return Object.assign({}, search, {
author: search.author || '',
series: search.series || '',
title: search.title || '',
genre: search.genre || '',
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 = ''; searchDate = '';
prevManualDate = ''; prevManualDate = '';
@@ -478,13 +462,22 @@ class Search {
{label: 'выбрать даты', value: 'manual'}, {label: 'выбрать даты', value: 'manual'},
]; ];
generateDefaults(obj, fields) {
obj.setDefaults = (self, value = {}) => {
for (const f of fields)
self[f] = value[f] || '';
self.page = value.page || 1;
self.limit = value.limit || 50;
};
}
created() { created() {
this.commit = this.$store.commit; this.commit = this.$store.commit;
this.api = this.$root.api; this.api = this.$root.api;
this.search = this.search.setDefaults(this.search); this.generateDefaults(this.search, ['author', 'series', 'title', 'genre', 'lang', 'date', 'librate']);
this.extSearch = this.extSearch.setDefaults(this.extSearch); this.search.setDefaults(this.search);
this.search.lang = this.langDefault;
this.loadSettings(); this.loadSettings();
} }
@@ -493,6 +486,10 @@ class Search {
(async() => { (async() => {
await this.api.updateConfig(); await this.api.updateConfig();
this.generateDefaults(this.extSearch, this.recStruct.map(f => f.field));
this.extSearch.setDefaults(this.extSearch);
this.search.lang = this.langDefault;
//для встраивания в liberama //для встраивания в liberama
window.addEventListener('message', (event) => { window.addEventListener('message', (event) => {
if (!_.isObject(event.data) || event.data.from != 'ExternalLibs') if (!_.isObject(event.data) || event.data.from != 'ExternalLibs')
@@ -510,11 +507,11 @@ class Search {
this.$refs.authorInput.focus(); this.$refs.authorInput.focus();
this.updateListFromRoute(this.$route); this.updateListFromRoute(this.$route);
this.updateSearchFromRouteQuery(this.$route);
this.sendMessage({type: 'mes', data: 'hello-from-inpx-web'});
this.ready = true; this.ready = true;
this.sendMessage({type: 'mes', data: 'hello-from-inpx-web'});
this.updateSearchFromRouteQuery(this.$route);
})(); })();
} }
@@ -554,6 +551,13 @@ class Search {
return this.$store.state.config; return this.$store.state.config;
} }
get recStruct() {
if (this.config.dbConfig && this.config.dbConfig.inpxInfo.recStruct)
return this.config.dbConfig.inpxInfo.recStruct;
else
return [];
}
get settings() { get settings() {
return this.$store.state.settings; return this.$store.state.settings;
} }
@@ -610,7 +614,12 @@ class Search {
} }
get extSearchNames() { get extSearchNames() {
return ''; let result = [];
for (const f of this.recStruct) {
if (this.extSearch[f.field])
result.push(`${f.field}=${this.extSearch[f.field]}`);
}
return result.join(', ');
} }
inputBgColor(inp) { inputBgColor(inp) {
@@ -820,6 +829,8 @@ class Search {
} }
clearExtSearch() { clearExtSearch() {
const self = this.extSearch;
self.setDefaults(self, {page: self.page, limit: self.limit});
} }
onScroll() { onScroll() {
@@ -925,6 +936,8 @@ class Search {
} }
updateSearchFromRouteQuery(to) { updateSearchFromRouteQuery(to) {
if (!this.ready)
return;
if (this.list.liberamaReady) if (this.list.liberamaReady)
this.sendCurrentUrl(); this.sendCurrentUrl();
@@ -933,35 +946,34 @@ class Search {
const query = to.query; const query = to.query;
if (!this.isExtendedSearch) { this.search.setDefaults(this.search, {
this.search = this.search.setDefaults( author: query.author,
Object.assign({}, this.search, { series: query.series,
author: query.author, title: query.title,
series: query.series, genre: query.genre,
title: query.title, lang: (typeof(query.lang) == 'string' ? query.lang : this.langDefault),
genre: query.genre, date: query.date,
lang: (typeof(query.lang) == 'string' ? query.lang : this.langDefault), librate: query.librate,
date: query.date,
librate: query.librate,
page: parseInt(query.page, 10), page: parseInt(query.page, 10),
limit: parseInt(query.limit, 10) || this.search.limit, limit: parseInt(query.limit, 10) || this.search.limit,
}) });
);
if (this.search.limit > maxLimit) if (this.search.limit > maxLimit)
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) const queryExtSearch = {
this.extSearch.limit = maxLimit; page: this.search.page,
limit: this.search.limit,
};
for (const f of this.recStruct) {
const field = `ex_${f.field}`;
if (query[field])
queryExtSearch[f.field] = query[field];
} }
this.extSearch.setDefaults(this.extSearch, queryExtSearch);
} }
updateRouteQueryFromSearch() { updateRouteQueryFromSearch() {
@@ -973,22 +985,21 @@ class Search {
const oldQuery = this.$route.query; const oldQuery = this.$route.query;
let query = {}; let query = {};
if (!this.isExtendedSearch) { const cloned = {};
const cloned = _.cloneDeep(this.search); this.search.setDefaults(cloned, this.search);
delete cloned.setDefaults; query = _.pickBy(cloned);
query = _.pickBy(cloned); if (this.search.lang == this.langDefault) {
delete query.lang;
if (this.search.lang == this.langDefault) {
delete query.lang;
} else {
query.lang = this.search.lang;
}
} else { } else {
const cloned = _.cloneDeep(this.extSearch); query.lang = this.search.lang;
delete cloned.setDefaults; }
query = _.pickBy(cloned);
for (const f of this.recStruct) {
const field = `ex_${f.field}`;
if (this.extSearch[f.field])
query[field] = this.extSearch[f.field];
} }
const diff = diffUtils.getObjDiff(oldQuery, query); const diff = diffUtils.getObjDiff(oldQuery, query);

View File

@@ -8,13 +8,13 @@
</div> </div>
</template> </template>
<div ref="box" class="column q-mt-xs overflow-auto" style="max-width: 700px; padding: 0px 10px 10px 10px;"> <div ref="box" class="column q-mt-xs overflow-auto" style="max-width: 660px; padding: 0px 10px 10px 10px;">
<div class="row"> <div class="row">
<div v-for="f in recStruct" :key="f.field" class="row"> <div v-for="f in recStruct" :key="f.field" class="row">
<div class="q-mx-xs" /> <div class="q-mx-xs" />
<q-input <q-input
v-model="search[f.field]" :maxlength="5000" v-model="search[f.field]" :maxlength="5000"
class="q-mt-xs" style="width: 150px;" :label="`${f.field} (${f.type == 'N' ? 'число' : 'строка'})`" class="q-mt-xs" style="width: 150px;" :label="`(${f.type}) ${f.field}`"
:bg-color="bgColor[f.field] || 'white'" :bg-color="bgColor[f.field] || 'white'"
stack-label outlined dense clearable stack-label outlined dense clearable
> >
@@ -31,9 +31,6 @@
<q-btn class="q-px-md q-ml-sm" color="primary" dense no-caps :disabled="error !== ''" @click="apply"> <q-btn class="q-px-md q-ml-sm" color="primary" dense no-caps :disabled="error !== ''" @click="apply">
Применить Применить
</q-btn> </q-btn>
<q-btn class="q-px-md q-ml-sm" color="primary" dense no-caps @click="okClick">
Закрыть
</q-btn>
</template> </template>
</Dialog> </Dialog>
</template> </template>
@@ -43,6 +40,7 @@
import vueComponent from '../../vueComponent.js'; import vueComponent from '../../vueComponent.js';
import Dialog from '../../share/Dialog.vue'; import Dialog from '../../share/Dialog.vue';
import _ from 'lodash';
const componentOptions = { const componentOptions = {
components: { components: {
@@ -55,8 +53,11 @@ const componentOptions = {
dialogVisible(newValue) { dialogVisible(newValue) {
this.$emit('update:modelValue', newValue); this.$emit('update:modelValue', newValue);
}, },
extSearch(newValue) { extSearch: {
this.search = newValue; handler(newValue) {
this.search = _.cloneDeep(newValue);
},
deep: true,
}, },
search: { search: {
handler() { handler() {
@@ -98,7 +99,16 @@ class SelectExtSearchDialog {
validate() { validate() {
const validNumValue = (n) => { const validNumValue = (n) => {
return false; const validChars = new Set('0123456789.'.split(''));
for (const c of n.split(''))
if (!validChars.has(c))
return false;
const v = n.split('..');
if ( isNaN(parseInt(v[0] || '0', 10)) || isNaN(parseInt(v[1] || '0', 10)) )
return false;
return true;
}; };
let error = []; let error = [];
@@ -115,13 +125,12 @@ class SelectExtSearchDialog {
this.error = error.join('<br>'); this.error = error.join('<br>');
} }
okClick() {
this.dialogVisible = false;
}
apply() { apply() {
this.validate(); this.validate();
this.dialogVisible = false; if (!this.error) {
this.$emit('update:extSearch', _.cloneDeep(this.search));
this.dialogVisible = false;
}
} }
} }

View File

@@ -213,12 +213,13 @@ class DbSearcher {
} }
//удаленные //удаленные
if (query.del !== undefined) { if (query.del) {
const key = `book-ids-del-${query.del}`; const del = parseInt(query.del, 10) || 0;
const key = `book-ids-del-${del}`;
let ids = await this.getCached(key); let ids = await this.getCached(key);
if (ids === null) { if (ids === null) {
ids = await tableBookIds('del', `@indexLR('value', ${db.esc(query.del)}, ${db.esc(query.del)})`); ids = await tableBookIds('del', `@indexLR('value', ${db.esc(del)}, ${db.esc(del)})`);
await this.putCached(key, ids); await this.putCached(key, ids);
} }
@@ -559,7 +560,7 @@ class DbSearcher {
//return !bookValue || (bookValue !== emptyFieldValue && !enru.has(bookValue[0]) && bookValue.indexOf(searchValue) >= 0); //return !bookValue || (bookValue !== emptyFieldValue && !enru.has(bookValue[0]) && bookValue.indexOf(searchValue) >= 0);
return 'true'; return 'true';
} else { } else {
return `(row.${bookField}.localeCompare(${db.esc(searchValue)}) >= 0 && row.${bookField}.localeCompare(${db.esc(searchValue)} + maxUtf8Char) <= 0)`; return `(row.${bookField}.localeCompare(${db.esc(searchValue)}) >= 0 && row.${bookField}.localeCompare(${db.esc(searchValue)} + ${db.esc(maxUtf8Char)}) <= 0)`;
} }
}; };