Работа над проектом
This commit is contained in:
@@ -156,6 +156,16 @@ class Api {
|
||||
return response;
|
||||
}
|
||||
|
||||
async getGenreTree() {
|
||||
const response = await this.request({action: 'get-genre-tree'});
|
||||
|
||||
if (response.error) {
|
||||
throw new Error(response.error);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
async getConfig() {
|
||||
const response = await this.request({action: 'get-config'});
|
||||
|
||||
|
||||
@@ -160,6 +160,8 @@
|
||||
</q-btn>
|
||||
</template>
|
||||
</Dialog>
|
||||
|
||||
<SelectGenreDialog v-model="selectGenreDialogVisible" v-model:genre="genre" :genre-tree="genreTree" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -169,6 +171,7 @@ import vueComponent from '../vueComponent.js';
|
||||
import { reactive } from 'vue';
|
||||
|
||||
import PageScroller from './PageScroller/PageScroller.vue';
|
||||
import SelectGenreDialog from './SelectGenreDialog/SelectGenreDialog.vue';
|
||||
import authorBooksStorage from './authorBooksStorage';
|
||||
import DivBtn from '../share/DivBtn.vue';
|
||||
import Dialog from '../share/Dialog.vue';
|
||||
@@ -180,6 +183,7 @@ import _ from 'lodash';
|
||||
const componentOptions = {
|
||||
components: {
|
||||
PageScroller,
|
||||
SelectGenreDialog,
|
||||
Dialog,
|
||||
DivBtn
|
||||
},
|
||||
@@ -236,6 +240,8 @@ class Search {
|
||||
loadingMessage = '';
|
||||
loadingMessage2 = '';
|
||||
settingsDialogVisible = false;
|
||||
selectGenreDialogVisible = false;
|
||||
|
||||
page = 1;
|
||||
pageCount = 1;
|
||||
|
||||
@@ -262,6 +268,8 @@ class Search {
|
||||
totalFound = 0;
|
||||
bookRowsOnPage = 100;
|
||||
inpxHash = '';
|
||||
genreTree = [];
|
||||
genreTreeInpxHash = '';
|
||||
|
||||
limitOptions = [
|
||||
{label: '10', value: 10},
|
||||
@@ -338,7 +346,7 @@ class Search {
|
||||
}
|
||||
|
||||
selectGenre() {
|
||||
this.$root.stdDialog.alert('Выбор жанра');
|
||||
this.selectGenreDialogVisible = true;
|
||||
}
|
||||
|
||||
selectLang() {
|
||||
@@ -455,9 +463,8 @@ class Search {
|
||||
try {
|
||||
let result;
|
||||
|
||||
const key = `${authorId}-${this.inpxHash}`;
|
||||
|
||||
if (this.abCacheEnabled) {
|
||||
const key = `${authorId}-${this.inpxHash}`;
|
||||
const data = await authorBooksStorage.getData(key);
|
||||
if (data) {
|
||||
result = JSON.parse(data);
|
||||
@@ -516,6 +523,33 @@ class Search {
|
||||
}
|
||||
}
|
||||
|
||||
async updateGenreTreeIfNeeded() {
|
||||
try {
|
||||
if (this.genreTreeInpxHash !== this.inpxHash) {
|
||||
let result;
|
||||
|
||||
if (this.abCacheEnabled) {
|
||||
const key = `genre-tree-${this.inpxHash}`;
|
||||
const data = await authorBooksStorage.getData(key);
|
||||
if (data) {
|
||||
result = JSON.parse(data);
|
||||
} else {
|
||||
result = await this.api.getGenreTree();
|
||||
|
||||
await authorBooksStorage.setData(key, JSON.stringify(result));
|
||||
}
|
||||
} else {
|
||||
result = await this.api.getGenreTree();
|
||||
}
|
||||
|
||||
this.genreTree = result.genreTree;
|
||||
this.genreTreeInpxHash = result.inpxHash;
|
||||
}
|
||||
} catch (e) {
|
||||
this.$root.stdDialog.alert(e.message, 'Ошибка');
|
||||
}
|
||||
}
|
||||
|
||||
async updateTableData() {
|
||||
let result = [];
|
||||
|
||||
@@ -591,6 +625,7 @@ class Search {
|
||||
this.inpxHash = result.inpxHash;
|
||||
|
||||
this.searchResult = result;
|
||||
await this.updateGenreTreeIfNeeded();
|
||||
await this.updateTableData();
|
||||
this.scrollToTop();
|
||||
} catch (e) {
|
||||
|
||||
172
client/components/Search/SelectGenreDialog/SelectGenreDialog.vue
Normal file
172
client/components/Search/SelectGenreDialog/SelectGenreDialog.vue
Normal file
@@ -0,0 +1,172 @@
|
||||
<template>
|
||||
<Dialog v-model="dialogVisible">
|
||||
<template #header>
|
||||
<div class="row items-center">
|
||||
<div style="font-size: 130%">
|
||||
Выбрать жанры
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="col column" style="height: 500px; min-width: 400px">
|
||||
<div class="row items-center top-panel bg-grey-3">
|
||||
<q-input ref="search" v-model="search" class="col" outlined dense bg-color="white" placeholder="Найти" clearable />
|
||||
</div>
|
||||
|
||||
<div class="col fit tree">
|
||||
<div v-show="nodes.length" class="checkbox-tick-all">
|
||||
<q-checkbox v-model="tickAll" size="36px" label="Выбрать все" @update:model-value="makeTickAll" />
|
||||
</div>
|
||||
<q-tree
|
||||
v-model:ticked="ticked"
|
||||
v-model:expanded="expanded"
|
||||
class="q-my-xs"
|
||||
:nodes="nodes"
|
||||
node-key="key"
|
||||
tick-strategy="leaf"
|
||||
selected-color="black"
|
||||
:filter="search"
|
||||
no-nodes-label="Жанров нет"
|
||||
no-results-label="Ничего не найдено"
|
||||
>
|
||||
</q-tree>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<q-btn class="q-px-md q-ml-sm" color="primary" dense no-caps @click="okClick">
|
||||
OK
|
||||
</q-btn>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
//-----------------------------------------------------------------------------
|
||||
import vueComponent from '../../vueComponent.js';
|
||||
|
||||
import Dialog from '../../share/Dialog.vue';
|
||||
|
||||
const componentOptions = {
|
||||
components: {
|
||||
Dialog
|
||||
},
|
||||
watch: {
|
||||
modelValue(newValue) {
|
||||
this.dialogVisible = newValue;
|
||||
if (newValue)
|
||||
this.init();//no await
|
||||
},
|
||||
dialogVisible(newValue) {
|
||||
this.$emit('update:modelValue', newValue);
|
||||
},
|
||||
genre() {
|
||||
this.updateTicked();
|
||||
},
|
||||
ticked() {
|
||||
this.checkAllTicked();
|
||||
this.updateGenre();
|
||||
},
|
||||
}
|
||||
};
|
||||
class GenreSelectDialog {
|
||||
_options = componentOptions;
|
||||
_props = {
|
||||
modelValue: Boolean,
|
||||
genre: {type: String, value: ''},
|
||||
genreTree: Array,
|
||||
};
|
||||
|
||||
dialogVisible = false;
|
||||
|
||||
search = '';
|
||||
ticked = [];
|
||||
expanded = [];
|
||||
tickAll = false;
|
||||
allKeys = [];
|
||||
|
||||
created() {
|
||||
}
|
||||
|
||||
async init() {
|
||||
}
|
||||
|
||||
get nodes() {
|
||||
const result = [];
|
||||
|
||||
this.allKeys = [];
|
||||
for (const section of this.genreTree) {
|
||||
const rkey = `r-${section.name}`;
|
||||
const sec = {label: section.name, key: rkey, children: []};
|
||||
|
||||
for (const g of section.value) {
|
||||
sec.children.push({label: g.name, key: g.value});
|
||||
this.allKeys.push(g.value);
|
||||
}
|
||||
|
||||
result.push(sec);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
makeTickAll() {
|
||||
if (this.tickAll) {
|
||||
const newTicked = [];
|
||||
for (const key of this.allKeys) {
|
||||
newTicked.push(key);
|
||||
}
|
||||
this.ticked = newTicked;
|
||||
} else {
|
||||
this.ticked = [];
|
||||
}
|
||||
}
|
||||
|
||||
checkAllTicked() {
|
||||
const ticked = new Set(this.ticked);
|
||||
|
||||
let newTickAll = !!(this.nodes.length);
|
||||
for (const key of this.allKeys) {
|
||||
if (!ticked.has(key)) {
|
||||
newTickAll = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.tickAll = newTickAll;
|
||||
}
|
||||
|
||||
updateTicked() {
|
||||
this.ticked = this.genre.split(',').filter(s => s);
|
||||
}
|
||||
|
||||
updateGenre() {
|
||||
this.$emit('update:genre', this.ticked.join(','));
|
||||
}
|
||||
|
||||
okClick() {
|
||||
this.dialogVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
export default vueComponent(GenreSelectDialog);
|
||||
//-----------------------------------------------------------------------------
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.top-panel {
|
||||
height: 50px;
|
||||
border-bottom: 1px solid gray;
|
||||
padding: 0 10px 0 12px;
|
||||
}
|
||||
|
||||
.tree {
|
||||
padding: 0px 10px 10px 10px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.checkbox-tick-all {
|
||||
border-bottom: 1px solid #bbbbbb;
|
||||
margin-bottom: 7px;
|
||||
padding: 5px 5px 2px 16px;
|
||||
}
|
||||
</style>
|
||||
@@ -31,7 +31,7 @@ import {QSelect} from 'quasar/src/components/select';
|
||||
//import {QPopupProxy} from 'quasar/src/components/popup-proxy';
|
||||
import {QDialog} from 'quasar/src/components/dialog';
|
||||
//import {QChip} from 'quasar/src/components/chip';
|
||||
//import {QTree} from 'quasar/src/components/tree';
|
||||
import {QTree} from 'quasar/src/components/tree';
|
||||
//import {QVirtualScroll} from 'quasar/src/components/virtual-scroll';
|
||||
|
||||
//import {QExpansionItem} from 'quasar/src/components/expansion-item';
|
||||
@@ -63,7 +63,7 @@ const components = {
|
||||
//QPopupProxy,
|
||||
QDialog,
|
||||
//QChip,
|
||||
//QTree,
|
||||
QTree,
|
||||
//QExpansionItem,
|
||||
//QVirtualScroll,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user