Переглянути джерело

perf: 标签页可按滑动力度进行左右滑动 (#884)

* perf: 标签页可按滑动力度进行左右滑动

* fix: login keypress
xiaoming 1 рік тому
батько
коміт
cc28f0a6de

+ 1 - 1
package.json

@@ -54,7 +54,7 @@
     "@logicflow/extension": "^1.2.19",
     "@pureadmin/descriptions": "^1.2.0",
     "@pureadmin/table": "^3.0.1",
-    "@pureadmin/utils": "^2.4.3",
+    "@pureadmin/utils": "^2.4.4",
     "@vueuse/core": "^10.7.2",
     "@vueuse/motion": "^2.0.0",
     "@wangeditor/editor": "^5.1.23",

+ 4 - 4
pnpm-lock.yaml

@@ -24,8 +24,8 @@ dependencies:
     specifier: ^3.0.1
     version: 3.0.1(element-plus@2.5.1)(typescript@5.3.3)
   '@pureadmin/utils':
-    specifier: ^2.4.3
-    version: 2.4.3(echarts@5.4.3)(vue@3.4.14)
+    specifier: ^2.4.4
+    version: 2.4.4(echarts@5.4.3)(vue@3.4.14)
   '@vueuse/core':
     specifier: ^10.7.2
     version: 10.7.2(vue@3.4.14)
@@ -1763,8 +1763,8 @@ packages:
       string-hash: 1.1.3
     dev: true
 
-  /@pureadmin/utils@2.4.3(echarts@5.4.3)(vue@3.4.14):
-    resolution: {integrity: sha512-2CT8HIFUWiFZCJnclBRpng5kVQawvZWdAH4ERPnDZGt5pPltGzNNodpsDVHBCKYAbf/xDKpiNUkYwNbPCCIM9Q==}
+  /@pureadmin/utils@2.4.4(echarts@5.4.3)(vue@3.4.14):
+    resolution: {integrity: sha512-dH1ml+/U50Te7KlZX8pkA08/o+XKYx8aFyds9aTBC34JDyn0GQSyhe0zFIfGwnFztWMToWn/cyitpXmDEcq3NA==}
     peerDependencies:
       echarts: '*'
       vue: '*'

+ 0 - 1
src/layout/components/tag/index.scss

@@ -109,7 +109,6 @@
       overflow: visible;
       white-space: nowrap;
       list-style: none;
-      transition: transform 0.5s ease-in-out;
 
       .scroll-item {
         transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);

+ 37 - 1
src/layout/components/tag/index.vue

@@ -38,6 +38,7 @@ const {
   pureSetting,
   activeIndex,
   getTabStyle,
+  isScrolling,
   iconIsActive,
   linkIsActive,
   currentSelect,
@@ -138,6 +139,37 @@ const handleScroll = (offset: number): void => {
       translateX.value = 0;
     }
   }
+  isScrolling.value = false;
+};
+
+const handleWheel = (event: WheelEvent): void => {
+  isScrolling.value = true;
+  const scrollIntensity = Math.abs(event.deltaX) + Math.abs(event.deltaY);
+  let offset = 0;
+  if (event.deltaX < 0) {
+    offset = scrollIntensity > 0 ? scrollIntensity : 100;
+  } else {
+    offset = scrollIntensity > 0 ? -scrollIntensity : -100;
+  }
+
+  smoothScroll(offset);
+};
+
+const smoothScroll = (offset: number): void => {
+  const scrollAmount = 20; // 每帧滚动的距离
+  let remaining = Math.abs(offset);
+
+  const scrollStep = () => {
+    const scrollOffset = Math.sign(offset) * Math.min(scrollAmount, remaining);
+    handleScroll(scrollOffset);
+    remaining -= Math.abs(scrollOffset);
+
+    if (remaining > 0) {
+      requestAnimationFrame(scrollStep);
+    }
+  };
+
+  requestAnimationFrame(scrollStep);
 };
 
 function dynamicRouteTag(value: string): void {
@@ -525,7 +557,11 @@ onBeforeUnmount(() => {
     <span v-show="isShowArrow" class="arrow-left">
       <IconifyIconOffline :icon="ArrowLeftSLine" @click="handleScroll(200)" />
     </span>
-    <div ref="scrollbarDom" class="scroll-container">
+    <div
+      ref="scrollbarDom"
+      class="scroll-container"
+      @wheel.prevent="handleWheel"
+    >
       <div ref="tabDom" class="tab select-none" :style="getTabStyle">
         <div
           v-for="(item, index) in multiTags"

+ 4 - 1
src/layout/hooks/useTag.ts

@@ -42,6 +42,7 @@ export function useTags() {
   const activeIndex = ref(-1);
   // 当前右键选中的路由信息
   const currentSelect = ref({});
+  const isScrolling = ref(false);
 
   /** 显示模式,默认灵动模式 */
   const showModel = ref(
@@ -152,7 +153,8 @@ export function useTags() {
 
   const getTabStyle = computed((): CSSProperties => {
     return {
-      transform: `translateX(${translateX.value}px)`
+      transform: `translateX(${translateX.value}px)`,
+      transition: isScrolling.value ? "none" : "transform 0.5s ease-in-out"
     };
   });
 
@@ -228,6 +230,7 @@ export function useTags() {
     pureSetting,
     activeIndex,
     getTabStyle,
+    isScrolling,
     iconIsActive,
     linkIsActive,
     currentSelect,

+ 2 - 1
src/views/login/index.vue

@@ -97,7 +97,8 @@ const immediateDebounce: any = debounce(
 );
 
 useEventListener(document, "keypress", ({ code }) => {
-  if (code === "Enter" && !disabled.value) immediateDebounce(ruleFormRef.value);
+  if (code === "Enter" && !disabled.value && !loading.value)
+    immediateDebounce(ruleFormRef.value);
 });
 
 watch(imgCode, value => {