Работа над проектом
This commit is contained in:
@@ -1,9 +1,27 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="q-my-sm" @click="selectTitle(book.title)">
|
||||
{{ book.title }}
|
||||
<br>{{ book.src }}
|
||||
<div class="row items-center">
|
||||
<div class="q-my-sm clickable2" @click="selectTitle">
|
||||
{{ book.serno ? `${book.serno}. ` : '' }}
|
||||
<span class="text-blue-10">{{ book.title }}</span>
|
||||
</div>
|
||||
|
||||
<div class="q-ml-sm">
|
||||
{{ bookSize }}, {{ book.ext }}
|
||||
</div>
|
||||
|
||||
<div class="q-ml-sm clickable" @click="download">
|
||||
(скачать)
|
||||
</div>
|
||||
|
||||
<div class="q-ml-sm clickable" @click="copyLink">
|
||||
<q-icon name="la la-copy" size="20px" />
|
||||
</div>
|
||||
|
||||
<div class="q-ml-sm">
|
||||
{{ bookGenre }}
|
||||
</div>
|
||||
|
||||
{{ book.src1 }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -21,11 +39,44 @@ class BookView {
|
||||
_options = componentOptions;
|
||||
_props = {
|
||||
book: Object,
|
||||
genreTree: Array,
|
||||
};
|
||||
|
||||
created() {
|
||||
}
|
||||
|
||||
get bookSize() {
|
||||
let size = this.book.size/1024;
|
||||
let unit = 'KB';
|
||||
if (size > 1024) {
|
||||
size = size/1024;
|
||||
unit = 'MB';
|
||||
}
|
||||
return `${size.toFixed(0)}${unit}`;
|
||||
}
|
||||
|
||||
get bookGenre() {
|
||||
let result = [];
|
||||
const genre = new Set(this.book.genre.split(','));
|
||||
|
||||
for (const section of this.genreTree) {
|
||||
for (const g of section.value)
|
||||
if (genre.has(g.value))
|
||||
result.push(g.name);
|
||||
}
|
||||
|
||||
return `(${result.join(', ')})`;
|
||||
}
|
||||
|
||||
selectTitle() {
|
||||
this.$emit('bookEvent', {action: 'titleClick', book: this.book});
|
||||
}
|
||||
|
||||
download() {
|
||||
}
|
||||
|
||||
copyLink() {
|
||||
}
|
||||
}
|
||||
|
||||
export default vueComponent(BookView);
|
||||
@@ -33,4 +84,13 @@ export default vueComponent(BookView);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.clickable {
|
||||
color: blue;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.clickable2 {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -131,7 +131,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clickable q-ml-xs q-py-sm" style="font-weight: bold" @click="selectAuthor(item.author)">
|
||||
<div class="clickable2 q-ml-xs q-py-sm text-green-10 text-bold" @click="selectAuthor(item.author)">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
|
||||
@@ -140,10 +140,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="item.bookLoading" class="book-row">
|
||||
Загрузка
|
||||
<q-icon class="la la-spinner icon-rotate text-blue-8" size="28px" />
|
||||
</div>
|
||||
|
||||
<div v-if="isExpanded(item) && item.books">
|
||||
<div v-for="book in item.books" :key="book.key" class="book-row column">
|
||||
<div v-if="book.type == 'series'" class="column">
|
||||
<div class="row items-center q-mr-xs no-wrap">
|
||||
<div class="row items-center q-mr-xs no-wrap text-grey-9">
|
||||
<div class="row items-center clickable2 q-py-xs no-wrap" @click="expandSeries(book)">
|
||||
<div style="min-width: 30px">
|
||||
<div v-if="!isExpandedSeries(book)">
|
||||
@@ -161,12 +166,10 @@
|
||||
</div>
|
||||
|
||||
<div v-if="isExpandedSeries(book) && book.books" class="book-row column">
|
||||
<BookView v-for="subbook in book.books" :key="subbook.key" :book="subbook" @book-event="bookEvent" />
|
||||
<BookView v-for="subbook in book.books" :key="subbook.key" :book="subbook" :genre-tree="genreTree" @book-event="bookEvent" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<BookView :book="book" @book-event="bookEvent" />
|
||||
</div>
|
||||
<BookView v-else :book="book" :genre-tree="genreTree" @book-event="bookEvent" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -179,6 +182,7 @@
|
||||
<div class="row justify-center">
|
||||
<PageScroller v-show="pageCount > 1" v-model="search.page" :page-count="pageCount" />
|
||||
</div>
|
||||
<div v-show="pageCount <= 1" class="q-mt-lg" />
|
||||
</div>
|
||||
|
||||
<Dialog v-model="settingsDialogVisible">
|
||||
@@ -237,6 +241,8 @@ import diffUtils from '../../share/diffUtils';
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
const maxItemCount = 500;//выше этого значения показываем "Загрузка"
|
||||
|
||||
const componentOptions = {
|
||||
components: {
|
||||
PageScroller,
|
||||
@@ -487,7 +493,7 @@ class Search {
|
||||
}
|
||||
|
||||
get hiddenResultsMessage() {
|
||||
return `+${this.hiddenCount} результат${utils.wordEnding(this.hiddenCount)} скрыты`;
|
||||
return `+${this.hiddenCount} результат${utils.wordEnding(this.hiddenCount)} скрыт${utils.wordEnding(this.hiddenCount, 2)}`;
|
||||
}
|
||||
|
||||
updatePageCount() {
|
||||
@@ -506,13 +512,37 @@ class Search {
|
||||
}
|
||||
}
|
||||
|
||||
getBookCount(item) {
|
||||
let result = '';
|
||||
if (!this.showCounts || item.count === undefined)
|
||||
return result;
|
||||
|
||||
if (item.books) {
|
||||
let count = 0;
|
||||
for (const book of item.books) {
|
||||
if (book.type == 'series')
|
||||
count += book.books.length;
|
||||
else
|
||||
count++;
|
||||
}
|
||||
|
||||
result = `${count}/${item.count}`;
|
||||
} else
|
||||
result = `#/${item.count}`;
|
||||
|
||||
return `(${result})`;
|
||||
}
|
||||
|
||||
selectAuthor(author) {
|
||||
this.search.author = `=${author}`;
|
||||
this.search.series = '';
|
||||
this.search.title = '';
|
||||
this.scrollToTop();
|
||||
}
|
||||
|
||||
selectSeries(series) {
|
||||
this.search.series = `=${series}`;
|
||||
this.search.title = '';
|
||||
}
|
||||
|
||||
bookEvent(event) {
|
||||
@@ -535,14 +565,14 @@ class Search {
|
||||
this.commit('setSettings', {[name]: _.cloneDeep(newValue)});
|
||||
}
|
||||
|
||||
expandAuthor(item) {
|
||||
async expandAuthor(item) {
|
||||
const expanded = _.cloneDeep(this.expanded);
|
||||
const key = item.author;
|
||||
|
||||
if (!this.isExpanded(item)) {
|
||||
expanded.push(key);
|
||||
|
||||
this.getBooks(item);
|
||||
await this.getBooks(item);
|
||||
|
||||
if (expanded.length > 100) {
|
||||
expanded.shift();
|
||||
@@ -581,19 +611,6 @@ class Search {
|
||||
}
|
||||
}
|
||||
|
||||
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 loadBooks(authorId) {
|
||||
try {
|
||||
let result;
|
||||
@@ -709,13 +726,20 @@ class Search {
|
||||
}
|
||||
|
||||
async getBooks(item) {
|
||||
if (item.books)
|
||||
if (item.books) {
|
||||
if (item.count > maxItemCount) {
|
||||
item.bookLoading = true;
|
||||
await utils.sleep(1);//для перерисовки списка
|
||||
item.bookLoading = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.getBooksFlag)
|
||||
this.getBooksFlag = 0;
|
||||
|
||||
this.getBooksFlag++;
|
||||
item.bookLoading = true;
|
||||
|
||||
try {
|
||||
if (this.getBooksFlag == 1) {
|
||||
@@ -736,6 +760,12 @@ class Search {
|
||||
type: 'book',
|
||||
title: book.title,
|
||||
series: book.series,
|
||||
serno: book.serno,
|
||||
genre: book.genre,
|
||||
size: book.size,
|
||||
ext: book.ext,
|
||||
|
||||
src: book,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -751,6 +781,7 @@ class Search {
|
||||
key: `${item.author}-${book.series}`,
|
||||
type: 'series',
|
||||
series: book.series,
|
||||
|
||||
books: [],
|
||||
});
|
||||
|
||||
@@ -766,22 +797,32 @@ class Search {
|
||||
//сортировка
|
||||
books.sort((a, b) => {
|
||||
if (a.type == 'series') {
|
||||
if (b.type == 'series')
|
||||
return a.key.localeCompare(b.key);
|
||||
else
|
||||
return -1;
|
||||
return (b.type == 'series' ? a.key.localeCompare(b.key) : -1);
|
||||
} else {
|
||||
if (b.type == 'book')
|
||||
return a.title.localeCompare(b.title);
|
||||
else
|
||||
return 1;
|
||||
return (b.type == 'book' ? a.title.localeCompare(b.title) : 1);
|
||||
}
|
||||
});
|
||||
|
||||
//сортировка внутри серий
|
||||
for (const book of books) {
|
||||
if (book.type == 'series') {
|
||||
book.books.sort((a, b) => {
|
||||
const dserno = (a.serno || Number.MAX_VALUE) - (b.serno || Number.MAX_VALUE);
|
||||
const dtitle = a.title.localeCompare(b.title);
|
||||
const dext = a.ext.localeCompare(b.ext);
|
||||
return (dserno ? dserno : (dtitle ? dtitle : dext));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (books.length == 1 && books[0].type == 'series' && !this.isExpandedSeries(books[0])) {
|
||||
this.expandSeries(books[0]);
|
||||
}
|
||||
|
||||
item.books = books;
|
||||
await this.$nextTick();
|
||||
} finally {
|
||||
item.bookLoading = false;
|
||||
this.getBooksFlag--;
|
||||
if (this.getBooksFlag == 0)
|
||||
this.loadingMessage2 = '';
|
||||
@@ -842,11 +883,12 @@ class Search {
|
||||
name: rec.author.replace(/,/g, ', '),
|
||||
count,
|
||||
book: false,
|
||||
bookLoading: false,
|
||||
});
|
||||
num++;
|
||||
|
||||
if (expandedSet.has(item.author)) {
|
||||
if (authors.length > 1)
|
||||
if (authors.length > 1 || item.count > maxItemCount)
|
||||
this.getBooks(item);//no await
|
||||
else
|
||||
await this.getBooks(item);
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
<template #prepend>
|
||||
<q-icon
|
||||
v-show="mmButtons"
|
||||
style="font-size: 100%"
|
||||
v-ripple="modelValue != min"
|
||||
style="font-size: 100%"
|
||||
:class="(modelValue != min ? '' : 'disable')"
|
||||
name="la la-angle-double-left"
|
||||
class="button"
|
||||
@@ -50,14 +50,13 @@
|
||||
|
||||
<q-icon
|
||||
v-show="mmButtons"
|
||||
style="font-size: 100%"
|
||||
v-ripple="modelValue != max"
|
||||
style="font-size: 100%"
|
||||
:class="(modelValue != max ? '' : 'disable')"
|
||||
name="la la-angle-double-right"
|
||||
class="button"
|
||||
@click="toMax"
|
||||
/>
|
||||
|
||||
</template>
|
||||
</q-input>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user