Просмотр исходного кода

web: 修复快捷键设置bug和esc键逻辑; 修复超大章节列表造成的卡顿

bug: 第一点击目录时没有跳转到合适位置
Xwite 3 лет назад
Родитель
Сommit
23018b702d

+ 1 - 0
modules/web/src/components.d.ts

@@ -10,6 +10,7 @@ export {}
 declare module '@vue/runtime-core' {
   export interface GlobalComponents {
     BookItems: typeof import('./components/BookItems.vue')['default']
+    CatalogItem: typeof import('./components/CatalogItem.vue')['default']
     ChapterContent: typeof import('./components/ChapterContent.vue')['default']
     ElButton: typeof import('element-plus/es')['ElButton']
     ElCheckbox: typeof import('element-plus/es')['ElCheckbox']

+ 1 - 2
modules/web/src/components/ChapterContent.vue

@@ -44,9 +44,8 @@ const calculateWordCount = (paragraph) => {
   return paragraph.replaceAll(imgPattern, imagePlaceHolder).length;
 };
 const wordCounts = computed(() => {
-  return Array.from(props.contents, content => calculateWordCount(content));
+  return Array.from(props.contents, (content) => calculateWordCount(content));
 });
-
 </script>
 
 <style lang="scss" scoped>

+ 38 - 67
modules/web/src/components/PopCatalog.vue

@@ -1,64 +1,55 @@
 <template>
   <div class="cata-wrapper" :style="popupTheme">
     <div class="title">目录</div>
-    <div
-      class="data-wrapper"
-      ref="cataData"
+    <virtual-list
+      style="height: 300px; overflow: auto"
       :class="{ night: isNight, day: !isNight }"
-    >
-      <div class="cata">
-        <div
-          class="log"
-          v-for="(note, index) in catalog"
-          :class="{ selected: isSelected(index) }"
-          :key="note.durChapterIndex"
-          @click="gotoChapter(note)"
-          ref="cata"
-        >
-          <div class="log-text">
-            {{ note.title }}
-          </div>
-        </div>
-      </div>
-    </div>
+      ref="virtualListRef"
+      :data-key="'index'"
+      :start="index"
+      wrap-class="data-wrapper"
+      item-class="cata"
+      :data-sources="catalog"
+      :data-component="CatalogItem"
+      :estimate-size="40"
+      :extra-props="{ gotoChapter }"
+    />
   </div>
 </template>
 
 <script setup>
+import VirtualList from "vue3-virtual-scroll-list";
 import jump from "../plugins/jump";
 import settings from "../plugins/config";
 import "../assets/fonts/popfont.css";
+import CatalogItem from "./CatalogItem.vue";
+
 const store = useBookStore();
 
-const isNight = ref(false);
-const { index } = toRefs(store.readingBook);
+const isNight = computed(() => theme.value == 6);
 const { catalog, popCataVisible } = storeToRefs(store);
 
 const theme = computed(() => {
   return store.config.theme;
 });
-
 const popupTheme = computed(() => {
   return {
     background: settings.themes[theme.value].popup,
   };
 });
-watchEffect(() => {
-  isNight.value = theme.value == 6;
-});
 
-const cata = ref();
-const cataData = ref();
-watch(popCataVisible, () => {
+const index = computed({
+  get: () => store.readingBook.index,
+  set: (value) => (store.readingBook.index = value),
+});
+const virtualListRef = ref();
+watch(popCataVisible, (visible) => {
+  if (!visible) return;
   nextTick(() => {
-    let wrapper = cataData.value;
-    jump(cata.value[index.value], { container: wrapper, duration: 0 });
+    virtualListRef.value.scrollToIndex(index.value);
   });
 });
 
-const isSelected = (idx) => {
-  return idx == index.value;
-};
 const emit = defineEmits(["getContent"]);
 const gotoChapter = (note) => {
   index.value = catalog.value.indexOf(note);
@@ -83,55 +74,35 @@ const gotoChapter = (note) => {
     width: fit-content;
     border-bottom: 1px solid #ed4259;
   }
-
-  .data-wrapper {
-    height: 300px;
-    overflow: auto;
-
+  :deep(.data-wrapper) {
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+    justify-content: space-between;
     .cata {
-      display: flex;
-      flex-direction: row;
-      flex-wrap: wrap;
-      justify-content: space-between;
-
-      .selected {
-        color: #eb4259;
-      }
-
-      .log {
-        width: 50%;
-        height: 40px;
-        cursor: pointer;
-        float: left;
-        font: 16px / 40px PingFangSC-Regular, HelveticaNeue-Light,
-          "Helvetica Neue Light", "Microsoft YaHei", sans-serif;
-
-        .log-text {
-          margin-right: 26px;
-          overflow: hidden;
-          white-space: nowrap;
-          text-overflow: ellipsis;
-        }
-      }
+      width: 50%;
+      height: 40px;
+      cursor: pointer;
+      font: 16px / 40px PingFangSC-Regular, HelveticaNeue-Light,
+        "Helvetica Neue Light", "Microsoft YaHei", sans-serif;
     }
   }
 
   .night {
-    :deep(.log) {
+    :deep(.cata) {
       border-bottom: 1px solid #666;
     }
   }
 
   .day {
-    :deep(.log) {
+    :deep(.cata) {
       border-bottom: 1px solid #f2f2f2;
     }
   }
 }
-
 @media screen and (max-width: 500px) {
-  .cata-wrapper .data-wrapper .cata .log {
-    width: 100%;
+  :deep(.cata) {
+    width: 100% !important;
   }
 }
 </style>

+ 22 - 12
modules/web/src/components/ToolBar.vue

@@ -221,21 +221,31 @@ const recordKeyDowning = ref(false);
 const recordKeyDownIndex = ref(-1);
 
 const stopRecordKeyDown = () => {
+  if (!recordKeyDowning.value) {
+    hotkeysDialogVisible.value = false;
+  }
   recordKeyDowning.value = false;
 };
 
-watch(hotkeysDialogVisible, (visibale) => {
-  if (!visibale) return hotkeys.unbind("*");
-  hotkeys.unbind();
-  /**监听按键 */
-  hotkeys("*", (event) => {
-    event.preventDefault();
-    if (recordKeyDowning.value && recordKeyDownIndex.value > -1)
-      buttons.value[recordKeyDownIndex.value].hotKeys =
-        // @ts-ignore
-        hotkeys.getPressedKeyString();
-  });
-});
+watch(
+  hotkeysDialogVisible,
+  (visibale) => {
+    if (!visibale) return hotkeys.unbind("*");
+    hotkeys.unbind();
+    /**监听按键 */
+    hotkeys("*", (event) => {
+      event.preventDefault();
+      let pressedKeys = hotkeys.getPressedKeyString();
+      if (pressedKeys.length == 1 && pressedKeys[0] == "esc") {
+        //单独按下esc 不录入
+        return;
+      }
+      if (recordKeyDowning.value && recordKeyDownIndex.value > -1)
+        buttons.value[recordKeyDownIndex.value].hotKeys = pressedKeys;
+    });
+  },
+  { immediate: true }
+);
 
 const recordKeyDown = (index) => {
   recordKeyDowning.value = true;

+ 2 - 3
modules/web/src/views/BookChapter.vue

@@ -148,7 +148,6 @@ const {
   config,
   readingBook,
 } = storeToRefs(store);
-
 const chapterPos = computed({
   get: () => readingBook.value.chapterPos,
   set: (value) => (readingBook.value.chapterPos = value),
@@ -293,9 +292,9 @@ const toChapterPos = (pos) => {
     let wordCount = 0;
     if (chapter.value.length != 1) return;
     for (let element of chapter.value[0].children) {
-      wordCount += parseInt(element.getAttribute("wordCount")) + 1;//计算换行符
+      wordCount += parseInt(element.getAttribute("wordCount")) + 1; //计算换行符
       if (wordCount - 1 >= pos) {
-      //最后一段没有换行符
+        //最后一段没有换行符
         jump(element, {
           duration: 0,
         });