Эх сурвалжийг харах

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

Book Pauk 2 жил өмнө
parent
commit
85007f3e91

+ 14 - 12
client/components/Search/BaseList.js

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

+ 84 - 73
client/components/Search/Search.vue

@@ -339,6 +339,13 @@ const componentOptions = {
             },
             deep: true,
         },
+        extSearch: {
+            handler() {
+                this.makeTitle();
+                this.updateRouteQueryFromSearch();
+            },
+            deep: true,
+        },
         extendedParams(newValue) {
             this.setSetting('extendedParams', newValue);
         },
@@ -415,31 +422,8 @@ class Search {
     inputDebounce = 200;
 
     //search fields
-    search = {
-        setDefaults(search) {
-            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,
-            });
-        },
-    };    
+    search = {};
+    extSearch = {};
 
     searchDate = '';
     prevManualDate = '';
@@ -478,13 +462,22 @@ class Search {
         {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() {
         this.commit = this.$store.commit;
         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.generateDefaults(this.search, ['author', 'series', 'title', 'genre', 'lang', 'date', 'librate']);
+        this.search.setDefaults(this.search);
 
         this.loadSettings();
     }
@@ -493,6 +486,10 @@ class Search {
         (async() => {
             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
             window.addEventListener('message', (event) => {
                 if (!_.isObject(event.data) || event.data.from != 'ExternalLibs')
@@ -510,11 +507,11 @@ class Search {
                 this.$refs.authorInput.focus();
 
             this.updateListFromRoute(this.$route);
-            this.updateSearchFromRouteQuery(this.$route);
-
-            this.sendMessage({type: 'mes', data: 'hello-from-inpx-web'});
 
             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;
     }
 
+    get recStruct() {
+        if (this.config.dbConfig && this.config.dbConfig.inpxInfo.recStruct)
+            return this.config.dbConfig.inpxInfo.recStruct;
+        else
+            return [];
+    }
+
     get settings() {
         return this.$store.state.settings;
     }
@@ -610,7 +614,12 @@ class Search {
     }
 
     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) {
@@ -820,6 +829,8 @@ class Search {
     }
 
     clearExtSearch() {
+        const self = this.extSearch;
+        self.setDefaults(self, {page: self.page, limit: self.limit});
     }
     
     onScroll() {
@@ -925,6 +936,8 @@ class Search {
     }
 
     updateSearchFromRouteQuery(to) {
+        if (!this.ready)
+            return;
         if (this.list.liberamaReady)
             this.sendCurrentUrl();
 
@@ -933,35 +946,34 @@ class Search {
 
         const query = to.query;
 
-        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,
-
-                    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;
+        this.search.setDefaults(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.search.limit > maxLimit)
+            this.search.limit = maxLimit;
+
+        const queryExtSearch = {
+            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() {
@@ -973,22 +985,21 @@ class Search {
             const oldQuery = this.$route.query;
             let query = {};
 
-            if (!this.isExtendedSearch) {                
-                const cloned = _.cloneDeep(this.search);
-
-                delete cloned.setDefaults;
+            const cloned = {};
+            this.search.setDefaults(cloned, this.search);
 
-                query = _.pickBy(cloned);
+            query = _.pickBy(cloned);
 
-                if (this.search.lang == this.langDefault) {
-                    delete query.lang;
-                } else {
-                    query.lang = this.search.lang;
-                }
+            if (this.search.lang == this.langDefault) {
+                delete query.lang;
             } else {
-                const cloned = _.cloneDeep(this.extSearch);
-                delete cloned.setDefaults;
-                query = _.pickBy(cloned);
+                query.lang = this.search.lang;
+            }
+
+            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);

+ 22 - 13
client/components/Search/SelectExtSearchDialog/SelectExtSearchDialog.vue

@@ -8,13 +8,13 @@
             </div>
         </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 v-for="f in recStruct" :key="f.field" class="row">
                     <div class="q-mx-xs" />
                     <q-input
                         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'"
                         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>
-            <q-btn class="q-px-md q-ml-sm" color="primary" dense no-caps @click="okClick">
-                Закрыть
-            </q-btn>
         </template>
     </Dialog>
 </template>
@@ -43,6 +40,7 @@
 import vueComponent from '../../vueComponent.js';
 
 import Dialog from '../../share/Dialog.vue';
+import _ from 'lodash';
 
 const componentOptions = {
     components: {
@@ -55,8 +53,11 @@ const componentOptions = {
         dialogVisible(newValue) {
             this.$emit('update:modelValue', newValue);
         },
-        extSearch(newValue) {
-            this.search = newValue;
+        extSearch: {
+            handler(newValue) {
+                this.search = _.cloneDeep(newValue);
+            },
+            deep: true,
         },
         search: {
             handler() {
@@ -98,7 +99,16 @@ class SelectExtSearchDialog {
 
     validate() {
         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 = [];
@@ -115,13 +125,12 @@ class SelectExtSearchDialog {
         this.error = error.join('<br>');
     }
 
-    okClick() {
-        this.dialogVisible = false;
-    }
-
     apply() {
         this.validate();
-        this.dialogVisible = false;
+        if (!this.error) {
+            this.$emit('update:extSearch', _.cloneDeep(this.search));
+            this.dialogVisible = false;
+        }
     }
 }
 

+ 5 - 4
server/core/DbSearcher.js

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