فهرست منبع

feat: 自动吸顶

zhangjie 7 ماه پیش
والد
کامیت
4ac29042af
4فایلهای تغییر یافته به همراه100 افزوده شده و 21 حذف شده
  1. 22 20
      src/assets/styles/base.scss
  2. 1 0
      src/directives/directives.js
  3. 71 0
      src/directives/sticky.js
  4. 6 1
      src/modules/questions/views/PropertyInfo.vue

+ 22 - 20
src/assets/styles/base.scss

@@ -127,18 +127,18 @@ body {
   border-radius: 8px;
   padding: 15px;
 }
-.icon-btn-group{
-  padding:0 6px 10px 6px;
-  .svg-btn{
-    &:not(:first-child){
-      margin-left:10px;
+.icon-btn-group {
+  padding: 0 6px 10px 6px;
+  .svg-btn {
+    &:not(:first-child) {
+      margin-left: 10px;
     }
   }
 }
-.right-btns{
-  .tool-tip-btn{
-    &:not(:first-child){
-      margin-left:12px;
+.right-btns {
+  .tool-tip-btn {
+    &:not(:first-child) {
+      margin-left: 12px;
     }
   }
 }
@@ -148,7 +148,7 @@ body {
 
 .el-form.part-filter-form {
   // padding: 20px 0 5px;
-  padding:5px 0 0;
+  padding: 5px 0 0;
   /* element-ui*/
   .el-form-item {
     margin-bottom: 15px;
@@ -186,8 +186,9 @@ body {
   }
   .el-form-item__content {
     // flex-grow: 2;
-    &>.el-input,&>.el-select{
-      width:136px !important;
+    & > .el-input,
+    & > .el-select {
+      width: 136px !important;
     }
   }
   .el-input__inner,
@@ -213,6 +214,7 @@ body {
 
 .part-box-title {
   font-size: 20px;
+  min-height: 40px;
   line-height: 1;
   padding-bottom: 20px;
   border-bottom: 1px solid $--color-border;
@@ -369,8 +371,8 @@ body {
 }
 .tips-error {
   color: $--color-danger;
-  &.hide{
-    opacity:0;
+  &.hide {
+    opacity: 0;
   }
 }
 .dialog-input-width {
@@ -419,9 +421,9 @@ body {
   color: $--color-danger;
 }
 
-.upload-gray-box{
-  background-color: #F0F0F0;
-  padding-top:15px;
-  margin-left:-20px;
-  margin-right:-20px;
-}
+.upload-gray-box {
+  background-color: #f0f0f0;
+  padding-top: 15px;
+  margin-left: -20px;
+  margin-right: -20px;
+}

+ 1 - 0
src/directives/directives.js

@@ -1,3 +1,4 @@
 import "../modules/questions/directives/directives";
 import "./domObserver";
 import "./permBtn";
+import "./sticky";

+ 71 - 0
src/directives/sticky.js

@@ -0,0 +1,71 @@
+import Vue from "vue";
+
+Vue.directive("sticky", {
+  inserted(el, binding) {
+    const referParent = binding.value.referParent
+      ? document.querySelector(binding.value.referParent)
+      : el.parentElement;
+    const stickyTop = binding.value.stickyTop || 0; // 设置吸顶的偏移量,默认0
+
+    const parent = el.parentElement;
+    const placeholder = document.createElement("div"); // 用于防止塌陷的占位元素
+    const elRect = el.getBoundingClientRect();
+    const siblingRect = el.nextElementSibling.getBoundingClientRect();
+    placeholder.style.height = `${siblingRect.top - elRect.top}px`;
+    placeholder.style.visibility = "hidden";
+    placeholder.style.display = "none";
+    parent.insertBefore(placeholder, el);
+
+    const parentRect = referParent.getBoundingClientRect();
+
+    const onScroll = () => {
+      const placeholderRect = placeholder.getBoundingClientRect();
+      const isSticky = placeholderRect.top < parentRect.top + stickyTop;
+      el.style.width = `${el.offsetWidth}px`;
+
+      if (isSticky) {
+        el.style.position = "fixed";
+        el.style.top = `${parentRect.top}px`;
+        el.style.left = `${elRect.left}px`;
+        el.style.boxShadow = `0 2px 2px 1px #eee`;
+        el.style.zIndex = 99;
+        placeholder.style.display = "block";
+      } else {
+        el.style.position = "";
+        el.style.top = "";
+        el.style.left = "";
+        el.style.boxShadow = "";
+        placeholder.style.display = "none";
+      }
+    };
+
+    // 监听滚动事件
+    referParent.addEventListener("scroll", onScroll);
+
+    // 监听窗口大小变化,更新元素宽度
+    const onResize = () => {
+      const parentRect = parent.getBoundingClientRect();
+      if (el.style.position === "fixed") {
+        el.style.width = `${parentRect.width}px`;
+        el.style.left = `${parentRect.left}px`;
+      }
+      placeholder.style.width = `${el.offsetWidth}px`;
+    };
+    window.addEventListener("resize", onResize);
+
+    // 移除监听器的清理函数
+    el._stickyCleanup = () => {
+      referParent.removeEventListener("scroll", onScroll);
+      window.removeEventListener("resize", onResize);
+      if (placeholder.parentElement) {
+        placeholder.parentElement.removeChild(placeholder);
+      }
+    };
+  },
+  unbind(el) {
+    // 清理事件监听器和占位元素
+    if (el._stickyCleanup) {
+      el._stickyCleanup();
+    }
+  },
+});

+ 6 - 1
src/modules/questions/views/PropertyInfo.vue

@@ -1,7 +1,12 @@
 <template>
   <section class="property-info">
     <!-- 正文信息 -->
-    <div class="part-box">
+    <div
+      class="part-box"
+      v-sticky="{
+        referParent: '.home-body',
+      }"
+    >
       <h2 class="part-box-title">{{ courseProperty.name }}</h2>
       <!-- <el-form
         class="part-filter-form"