Forráskód Böngészése

Работа над BookInfoDialog

Book Pauk 2 éve
szülő
commit
391fb3aa70

+ 163 - 15
client/components/Search/BookInfoDialog/BookInfoDialog.vue

@@ -9,9 +9,57 @@
         </template>
 
         <div ref="box" class="fit column q-mt-xs overflow-auto no-wrap" style="padding: 0px 10px 10px 10px;">
-            <div class="row" style="height: 300px">
-                <div style="height: 300px">
-                    <img v-if="coverSrc" :src="coverSrc" style="height: 100%;" />
+            <div class="text-green-10">
+                {{ bookAuthor }}
+            </div>
+            <div>
+                <b>{{ book.title }}</b>
+            </div>
+
+            <div class="row q-mt-sm no-wrap">
+                <div class="column justify-center" style="height: 300px; width: 200px;">
+                    <img v-if="coverSrc" :src="coverSrc" class="fit row justify-center items-center" style="object-fit: contain" @error="coverSrc = ''" />
+                    <div v-if="!coverSrc" class="fit row justify-center items-center text-grey-5" style="border: 1px solid #ccc; font-size: 300%">
+                        <i>{{ book.ext }}</i>
+                    </div>
+                </div>
+
+                <div class="col column q-ml-sm" style="min-width: 300px; border: 1px solid #ccc">
+                    <div class="bg-grey-3 row">
+                        <q-tabs
+                            v-model="selectedTab"
+                            active-color="black"
+                            active-bg-color="white"
+                            indicator-color="white"
+                            dense
+                            no-caps
+                            inline-label
+                            class="bg-grey-4 text-grey-7"
+                        >
+                            <q-tab name="fb2" label="Fb2 инфо" />
+                            <q-tab name="inpx" label="Inpx инфо" />
+                        </q-tabs>
+                    </div>
+
+                    <div class="overflow-auto full-width" style="height: 262px">
+                        <div v-for="item in info" :key="item.name">
+                            <div class="row q-ml-sm q-mt-sm items-center">
+                                <div class="text-blue" style="font-size: 90%">
+                                    {{ item.label }}
+                                </div>
+                                <div class="col q-mx-xs" style="height: 0px; border-top: 1px solid #ccc" />
+                            </div>
+
+                            <div v-for="subItem in item.value" :key="subItem.name" class="row q-ml-md">
+                                <div style="width: 110px">
+                                    {{ subItem.label }}
+                                </div>
+                                <div class="q-ml-sm">
+                                    {{ subItem.value }}
+                                </div>
+                            </div>
+                        </div>
+                    </div>
                 </div>
             </div>
 
@@ -40,13 +88,12 @@ const componentOptions = {
     watch: {
         modelValue(newValue) {
             this.dialogVisible = newValue;
+            if (newValue)
+                this.init();
         },
         dialogVisible(newValue) {
             this.$emit('update:modelValue', newValue);
         },
-        bookInfo() {
-            this.parseBookInfo();
-        }
     }
 };
 class BookInfoDialog {
@@ -57,28 +104,125 @@ class BookInfoDialog {
     };
 
     dialogVisible = false;
+    selectedTab = 'fb2';
 
     //info props
     coverSrc = '';
     annotation = '';
-    info = [];
+    fb2 = [];
+    book = {};
 
     created() {
         this.commit = this.$store.commit;
-        this.parseBookInfo();
     }
 
     mounted() {
     }
 
-    parseBookInfo() {
-        const bookInfo = this.bookInfo;
-        const parser = new Fb2Parser();
-
+    init() {
         //defaults
         this.coverSrc = '';
         this.annotation = '';
-        this.info = [];
+        this.fb2 = [];
+        this.book = {};
+
+        this.parseBookInfo();
+    }
+
+    get bookAuthor() {
+        if (this.book.author) {
+            let a = this.book.author.split(',');
+            return a.slice(0, 3).join(', ') + (a.length > 3 ? ' и др.' : '');
+        }
+
+        return '';
+    }
+
+    get inpx() {
+        const mapping = [
+            {name: 'fileInfo', label: 'Информация о файле', value: [
+                {name: 'folder', label: 'Папка'},
+                {name: 'file', label: 'Файл'},
+                {name: 'size', label: 'Размер'},
+                {name: 'date', label: 'Добавлен'},
+            ]},
+        ];
+/*
+                {name: 'author', label: 'Автор(ы)'},
+                {name: 'bookTitle', label: 'Название'},
+                {name: 'sequenceName', label: 'Серия'},
+                {name: 'sequenceNum', label: 'Номер в серии'},
+                {name: 'genre', label: 'Жанр'},
+
+                {name: 'date', label: 'Дата'},
+                {name: 'lang', label: 'Язык книги'},
+                {name: 'srcLang', label: 'Язык оригинала'},
+                {name: 'translator', label: 'Переводчик(и)'},
+                {name: 'keywords', label: 'Ключевые слова'},
+
+
+        {"author":"Грант Максвелл",
+         "genre":"det_hard",
+         "title":"Tower of Death",
+         "series":"The Shadow[a]",
+         "serno":53,
+         "file":"641310",
+         "size":420422,
+         "libid":"641310",
+         "del":0,
+         "ext":"fb2",
+         "date":"2021-11-04",
+         "insno":181,
+         "folder":"f.fb2-641019-643928.zip",
+         "lang":"en",
+         "librate":0,
+         "keywords":"Hard-Boiled, Pulp Fiction,det",
+*/
+        const valueToString = (value, nodePath) => {//eslint-disable-line no-unused-vars
+            if (typeof(value) === 'string') {
+                return value;
+            }
+
+            return value;
+        };
+
+        let result = [];
+        for (const item of mapping) {
+            const itemOut = {name: item.name, label: item.label, value: []};
+
+            for (const subItem of item.value) {
+                const subItemOut = {
+                    name: subItem.name,
+                    label: subItem.label,
+                    value: valueToString(this.book[subItem.name], `${item.name}/${subItem.name}`)
+                };
+                if (subItemOut.value)
+                    itemOut.value.push(subItemOut);
+            }
+
+            if (itemOut.value.length)
+                result.push(itemOut);
+        }
+
+        return result;
+    }
+
+    get info() {
+        let result = [];
+
+        switch (this.selectedTab) {
+            case 'fb2':
+                return this.fb2;
+            case 'inpx':
+                return this.inpx;
+        }
+
+        return result;
+    }
+
+    parseBookInfo() {
+        const bookInfo = this.bookInfo;
+        const parser = new Fb2Parser();
 
         //cover
         if (bookInfo.cover)
@@ -86,10 +230,10 @@ class BookInfoDialog {
 
         //fb2
         if (bookInfo.fb2) {
-            this.info = parser.bookInfoList(bookInfo.fb2);
+            this.fb2 = parser.bookInfoList(bookInfo.fb2);
             
             const infoObj = parser.bookInfo(bookInfo.fb2);
-            if (infoObj) {
+            if (infoObj.titleInfo) {
                 let ann = infoObj.titleInfo.annotationHtml;
                 if (ann) {
                     ann = ann.replace(/<p>/g, `<p class="p-annotation">`);
@@ -97,6 +241,10 @@ class BookInfoDialog {
                 }
             }
         }
+
+        //book
+        if (bookInfo.book)
+            this.book = bookInfo.book;
     }
 
     okClick() {

+ 2 - 2
client/quasar.js

@@ -17,7 +17,7 @@ import {QBtn} from 'quasar/src/components/btn';
 import {QBtnToggle} from 'quasar/src/components/btn-toggle';
 import {QIcon} from 'quasar/src/components/icon';
 //import {QSlider} from 'quasar/src/components/slider';
-//import {QTabs, QTab} from 'quasar/src/components/tabs';
+import {QTabs, QTab} from 'quasar/src/components/tabs';
 //import {QTabPanels, QTabPanel} from 'quasar/src/components/tab-panels';
 //import {QSeparator} from 'quasar/src/components/separator';
 //import {QList} from 'quasar/src/components/item';
@@ -52,7 +52,7 @@ const components = {
     QBtnToggle,
     QIcon,
     //QSlider,
-    //QTabs, QTab,
+    QTabs, QTab,
     //QTabPanels, QTabPanel,
     //QSeparator,
     //QList,

+ 12 - 8
server/core/fb2/Fb2Parser.js

@@ -79,10 +79,10 @@ class Fb2Parser extends XmlParser {
 
             info.translator = parseAuthors('translator');
 
-            const seqAttrs = titleInfo.attrs('sequence') || new Map();
-            info.sequenceName = seqAttrs.get('name') || null;
-            info.sequenceNum = seqAttrs.get('number') || null;
-            info.sequenceLang = seqAttrs.get('xml:lang') || null;
+            const seqAttrs = titleInfo.attrs('sequence') || {};
+            info.sequenceName = seqAttrs['name'] || null;
+            info.sequenceNum = seqAttrs['number'] || null;
+            info.sequenceLang = seqAttrs['xml:lang'] || null;
 
             result.titleInfo = info;
         }
@@ -141,12 +141,16 @@ class Fb2Parser extends XmlParser {
                 continue;
 
             for (const subItem of item.value) {
-                if (info[subItem.name] !== null)
-                    itemOut.value.push({
+                if (info[subItem.name] !== null) {
+                    const subItemOut = {
                         name: subItem.name,
                         label: subItem.label,
-                        value: valueToString(info[subItem.name])
-                    });
+                        value: valueToString(info[subItem.name], `${item.name}/${subItem.name}`)
+                    };
+
+                    if (subItemOut.value)
+                        itemOut.value.push(subItemOut);
+                }
             }
 
             if (itemOut.value.length)