ChenYangfan 6 лет назад
Родитель
Сommit
cc85d6f986

+ 12 - 9
src/components/Discussion/DiscussionArea.vue

@@ -2,13 +2,13 @@
   <div class="discussion-area">
     <h1 class="sub-title vertical-center">
       本页留言板
-      <c-button theme="green" :left="12" :icon="showWriteTool ? 'unfold_less' : 'edit'" text @click="showWriteTool = !showWriteTool">
-        {{showWriteTool ? '隐藏编辑器' : '发帖'}}
+      <c-button theme="green" :left="12" :icon="focus ? 'unfold_less' : 'edit'" text @click="handleFocusButtonClick">
+        {{focus ? '隐藏编辑器' : '发帖'}}
       </c-button>
     </h1>
     <div class="discussion-area-content">
       <show-transition>
-        <write-new-comment v-show="showWriteTool" class="mb-8" ref="writeComment" @comment-submit="handleCommentSubmit"
+        <write-new-comment v-show="focus" class="mb-8" ref="writeComment" @comment-submit="handleCommentSubmit"
                            :placeholder="writingAreaPlaceholder"></write-new-comment>
       </show-transition>
       <div class="no-content-warning" v-if="comments === null">
@@ -42,6 +42,7 @@ import WebsocketPublisher from '@/server/websocket/ws'
 import { useCommentWsServer } from '@/config/server-info'
 import CButton from '@/components/Basic/CButton'
 import ShowTransition from '@/animations/ShowTransition'
+import { FOCUS_ON_INPUT, USE_FOCUS } from '@/store/types/pdf-types'
 
 export default {
   components: { ShowTransition, CButton, WriteNewComment, CComment },
@@ -49,8 +50,7 @@ export default {
     return {
       comments: null,
       wsComments: [],
-      slideId: this.$route.params.slideId,
-      showWriteTool: false
+      slideId: this.$route.params.slideId
     }
   },
   mounted () {
@@ -64,7 +64,8 @@ export default {
   computed: {
     ...mapState({
       userInfo: state => state.main.userInfo,
-      currentPage: state => state.pdf.currentPage
+      currentPage: state => state.pdf.currentPage,
+      focus: state => state.pdf.focus
     }),
     writingAreaPlaceholder () {
       return '主题'
@@ -93,9 +94,7 @@ export default {
       })
     },
     updateComments () {
-      this.getComments(30).then(() => {
-        this.getComments(10000)
-      })
+      this.getComments(1000)
     },
     getComments (size) {
       return getComments({
@@ -122,6 +121,9 @@ export default {
       }).catch(err => {
         this.$setErrorMessage(err.response.data.msg)
       })
+    },
+    handleFocusButtonClick () {
+      this.focus ? this.$store.commit(USE_FOCUS) : this.$store.commit(FOCUS_ON_INPUT)
     }
   }
 }
@@ -137,6 +139,7 @@ export default {
   min-width: 405px;
   max-height: calc(100vh - 76px);
   overflow: auto;
+  overflow-x: hidden;
   bottom: 0;
   right: 0;
   background-color: rgba(250, 250, 250, 0.8);

+ 29 - 2
src/components/Discussion/WriteNewComment.vue

@@ -1,10 +1,10 @@
 <template>
   <div class="write-new-comment">
     <label>
-      <input type="text" v-model="title" :placeholder="placeholder || '讨论主题'" maxlength="100">
+      <input ref="title" @keydown="handleTitleKey" type="text" v-model="title" :placeholder="placeholder || '讨论主题'" maxlength="100">
     </label>
     <label>
-      <textarea v-model="content" placeholder="详细内容"></textarea>
+      <textarea @keyup="handleContentKey" ref="content" v-model="content" placeholder="详细内容"></textarea>
     </label>
     <icon-button class="send-button" theme="green" @click="handleSubmitComment" :size="32">send</icon-button>
   </div>
@@ -12,10 +12,23 @@
 
 <script>
 import IconButton from '@/components/Basic/IconButton'
+import { mapState } from 'vuex'
 
 export default {
   props: ['placeholder'],
   components: { IconButton },
+  computed: {
+    ...mapState({
+      focus: state => state.pdf.focus
+    })
+  },
+  watch: {
+    focus: {
+      handler () {
+        this.focus && this.$refs.title.focus()
+      }
+    }
+  },
   data () {
     return {
       title: '',
@@ -33,6 +46,20 @@ export default {
     resetContent () {
       this.title = ''
       this.content = ''
+    },
+    handleTitleKey (e) {
+      if (this.title && !e.isComposing && e.key === 'Enter') {
+        this.$refs.content.focus()
+        e.preventDefault()
+      }
+      if (e.shiftKey && e.key === 'Enter') {
+        this.handleSubmitComment()
+      }
+    },
+    handleContentKey (e) {
+      if (e.shiftKey && !e.isComposing && e.key === 'Enter') {
+        this.handleSubmitComment()
+      }
     }
   }
 }

+ 9 - 10
src/store/modules/pdf.js

@@ -1,9 +1,10 @@
 import {
+  FOCUS_ON_INPUT,
   NEXT_PAGE,
   PREVIOUS_PAGE,
   RESET,
-  SET_CURRENT_PAGE, SET_SCREEN_SHOT, SET_SLIDE_INFO,
-  SET_SRC, SET_TOTAL_PAGES, TOGGLE_SHOW_DISCUSSION, UNSET_SLIDE_INFO, USE_SCREEN_SHOT
+  SET_CURRENT_PAGE, SET_SLIDE_INFO,
+  SET_SRC, SET_TOTAL_PAGES, TOGGLE_SHOW_DISCUSSION, UNSET_SLIDE_INFO, USE_FOCUS
 } from '@/store/types/pdf-types'
 
 export default {
@@ -13,7 +14,7 @@ export default {
     totalPages: 0,
     currentPage: 1,
     showDiscussion: false,
-    screenShot: false
+    focus: false
   },
 
   mutations: {
@@ -41,19 +42,17 @@ export default {
     [TOGGLE_SHOW_DISCUSSION] (state) {
       state.showDiscussion = !state.showDiscussion
     },
-    [SET_SCREEN_SHOT] (state) {
-      state.screenShot = true
-      // 防止没有还原导致不能截图
-      setTimeout(() => { state.screenShot = false }, 200)
+    [FOCUS_ON_INPUT] (state) {
+      state.focus = true
     },
-    [USE_SCREEN_SHOT] (state) {
-      state.screenShot = false
+    [USE_FOCUS] (state) {
+      state.focus = false
     },
     [RESET] (state) {
       state.src = ''
       state.totalPages = 0
       state.currentPage = 1
-      state.screenShot = false
+      state.focus = false
     }
   }
 }

+ 2 - 2
src/store/types/pdf-types.js

@@ -5,7 +5,7 @@ export const TOGGLE_SHOW_DISCUSSION = 'toggleShowDiscussion'
 export const RESET = 'reset'
 export const NEXT_PAGE = 'nextPage'
 export const PREVIOUS_PAGE = 'previousPage'
-export const SET_SCREEN_SHOT = 'getScreenShot'
-export const USE_SCREEN_SHOT = 'useScreenShot'
 export const SET_SLIDE_INFO = 'setSlideInfo'
 export const UNSET_SLIDE_INFO = 'unsetSlideInfo'
+export const FOCUS_ON_INPUT = 'focusOnInput'
+export const USE_FOCUS = 'useFocus'

+ 25 - 11
src/views/reader/PdfReader.vue

@@ -14,7 +14,7 @@ import PdfViewer from '@/components/PDF/PdfViewer'
 import { mapState } from 'vuex'
 import DiscussionArea from '@/components/Discussion/DiscussionArea'
 import { getSlideInfo, getSlideUrl } from '@/server/slide'
-import { NEXT_PAGE, PREVIOUS_PAGE, RESET, SET_SRC } from '@/store/types/pdf-types'
+import { FOCUS_ON_INPUT, NEXT_PAGE, PREVIOUS_PAGE, RESET, SET_SRC, USE_FOCUS } from '@/store/types/pdf-types'
 import IconButton from '@/components/Basic/IconButton'
 
 export default {
@@ -22,7 +22,8 @@ export default {
   computed: {
     ...mapState({
       src: state => state.pdf.src,
-      showDiscussion: state => state.pdf.showDiscussion
+      showDiscussion: state => state.pdf.showDiscussion,
+      focus: state => state.pdf.focus
     })
   },
   data () {
@@ -45,17 +46,30 @@ export default {
     })
     window.addEventListener('keydown', this.handleKey)
   },
+  beforeDestroy () {
+    window.removeEventListener('keydown', this.handleKey)
+  },
   methods: {
     handleKey (e) {
-      switch (e.key) {
-        case 'ArrowDown':
-        case 'ArrowRight':
-          this.$store.commit(NEXT_PAGE)
-          break
-        case 'ArrowUp':
-        case 'ArrowLeft':
-          this.$store.commit(PREVIOUS_PAGE)
-          break
+      if (e.key === 'Enter') {
+        !this.focus && this.$store.commit(FOCUS_ON_INPUT)
+        return
+      }
+      if (e.key === 'Escape') {
+        this.focus && this.$store.commit(USE_FOCUS)
+        return
+      }
+      if (!this.focus) {
+        switch (e.key) {
+          case 'ArrowDown':
+          case 'ArrowRight':
+            this.$store.commit(NEXT_PAGE)
+            break
+          case 'ArrowUp':
+          case 'ArrowLeft':
+            this.$store.commit(PREVIOUS_PAGE)
+            break
+        }
       }
     }
   }