Browse Source

feat(home): 为用户组件添加可选的尾部装饰

- 在 User 组件中新增 tailSrc 属性,支持传入尾部装饰图片
- 添加三组 SVG 尾部装饰文件,包含动画效果
- 在 Flowchart 组件中为特定用户配置不同的尾部装饰
- 移除原有的 CSS 伪元素实现,改为使用 SVG 图片
- 调整箭头位置和层级以适配新的布局
reaper 1 tháng trước cách đây
mục cha
commit
33db425a67

+ 49 - 0
app/assets/svg/home/user2-tail.svg

@@ -0,0 +1,49 @@
+<svg width="14" height="151" viewBox="0 0 14 151" fill="none" xmlns="http://www.w3.org/2000/svg">
+<style>
+  .flowCore,
+  .flowGlow {
+    fill-rule: evenodd;
+  }
+
+  .flowCore {
+    fill: rgba(255, 255, 255, 0.9);
+  }
+
+  .flowGlow {
+    fill: rgba(150, 215, 255, 0.34);
+    filter: url(#flowBlur);
+  }
+
+  @media (prefers-reduced-motion: reduce) {
+    .flowGroup {
+      display: none;
+    }
+  }
+</style>
+<rect width="14" height="151" fill="url(#paint0_linear_3000_1)"/>
+<g class="flowGroup" mask="url(#flowMaskY)">
+<rect class="flowGlow" width="14" height="151"/>
+<rect class="flowCore" width="14" height="151"/>
+</g>
+<defs>
+<linearGradient id="flowSweepY" x1="0" y1="0" x2="0" y2="1">
+<stop offset="0" stop-color="white" stop-opacity="0"/>
+<stop offset="0.42" stop-color="white" stop-opacity="0"/>
+<stop offset="0.5" stop-color="white" stop-opacity="1"/>
+<stop offset="0.58" stop-color="white" stop-opacity="0"/>
+<stop offset="1" stop-color="white" stop-opacity="0"/>
+</linearGradient>
+<mask id="flowMaskY" maskUnits="userSpaceOnUse">
+<rect x="0" y="-151" width="14" height="151" fill="url(#flowSweepY)">
+<animate attributeName="y" from="-151" to="151" dur="1.2s" repeatCount="indefinite"/>
+</rect>
+</mask>
+<filter id="flowBlur" x="-60%" y="-20%" width="220%" height="140%" color-interpolation-filters="sRGB">
+<feGaussianBlur stdDeviation="1.4"/>
+</filter>
+<linearGradient id="paint0_linear_3000_1" x1="7" y1="0" x2="7" y2="151" gradientUnits="userSpaceOnUse">
+<stop stop-color="#979797"/>
+<stop offset="1" stop-color="#E6E6E6"/>
+</linearGradient>
+</defs>
+</svg>

+ 49 - 0
app/assets/svg/home/user3-tail.svg

@@ -0,0 +1,49 @@
+<svg width="14" height="151" viewBox="0 0 14 151" fill="none" xmlns="http://www.w3.org/2000/svg">
+<style>
+  .flowCore,
+  .flowGlow {
+    fill-rule: evenodd;
+  }
+
+  .flowCore {
+    fill: rgba(255, 255, 255, 0.9);
+  }
+
+  .flowGlow {
+    fill: rgba(150, 215, 255, 0.34);
+    filter: url(#flowBlur);
+  }
+
+  @media (prefers-reduced-motion: reduce) {
+    .flowGroup {
+      display: none;
+    }
+  }
+</style>
+<rect width="14" height="151" fill="url(#paint0_linear_3000_2)"/>
+<g class="flowGroup" mask="url(#flowMaskY)">
+<rect class="flowGlow" width="14" height="151"/>
+<rect class="flowCore" width="14" height="151"/>
+</g>
+<defs>
+<linearGradient id="flowSweepY" x1="0" y1="0" x2="0" y2="1">
+<stop offset="0" stop-color="white" stop-opacity="0"/>
+<stop offset="0.42" stop-color="white" stop-opacity="0"/>
+<stop offset="0.5" stop-color="white" stop-opacity="1"/>
+<stop offset="0.58" stop-color="white" stop-opacity="0"/>
+<stop offset="1" stop-color="white" stop-opacity="0"/>
+</linearGradient>
+<mask id="flowMaskY" maskUnits="userSpaceOnUse">
+<rect x="0" y="-151" width="14" height="151" fill="url(#flowSweepY)">
+<animate attributeName="y" from="-151" to="151" dur="1.2s" repeatCount="indefinite"/>
+</rect>
+</mask>
+<filter id="flowBlur" x="-60%" y="-20%" width="220%" height="140%" color-interpolation-filters="sRGB">
+<feGaussianBlur stdDeviation="1.4"/>
+</filter>
+<linearGradient id="paint0_linear_3000_2" x1="7" y1="0" x2="7" y2="151" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FF5852"/>
+<stop offset="1" stop-color="#FFFFFF"/>
+</linearGradient>
+</defs>
+</svg>

+ 49 - 0
app/assets/svg/home/user4-tail.svg

@@ -0,0 +1,49 @@
+<svg width="14" height="151" viewBox="0 0 14 151" fill="none" xmlns="http://www.w3.org/2000/svg">
+<style>
+  .flowCore,
+  .flowGlow {
+    fill-rule: evenodd;
+  }
+
+  .flowCore {
+    fill: rgba(255, 255, 255, 0.9);
+  }
+
+  .flowGlow {
+    fill: rgba(150, 215, 255, 0.34);
+    filter: url(#flowBlur);
+  }
+
+  @media (prefers-reduced-motion: reduce) {
+    .flowGroup {
+      display: none;
+    }
+  }
+</style>
+<rect width="14" height="151" fill="url(#paint0_linear_3000_3)"/>
+<g class="flowGroup" mask="url(#flowMaskY)">
+<rect class="flowGlow" width="14" height="151"/>
+<rect class="flowCore" width="14" height="151"/>
+</g>
+<defs>
+<linearGradient id="flowSweepY" x1="0" y1="0" x2="0" y2="1">
+<stop offset="0" stop-color="white" stop-opacity="0"/>
+<stop offset="0.42" stop-color="white" stop-opacity="0"/>
+<stop offset="0.5" stop-color="white" stop-opacity="1"/>
+<stop offset="0.58" stop-color="white" stop-opacity="0"/>
+<stop offset="1" stop-color="white" stop-opacity="0"/>
+</linearGradient>
+<mask id="flowMaskY" maskUnits="userSpaceOnUse">
+<rect x="0" y="-151" width="14" height="151" fill="url(#flowSweepY)">
+<animate attributeName="y" from="-151" to="151" dur="1.2s" repeatCount="indefinite"/>
+</rect>
+</mask>
+<filter id="flowBlur" x="-60%" y="-20%" width="220%" height="140%" color-interpolation-filters="sRGB">
+<feGaussianBlur stdDeviation="1.4"/>
+</filter>
+<linearGradient id="paint0_linear_3000_3" x1="7" y1="0" x2="7" y2="151" gradientUnits="userSpaceOnUse">
+<stop stop-color="#CCCCCC"/>
+<stop offset="1" stop-color="#FFFFFF"/>
+</linearGradient>
+</defs>
+</svg>

+ 8 - 37
app/components/home/Flowchart.vue

@@ -2,9 +2,9 @@
   <section class="flowchart-container">
     <div class="flowchart-users">
       <User text="正常访客" :src="user1Icon" class="user1" />
-      <User text="DDos" :src="user2Icon" class="user2" />
-      <User text="异常访客" :src="user3Icon" class="user3" />
-      <User text="... ..." :src="user4Icon" class="user4" />
+      <User text="DDos" :src="user2Icon" :tail-src="user2Tail" class="user2" />
+      <User text="异常访客" :src="user3Icon" :tail-src="user3Tail" class="user3" />
+      <User text="... ..." :src="user4Icon" :tail-src="user4Tail" class="user4" />
     </div>
     <div class="flowchart-arrow">
       <img class="arrow1" src="~/assets/svg/home/arrow.svg" alt="arrow" />
@@ -115,6 +115,9 @@ import user1Icon from '~/assets/svg/home/user1.svg'
 import user2Icon from '~/assets/svg/home/user2.svg'
 import user3Icon from '~/assets/svg/home/user3.svg'
 import user4Icon from '~/assets/svg/home/user4.svg'
+import user2Tail from '~/assets/svg/home/user2-tail.svg'
+import user3Tail from '~/assets/svg/home/user3-tail.svg'
+import user4Tail from '~/assets/svg/home/user4-tail.svg'
 </script>
 <style lang="scss" scoped>
 .flowchart-container {
@@ -137,51 +140,18 @@ import user4Icon from '~/assets/svg/home/user4.svg'
       position: absolute;
       top: 0;
       right: 394px;
-
-      &::after {
-        content: "";
-        position: absolute;
-        width: 14px;
-        height: 151px;
-        top: 100%;
-        right: 40%;
-        background: linear-gradient(#979797, #E6E6E6);
-        transform: translateX(-50%);
-      }
     }
 
     .user3 {
       position: absolute;
       top: 0;
       right: 197px;
-
-      &::after {
-        content: "";
-        position: absolute;
-        width: 14px;
-        height: 151px;
-        top: 100%;
-        right: 40%;
-        background: linear-gradient(#FF5852, #fff);
-        transform: translateX(-50%);
-      }
     }
 
     .user4 {
       position: absolute;
       top: 0;
       right: 0;
-
-      &::after {
-        content: "";
-        position: absolute;
-        width: 14px;
-        height: 151px;
-        top: 100%;
-        right: 40%;
-        background: linear-gradient(#ccc, #fff);
-        transform: translateX(-50%);
-      }
     }
 
   }
@@ -195,8 +165,9 @@ import user4Icon from '~/assets/svg/home/user4.svg'
 
     .arrow1 {
       position: absolute;
-      top: 122px;
+      top: 120px;
       left: 106px;
+      z-index: 0;
     }
 
     .text-box {

+ 18 - 2
app/components/home/User.vue

@@ -2,6 +2,7 @@
   <div class="user-item">
     <img width="72" :src="src" class="user1-img" alt="user" />
     <div class="user1-text">{{ text }}</div>
+    <img v-if="tailSrc" class="user-tail" :src="tailSrc" alt="" aria-hidden="true" />
   </div>
 </template>
 <script setup>
@@ -17,11 +18,16 @@ const props = defineProps({
     type: String,
     default: defaultUserSrc,
     required: true,
-  }
+  },
+  tailSrc: {
+    type: String,
+    default: "",
+  },
 });
 </script>
 <style lang="scss" scoped>
 .user-item {
+  position: relative;
   display: flex;
   flex-direction: column;
   justify-content: center;
@@ -43,4 +49,14 @@ const props = defineProps({
     line-height: 20px;
   }
 }
-</style>
+
+.user-tail {
+  position: absolute;
+  width: 14px;
+  height: 151px;
+  top: 100%;
+  right: 40%;
+  transform: translateX(-50%);
+  pointer-events: none;
+}
+</style>