Начало добавления группировки в RecentBooksPage
This commit is contained in:
@@ -9,7 +9,62 @@
|
|||||||
|
|
||||||
<a ref="download" style="display: none;" target="_blank"></a>
|
<a ref="download" style="display: none;" target="_blank"></a>
|
||||||
|
|
||||||
<q-table
|
<div id="vs-container" ref="vsContainer" class="recent-books-scroll col">
|
||||||
|
<div ref="header" class="scroll-header bg-blue-2">
|
||||||
|
<q-input
|
||||||
|
ref="input" v-model="search"
|
||||||
|
outlined rounded dense
|
||||||
|
style="position: relative; top: 5px; left: 200px; width: 350px" bg-color="white"
|
||||||
|
placeholder="Найти"
|
||||||
|
@click.stop
|
||||||
|
>
|
||||||
|
<template #append>
|
||||||
|
<q-icon v-if="search !== ''" name="la la-times" class="cursor-pointer" @click.stop="resetSearch" />
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<q-virtual-scroll
|
||||||
|
v-slot="{ item, index }"
|
||||||
|
:items="tableData"
|
||||||
|
scroll-target="#vs-container"
|
||||||
|
virtual-scroll-item-size="80"
|
||||||
|
@virtual-scroll="onScroll"
|
||||||
|
>
|
||||||
|
<div class="table-row row" :class="{even: index % 2 > 0, 'active-book': item.active}">
|
||||||
|
<div class="row-part row justify-center items-center" style="width: 80px">
|
||||||
|
{{ index }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row-part column items-stretch break-word clickable" style="width: 350px; font-size: 80%" @click="loadBook(item)">
|
||||||
|
<div class="column col">
|
||||||
|
<div style="color: green">
|
||||||
|
{{ item.desc.author }}
|
||||||
|
</div>
|
||||||
|
<div>{{ item.desc.title }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="read-bar" :style="`width: ${340*item.readPart}px`"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row-part column justify-center" style="width: 80px; font-size: 80%">
|
||||||
|
<a v-show="isUrl(item.url)" :href="item.url" target="_blank">Оригинал</a><br>
|
||||||
|
<a :href="item.path" @click.prevent="downloadBook(item.path, item.fullTitle)">Скачать FB2</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row-part column justify-center">
|
||||||
|
<q-btn
|
||||||
|
dense
|
||||||
|
style="width: 30px; height: 30px; padding: 7px 0 7px 0; margin-left: 4px"
|
||||||
|
@click="handleDel(item.key)"
|
||||||
|
>
|
||||||
|
<q-icon class="la la-times" size="14px" />
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-virtual-scroll>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--q-table
|
||||||
class="recent-books-table col"
|
class="recent-books-table col"
|
||||||
:rows="tableData"
|
:rows="tableData"
|
||||||
row-key="key"
|
row-key="key"
|
||||||
@@ -91,7 +146,7 @@
|
|||||||
</q-td>
|
</q-td>
|
||||||
</q-tr>
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
</q-table>
|
</q-table-->
|
||||||
</Window>
|
</Window>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -103,6 +158,7 @@ import path from 'path-browserify';
|
|||||||
//import _ from 'lodash';
|
//import _ from 'lodash';
|
||||||
|
|
||||||
import * as utils from '../../../share/utils';
|
import * as utils from '../../../share/utils';
|
||||||
|
import LockQueue from '../../../share/LockQueue';
|
||||||
import Window from '../../share/Window.vue';
|
import Window from '../../share/Window.vue';
|
||||||
import bookManager from '../share/bookManager';
|
import bookManager from '../share/bookManager';
|
||||||
import readerApi from '../../../api/reader';
|
import readerApi from '../../../api/reader';
|
||||||
@@ -127,10 +183,14 @@ class RecentBooksPage {
|
|||||||
pagination = {};
|
pagination = {};
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
this.firstInit = true;
|
this.lastScrollTop1 = 0;
|
||||||
this.pagination = {rowsPerPage: 0};
|
this.lastScrollTop2 = 0;
|
||||||
|
|
||||||
this.columns = [
|
this.lock = new LockQueue(100);
|
||||||
|
|
||||||
|
//this.pagination = {rowsPerPage: 0};
|
||||||
|
|
||||||
|
/*this.columns = [
|
||||||
{
|
{
|
||||||
name: 'num',
|
name: 'num',
|
||||||
label: '#',
|
label: '#',
|
||||||
@@ -168,7 +228,7 @@ class RecentBooksPage {
|
|||||||
label: '',
|
label: '',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
},
|
},
|
||||||
];
|
];*/
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
@@ -177,28 +237,84 @@ class RecentBooksPage {
|
|||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
//this.$refs.input.focus();//плохо на планшетах
|
//this.$refs.input.focus();//плохо на планшетах
|
||||||
});
|
});
|
||||||
(async() => {//подгрузка списка
|
|
||||||
if (this.initing)
|
|
||||||
return;
|
|
||||||
this.initing = true;
|
|
||||||
|
|
||||||
if (this.firstInit) {//для отзывчивости
|
this.updateTableData();//no await
|
||||||
await this.updateTableData(20);
|
|
||||||
this.firstInit = false;
|
|
||||||
}
|
|
||||||
await utils.sleep(50);
|
|
||||||
await this.updateTableData();
|
|
||||||
|
|
||||||
this.initing = false;
|
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateTableData(limit) {
|
async updateTableData() {
|
||||||
|
await this.lock.get();
|
||||||
|
try {
|
||||||
|
let result = [];
|
||||||
|
|
||||||
|
const sorted = bookManager.getSortedRecent();
|
||||||
|
const activeBook = bookManager.mostRecentBook();
|
||||||
|
|
||||||
|
let num = 0;
|
||||||
|
for (const book of sorted) {
|
||||||
|
if (book.deleted)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
num++;
|
||||||
|
|
||||||
|
let d = new Date();
|
||||||
|
d.setTime(book.touchTime);
|
||||||
|
const touchTime = utils.formatDate(d);
|
||||||
|
|
||||||
|
let readPart = 0;
|
||||||
|
let perc = '';
|
||||||
|
let textLen = '';
|
||||||
|
const p = (book.bookPosSeen ? book.bookPosSeen : (book.bookPos ? book.bookPos : 0));
|
||||||
|
if (book.textLength) {
|
||||||
|
readPart = p/book.textLength;
|
||||||
|
perc = ` [${(readPart*100).toFixed(2)}%]`;
|
||||||
|
textLen = ` ${Math.round(book.textLength/1000)}k`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bt = utils.getBookTitle(book.fb2);
|
||||||
|
|
||||||
|
let title = bt.bookTitle;
|
||||||
|
title = (title ? `"${title}"`: '');
|
||||||
|
const author = (bt.author ? bt.author : (bt.bookTitle ? bt.bookTitle : (book.uploadFileName ? book.uploadFileName : book.url)));
|
||||||
|
|
||||||
|
result.push({
|
||||||
|
num,
|
||||||
|
touchTime,
|
||||||
|
desc: {
|
||||||
|
author,
|
||||||
|
title: `${title}${perc}${textLen}`,
|
||||||
|
},
|
||||||
|
readPart,
|
||||||
|
url: book.url,
|
||||||
|
path: book.path,
|
||||||
|
fullTitle: bt.fullTitle,
|
||||||
|
key: book.key,
|
||||||
|
active: (activeBook.key == book.key),
|
||||||
|
|
||||||
|
//для сортировки
|
||||||
|
touchTimeRaw: book.touchTime,
|
||||||
|
descString: `${author}${title}${perc}${textLen}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const search = this.search;
|
||||||
|
result = result.filter(item => {
|
||||||
|
return !search ||
|
||||||
|
item.touchTime.includes(search) ||
|
||||||
|
item.desc.title.toLowerCase().includes(search.toLowerCase()) ||
|
||||||
|
item.desc.author.toLowerCase().includes(search.toLowerCase())
|
||||||
|
});
|
||||||
|
|
||||||
|
this.tableData = result;
|
||||||
|
} finally {
|
||||||
|
this.lock.ret();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*async updateTableData(limit) {
|
||||||
while (this.updating) await utils.sleep(100);
|
while (this.updating) await utils.sleep(100);
|
||||||
this.updating = true;
|
this.updating = true;
|
||||||
let result = [];
|
let result = [];
|
||||||
|
|
||||||
this.loading = !!limit;
|
|
||||||
const sorted = bookManager.getSortedRecent();
|
const sorted = bookManager.getSortedRecent();
|
||||||
|
|
||||||
let num = 0;
|
let num = 0;
|
||||||
@@ -260,7 +376,7 @@ class RecentBooksPage {
|
|||||||
|
|
||||||
this.tableData = result;
|
this.tableData = result;
|
||||||
this.updating = false;
|
this.updating = false;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
resetSearch() {
|
resetSearch() {
|
||||||
this.search = '';
|
this.search = '';
|
||||||
@@ -324,6 +440,24 @@ class RecentBooksPage {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onScroll() {
|
||||||
|
const curScrollTop = this.$refs.vsContainer.scrollTop;
|
||||||
|
|
||||||
|
if (curScrollTop - this.lastScrollTop1 > 150) {
|
||||||
|
this.$refs.header.style.top = `-${this.$refs.header.offsetHeight}px`;
|
||||||
|
this.$refs.header.style.transition = 'top 0.2s ease 0s';
|
||||||
|
|
||||||
|
this.lastScrollTop1 = curScrollTop;
|
||||||
|
} else if (curScrollTop - this.lastScrollTop2 < 0) {
|
||||||
|
this.$refs.header.style.position = 'sticky';
|
||||||
|
this.$refs.header.style.top = 0;
|
||||||
|
|
||||||
|
this.lastScrollTop1 = curScrollTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastScrollTop2 = curScrollTop;
|
||||||
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.$emit('recent-books-close');
|
this.$emit('recent-books-close');
|
||||||
}
|
}
|
||||||
@@ -341,31 +475,34 @@ export default vueComponent(RecentBooksPage);
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.recent-books-table {
|
.recent-books-scroll {
|
||||||
width: 573px;
|
width: 573px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scroll-header {
|
||||||
|
height: 50px;
|
||||||
|
position: sticky;
|
||||||
|
z-index: 1;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
min-height: 80px;
|
||||||
|
border-bottom: 1px solid #cccccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-part {
|
||||||
|
padding: 4px 4px 4px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.clickable {
|
.clickable {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.td-mp {
|
|
||||||
margin: 0 !important;
|
|
||||||
padding: 4px 4px 4px 4px !important;
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-mp {
|
|
||||||
margin: 0 !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
border: 0;
|
|
||||||
border-left: 1px solid #ddd !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.break-word {
|
.break-word {
|
||||||
line-height: 180%;
|
line-height: 150%;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
@@ -375,21 +512,12 @@ export default vueComponent(RecentBooksPage);
|
|||||||
height: 3px;
|
height: 3px;
|
||||||
background-color: #aaaaaa;
|
background-color: #aaaaaa;
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
|
|
||||||
<style>
|
.even {
|
||||||
.recent-books-table .q-table__middle {
|
background-color: #f0f0f0;
|
||||||
height: 100%;
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.recent-books-table thead tr:first-child th {
|
.active-book {
|
||||||
position: sticky;
|
background-color: #b0f0b0 !important;
|
||||||
z-index: 1;
|
|
||||||
top: 0;
|
|
||||||
background-color: #c1f4cd;
|
|
||||||
}
|
|
||||||
.recent-books-table tr:nth-child(even) {
|
|
||||||
background-color: #f8f8f8;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ import {QPopupProxy} from 'quasar/src/components/popup-proxy';
|
|||||||
import {QDialog} from 'quasar/src/components/dialog';
|
import {QDialog} from 'quasar/src/components/dialog';
|
||||||
import {QChip} from 'quasar/src/components/chip';
|
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';
|
//import {QExpansionItem} from 'quasar/src/components/expansion-item';
|
||||||
|
|
||||||
const components = {
|
const components = {
|
||||||
@@ -62,6 +64,7 @@ const components = {
|
|||||||
QChip,
|
QChip,
|
||||||
QTree,
|
QTree,
|
||||||
//QExpansionItem,
|
//QExpansionItem,
|
||||||
|
QVirtualScroll,
|
||||||
};
|
};
|
||||||
|
|
||||||
//directives
|
//directives
|
||||||
|
|||||||
Reference in New Issue
Block a user