From b37e141c00a123cf362fae00c1e63175d41c4bbe Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 10 三月 2026 17:01:06 +0800
Subject: [PATCH] #

---
 src/main/webapp/views/index.html |  161 +++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 135 insertions(+), 26 deletions(-)

diff --git a/src/main/webapp/views/index.html b/src/main/webapp/views/index.html
index 9a51064..e6fd9eb 100644
--- a/src/main/webapp/views/index.html
+++ b/src/main/webapp/views/index.html
@@ -37,12 +37,23 @@
     }
 
     .layout-aside {
+      position: relative;
+      flex-shrink: 0;
       display: flex;
       flex-direction: column;
       overflow: hidden;
       border-radius: 16px;
       background: linear-gradient(180deg, #16324d 0%, #0d2237 100%);
       box-shadow: 0 14px 32px rgba(22, 50, 77, 0.18);
+      transform: translateZ(0);
+      backface-visibility: hidden;
+      will-change: width;
+      transition: width 0.22s cubic-bezier(0.22, 1, 0.36, 1),
+      box-shadow 0.22s ease;
+    }
+
+    .layout-aside.is-animating {
+      pointer-events: none;
     }
 
     .layout-panel {
@@ -55,6 +66,8 @@
       background: #f5f7fa;
       box-shadow: 0 14px 32px rgba(83, 104, 129, 0.12);
       border: 1px solid #e4eaf2;
+      transform: translateZ(0);
+      backface-visibility: hidden;
     }
 
     .aside-logo {
@@ -66,6 +79,8 @@
       box-sizing: border-box;
       color: #fff;
       border-bottom: 1px solid rgba(255, 255, 255, 0.08);
+      transition: min-height 0.22s cubic-bezier(0.22, 1, 0.36, 1),
+      padding 0.22s cubic-bezier(0.22, 1, 0.36, 1);
     }
 
     .aside-logo-image {
@@ -74,6 +89,8 @@
       max-width: 178px;
       height: auto;
       object-fit: contain;
+      transform: translateZ(0);
+      transition: max-width 0.22s cubic-bezier(0.22, 1, 0.36, 1);
     }
 
     .aside-logo.is-collapse {
@@ -88,6 +105,17 @@
     .aside-search {
       padding: 12px 12px 8px;
       box-sizing: border-box;
+    }
+
+    .aside-fade-enter-active,
+    .aside-fade-leave-active {
+      transition: opacity 0.14s ease, transform 0.18s ease;
+    }
+
+    .aside-fade-enter,
+    .aside-fade-leave-to {
+      opacity: 0;
+      transform: translate3d(-10px, 0, 0);
     }
 
     .aside-search .el-input__inner {
@@ -109,6 +137,7 @@
     .aside-scroll {
       flex: 1;
       min-height: 0;
+      transform: translateZ(0);
     }
 
     .aside-scroll .el-scrollbar__wrap {
@@ -118,6 +147,7 @@
     .side-menu {
       border-right: none;
       background: transparent;
+      transform: translateZ(0);
     }
 
     .side-menu .el-submenu__title,
@@ -127,6 +157,7 @@
       margin: 0 10px 6px;
       border-radius: 10px;
       box-sizing: border-box;
+      backface-visibility: hidden;
     }
 
     .side-menu .el-submenu__title:hover,
@@ -533,20 +564,25 @@
 <body>
 <div id="app" v-cloak>
   <el-container class="shell-container">
-    <el-aside class="layout-aside" :width="asideWidth">
-      <div class="aside-logo" :class="{ 'is-collapse': isCollapse }">
+    <el-aside
+        class="layout-aside"
+        :class="{ 'is-animating': collapseAnimating }"
+        :width="asideWidth">
+      <div class="aside-logo" :class="{ 'is-collapse': asideCompact }">
         <img class="aside-logo-image" src="../static/images/zy-logo.png" alt="娴欐睙涓壃">
       </div>
 
-      <div class="aside-search" v-show="!isCollapse">
-        <el-input
-            v-model.trim="menuKeyword"
-            size="small"
-            clearable
-            prefix-icon="el-icon-search"
-            :placeholder="t('index.searchMenu')">
-        </el-input>
-      </div>
+      <transition name="aside-fade">
+        <div class="aside-search" v-show="showAsideExtras">
+          <el-input
+              v-model.trim="menuKeyword"
+              size="small"
+              clearable
+              prefix-icon="el-icon-search"
+              :placeholder="t('index.searchMenu')">
+          </el-input>
+        </div>
+      </transition>
 
       <el-scrollbar class="aside-scroll">
         <div v-if="menuLoading" class="aside-loading" aria-hidden="true">
@@ -562,7 +598,7 @@
               ref="sideMenu"
               class="side-menu"
               :default-active="activeMenuKey"
-              :collapse="isCollapse"
+              :collapse="menuCollapse"
               :collapse-transition="false"
               :default-openeds="defaultOpeneds"
               unique-opened
@@ -596,19 +632,21 @@
         </template>
       </el-scrollbar>
 
-      <div class="aside-footer" v-show="!isCollapse">
-        <div class="aside-footer-copy">漏 2026 {{ t('app.company') }}</div>
-        <div class="aside-footer-version">
-          <span class="aside-footer-version-text">{{ versionText }}</span>
-          <el-tag
-              v-if="versionType"
-              size="mini"
-              :type="versionTagType"
-              effect="dark">
-            {{ versionTypeTag }}
-          </el-tag>
+      <transition name="aside-fade">
+        <div class="aside-footer" v-show="showAsideExtras">
+          <div class="aside-footer-copy">漏 2026 {{ t('app.company') }}</div>
+          <div class="aside-footer-version">
+            <span class="aside-footer-version-text">{{ versionText }}</span>
+            <el-tag
+                v-if="versionType"
+                size="mini"
+                :type="versionTagType"
+                effect="dark">
+              {{ versionTypeTag }}
+            </el-tag>
+          </div>
         </div>
-      </div>
+      </transition>
     </el-aside>
 
     <el-container class="layout-panel">
@@ -757,6 +795,8 @@
     group: "璐︽埛涓績",
     menuKey: ""
   };
+  var SIDEBAR_TRANSITION_MS = 220;
+  var SIDEBAR_EXPAND_CONTENT_DELAY = 180;
   var TAB_STORAGE_KEY = "wcs-element-home-tabs";
   var USER_STORAGE_KEY = "username";
   var INDEX_I18N_FALLBACKS = {
@@ -800,6 +840,11 @@
     data: function () {
       return {
         isCollapse: false,
+        asideCompact: false,
+        menuCollapse: false,
+        showAsideExtras: true,
+        collapseAnimating: false,
+        collapseTimer: null,
         menuLoading: true,
         pageLoading: true,
         loadingText: window.WCS_I18N ? window.WCS_I18N.tl("姝e湪鍔犺浇椤甸潰...") : "姝e湪鍔犺浇椤甸潰...",
@@ -828,7 +873,7 @@
     },
     computed: {
       asideWidth: function () {
-        return this.isCollapse ? "72px" : "248px";
+        return this.asideCompact ? "72px" : "248px";
       },
       filteredMenus: function () {
         var keyword = (this.menuKeyword || "").toLowerCase();
@@ -961,6 +1006,10 @@
       if (this.menuSyncTimer) {
         clearTimeout(this.menuSyncTimer);
         this.menuSyncTimer = null;
+      }
+      if (this.collapseTimer) {
+        clearTimeout(this.collapseTimer);
+        this.collapseTimer = null;
       }
       if (this.aiTipIndex) {
         layer.close(this.aiTipIndex);
@@ -1356,8 +1405,65 @@
           this.syncFrameI18n(this.tabs[i].name);
         }
       },
+      clearCollapseTimer: function () {
+        if (this.collapseTimer) {
+          clearTimeout(this.collapseTimer);
+          this.collapseTimer = null;
+        }
+      },
+      nextFrame: function (callback) {
+        if (window.requestAnimationFrame) {
+          window.requestAnimationFrame(function () {
+            callback();
+          });
+          return;
+        }
+        setTimeout(callback, 16);
+      },
+      finishCollapseStage: function (callback, delay) {
+        var that = this;
+        this.clearCollapseTimer();
+        this.collapseTimer = setTimeout(function () {
+          that.collapseTimer = null;
+          callback();
+        }, delay);
+      },
       toggleCollapse: function () {
-        this.isCollapse = !this.isCollapse;
+        var that = this;
+
+        if (this.collapseAnimating) {
+          return;
+        }
+
+        this.collapseAnimating = true;
+
+        if (this.isCollapse) {
+          this.isCollapse = false;
+          this.asideCompact = false;
+          this.nextFrame(function () {
+            that.finishCollapseStage(function () {
+              that.menuCollapse = false;
+              that.showAsideExtras = true;
+              that.collapseAnimating = false;
+              that.$nextTick(function () {
+                that.syncMenuStateByUrl(that.activeTabUrl);
+              });
+            }, SIDEBAR_EXPAND_CONTENT_DELAY);
+          });
+          return;
+        }
+
+        this.isCollapse = true;
+        this.showAsideExtras = false;
+        this.menuCollapse = true;
+        this.$nextTick(function () {
+          that.nextFrame(function () {
+            that.asideCompact = true;
+            that.finishCollapseStage(function () {
+              that.collapseAnimating = false;
+            }, SIDEBAR_TRANSITION_MS);
+          });
+        });
       },
       handleMenuSelect: function (group, item) {
         this.addOrActivateTab({
@@ -1516,6 +1622,9 @@
           if (!menu) {
             return;
           }
+          if (that.menuCollapse) {
+            return;
+          }
           openedMenus = menu.openedMenus ? menu.openedMenus.slice() : [];
           if (!groupIndex) {
             if (openedMenus.length) {

--
Gitblit v1.9.1