Browse Source

feat: 增加@智能体滚动加载

sunxiao 7 months ago
parent
commit
f9c3c227af
4 changed files with 47 additions and 18 deletions
  1. 4 4
      package-lock.json
  2. 1 1
      package.json
  3. 40 10
      src/components/Chat/ChatInputCopy.vue
  4. 2 3
      src/components/Layout/TheSubMenu.vue

+ 4 - 4
package-lock.json

@@ -19,7 +19,7 @@
         "markdown-it-link-attributes": "^4.0.1",
         "markdown-it-math": "^4.1.1",
         "markdown-it-texmath": "^1.0.0",
-        "naive-ui": "^2.38.2",
+        "naive-ui": "^2.39.0",
         "pinia": "^2.1.7",
         "pinia-plugin-persistedstate": "^3.2.1",
         "sass": "^1.77.1",
@@ -5063,9 +5063,9 @@
       }
     },
     "node_modules/naive-ui": {
-      "version": "2.38.2",
-      "resolved": "https://registry.npmmirror.com/naive-ui/-/naive-ui-2.38.2.tgz",
-      "integrity": "sha512-WhZ+6DW61aYSmFyfH7evcSGFmd2xR68Yq1mNRrVdJwBhZsnNdAUsMN9IeNCVEPMCND/jzYZghkStoNoR5Xa09g==",
+      "version": "2.39.0",
+      "resolved": "https://registry.npmmirror.com/naive-ui/-/naive-ui-2.39.0.tgz",
+      "integrity": "sha512-5oUJzRG+rtLSH8eRU+fJvVYiQids2BxF9jp+fwGoAqHOptEINrBlgBu9uy+95RHE5FLJ7Q/z41o+qkoGnUrKxQ==",
       "dependencies": {
         "@css-render/plugin-bem": "^0.15.12",
         "@css-render/vue3-ssr": "^0.15.12",

+ 1 - 1
package.json

@@ -26,7 +26,7 @@
     "markdown-it-link-attributes": "^4.0.1",
     "markdown-it-math": "^4.1.1",
     "markdown-it-texmath": "^1.0.0",
-    "naive-ui": "^2.38.2",
+    "naive-ui": "^2.39.0",
     "pinia": "^2.1.7",
     "pinia-plugin-persistedstate": "^3.2.1",
     "sass": "^1.77.1",

+ 40 - 10
src/components/Chat/ChatInputCopy.vue

@@ -15,6 +15,8 @@ const props = defineProps({
 
 const emit = defineEmits(['onClick', 'onEnter']);
 
+const MAX_NUM = 5;
+
 const modelLoading = defineModel('loading');
 const switchStatus = defineModel('switch');
 
@@ -31,6 +33,7 @@ const helperList = ref([]);
 
 const popoverTriggerRef = ref(null);
 const popoverInnerRef = ref(null);
+const scrollRef = ref(null);
 
 const agentOptions = computed(() => helperList.value.filter(({ tools }) => tools));
 
@@ -50,7 +53,6 @@ watch(inpVal, (curVal) => {
   } else {
     isOpen.value = false;
   }
-  // isOpen.value = (curVal === "@" && curVal.length === 1);
 })
 
 watch(() => props.activeItem, (curVal) => {
@@ -64,7 +66,6 @@ const handleInpFocus = () => {
 const commonEmitEvent = (eventName) => {
   const val = unref(inpVal);
   const len = val.trim().length;
-
   if ( !len ) {
     return message.warning('请输入您的问题或需求');
   }
@@ -77,8 +78,7 @@ const commonEmitEvent = (eventName) => {
     return message.warning('当前对话进行中');
   }
 
-  // emit(eventName, val);
-  emit(eventName, {question: val, selectedOption: selectedOption.value || {}});
+  emit(eventName, { question: val, selectedOption: selectedOption.value || {} });
 
   inpVal.value = '';
 }
@@ -101,20 +101,53 @@ const clearInpVal = () => {
   inpVal.value = '';
 }
 
+// 键盘上键无限滚动
+const scrollKeyUp = (index) => {
+  const itemLength = agentOptions.value.length;
+  if ( itemLength - MAX_NUM > index ) {
+    scrollRef.value.scrollBy({
+      top: -40 ,
+      behavior: 'smooth'
+    })
+  }
+  if ( index == itemLength - 1 ) {
+    scrollRef.value.scrollTo({
+      top: itemLength * 40,
+      behavior: 'smooth'
+    })
+  }
+}
+
+// 键盘下键无限滚动
+const scrollKeyDown = (index) => {
+  if ( index >= MAX_NUM ) {
+    scrollRef.value.scrollBy({
+      top: 40,
+      behavior: 'smooth'
+    })
+  } 
+  if ( index == 0 ) {
+    scrollRef.value.scrollTo({
+      top: 0,
+      behavior: 'smooth'
+    })
+  }
+}
+
 // 键盘事件
 const handleKeyDown = (event) => {
   const len = unref(agentOptions).length;
-
   if ( !isOpen.value ) return;
-
   switch (event.key) {
     case 'ArrowUp':
       event.preventDefault();
       highlightedIndex.value = (unref(highlightedIndex) - 1 + len) % len;
+      scrollKeyUp(unref(highlightedIndex), 1)
       break;
     case 'ArrowDown':
       event.preventDefault();
       highlightedIndex.value = (unref(highlightedIndex) + 1) % len;
+      scrollKeyDown(unref(highlightedIndex))
       break;
     case 'Enter':
       event.preventDefault();
@@ -138,10 +171,7 @@ const selectOption = (index) => {
   selectedOption.value = agentOptions.value[index];
   highlightedIndex.value = index;
   isOpen.value = false;
- 
   inpVal.value = selectedOption.value.content;
-
-  // clearInpVal();
 }
 
 onMounted(async () => {
@@ -228,7 +258,7 @@ defineExpose({
           <SvgIcon name="chat-icon-close-btn"></SvgIcon>
         </p>
       </div>
-      <NScrollbar style="max-height: 240px;">
+      <NScrollbar style="max-height: 200px;" ref="scrollRef" trigger="none">
         <div class="item" v-for="item, index in agentOptions" :class="['item', { active: highlightedIndex === index }]" @click="selectOption(index)">
           <p class="icon">
             <img :src="item.banner" alt="">

+ 2 - 3
src/components/Layout/TheSubMenu.vue

@@ -49,7 +49,7 @@ defineExpose({ scrollToTop });
     </div>
 
     <div class="sub-menu-main w-full h-full" >
-      <NInfiniteScroll class="h-full" :distance="10" @load="handleLoadMore" content-class="scroll_container">
+      <NInfiniteScroll passive class="h-full" :distance="10" @load="handleLoadMore" content-class="scroll_container">
         <slot></slot>
         <div class="footer-loading w-full h-[50px]" v-show="loading">
           加载更多
@@ -69,7 +69,6 @@ defineExpose({ scrollToTop });
     position: relative;
     height: calc(100% - 100px);
     width: 100%;
-    // flex: 1;
   }
 
   .footer-loading {
@@ -81,4 +80,4 @@ defineExpose({ scrollToTop });
     color: #666;
   }
 }
-</style>@/stores/modules/appStore
+</style>