Преглед изворни кода

[Style 0000]新版菜单栏样式

wangkeyi пре 1 месец
родитељ
комит
0d33c6ba33

BIN
src/assets/images/vent/sider/border-bottom.png


BIN
src/assets/images/vent/sider/border-lbot.png


BIN
src/assets/images/vent/sider/border-left.png


BIN
src/assets/images/vent/sider/border-ltop.png


BIN
src/assets/images/vent/sider/border-rbot.png


BIN
src/assets/images/vent/sider/border-right.png


BIN
src/assets/images/vent/sider/border-rtop.png


BIN
src/assets/images/vent/sider/border.png


BIN
src/assets/images/vent/sider/buttonBot-active.png


BIN
src/assets/images/vent/sider/buttonBot.png


BIN
src/assets/images/vent/sider/buttonCont-hover.png


BIN
src/assets/images/vent/sider/buttonCont.png


BIN
src/assets/images/vent/sider/buttonTitle-hover.png


BIN
src/assets/images/vent/sider/buttonTitle.png


+ 30 - 0
src/assets/images/vent/sider/icon-inner.svg

@@ -0,0 +1,30 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="45.37" height="45.369" viewBox="0 0 45.37 45.369">
+  <defs>
+    <linearGradient id="linear-gradient" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox">
+      <stop offset="0" stop-color="#fff"/>
+      <stop offset="1" stop-color="#3df6ff"/>
+    </linearGradient>
+    <filter id="路径_57740" x="0" y="0" width="45.37" height="45.369" filterUnits="userSpaceOnUse">
+      <feOffset input="SourceAlpha"/>
+      <feGaussianBlur stdDeviation="1" result="blur"/>
+      <feFlood flood-color="#2cb6ff"/>
+      <feComposite operator="in" in2="blur"/>
+      <feComposite in="SourceGraphic"/>
+    </filter>
+    <filter id="路径_57741" x="21.344" y="22.768" width="22.602" height="22.602" filterUnits="userSpaceOnUse">
+      <feOffset input="SourceAlpha"/>
+      <feGaussianBlur stdDeviation="1" result="blur-2"/>
+      <feFlood flood-color="#36c7ff"/>
+      <feComposite operator="in" in2="blur-2"/>
+      <feComposite in="SourceGraphic"/>
+    </filter>
+  </defs>
+  <g id="组_16453" data-name="组 16453" transform="translate(3 3)">
+    <g transform="matrix(1, 0, 0, 1, -3, -3)" filter="url(#路径_57740)">
+      <path id="路径_57740-2" data-name="路径 57740" d="M35.463,23.464h7.116a4.758,4.758,0,0,1,4.743,4.743V40.066H35.463a4.758,4.758,0,0,1-4.743-4.747V28.2A4.757,4.757,0,0,1,35.463,23.464Zm0,21.345H47.322V56.668a4.758,4.758,0,0,1-4.743,4.743H35.463a4.761,4.761,0,0,1-4.743-4.747V49.547a4.757,4.757,0,0,1,4.743-4.739Zm0,0,24.9-1.189-8.3-8.535a4.3,4.3,0,0,1-1.423-3.32,4.672,4.672,0,0,1,1.423-3.32l4.981-4.981a4.583,4.583,0,0,1,6.639,0l4.981,4.981a4.583,4.583,0,0,1,0,6.639Zm0-19.21a2.165,2.165,0,0,0-1.662.712L53.727,30.1a2.3,2.3,0,0,0,0,3.324l6.639,6.639L67,33.427A2.3,2.3,0,0,0,67,30.1l-4.981-4.981a2.15,2.15,0,0,0-1.658-.712Zm0,0" transform="translate(-27.72 -19.04)" fill="url(#linear-gradient)"/>
+    </g>
+    <g transform="matrix(1, 0, 0, 1, -3, -3)" filter="url(#路径_57741)">
+      <path id="路径_57741-2" data-name="路径 57741" d="M562.074,588.8h11.859a4.758,4.758,0,0,1,4.743,4.743v7.116a4.758,4.758,0,0,1-4.743,4.743h-7.116a4.758,4.758,0,0,1-4.743-4.743Zm0,0" transform="translate(-537.73 -563.03)" fill="url(#linear-gradient)"/>
+    </g>
+  </g>
+</svg>

BIN
src/assets/images/vent/sider/icon-outer.png


BIN
src/assets/images/vent/sider/menu-bg.png


BIN
src/assets/images/vent/sider/svg-arrow.png


+ 14 - 0
src/assets/images/vent/sider/svg-close.svg

@@ -0,0 +1,14 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="23.83" height="23.83" viewBox="0 0 23.83 23.83">
+  <defs>
+    <filter id="路径_57742" x="0" y="0" width="23.83" height="23.83" filterUnits="userSpaceOnUse">
+      <feOffset input="SourceAlpha"/>
+      <feGaussianBlur stdDeviation="1" result="blur"/>
+      <feFlood flood-color="#3df6ff"/>
+      <feComposite operator="in" in2="blur"/>
+      <feComposite in="SourceGraphic"/>
+    </filter>
+  </defs>
+  <g transform="matrix(1, 0, 0, 1, 0, 0)" filter="url(#路径_57742)">
+    <path id="路径_57742-2" data-name="路径 57742" d="M168.085,164.9l5.459-5.459a.993.993,0,0,0,0-1.364l-1.82-1.82a.993.993,0,0,0-1.364,0l-5.459,5.456-5.459-5.459a.993.993,0,0,0-1.364,0l-1.82,1.82a.993.993,0,0,0,0,1.364l5.456,5.461-5.459,5.459a.993.993,0,0,0,0,1.364l1.82,1.82a.993.993,0,0,0,1.364,0l5.461-5.459,5.459,5.459a.993.993,0,0,0,1.364,0l1.82-1.82a.993.993,0,0,0,0-1.364Z" transform="translate(-152.98 -152.98)" fill="#3df6ff"/>
+  </g>
+</svg>

+ 77 - 0
src/components/vent/siderBorderBg.vue

@@ -0,0 +1,77 @@
+<template>
+  <div class="sider-border-bg">
+    <!-- 边框效果 -->
+    <div class="border_corner border_corner_left_top"></div>
+    <div class="border_corner border_corner_right_top"></div>
+    <div class="border_corner border_corner_left_bottom"></div>
+    <div class="border_corner border_corner_right_bottom"></div>
+    <div class="border_corner_left"></div>
+    <div class="border_corner_right"></div>
+    <div class="main-container">
+      <!-- 这里写内容 -->
+      <slot></slot>
+    </div>
+  </div>
+</template>
+<script>
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    name: 'SiderBorderBg',
+    setup() {},
+  });
+</script>
+
+<style lang="less" scoped>
+  .sider-border-bg {
+    position: relative;
+    .main-container {
+    }
+    .border_corner {
+      position: absolute;
+      width: 265px;
+      height: 130px;
+    }
+    .border_corner_left_top {
+      background: url(/@/assets/images//vent/sider/border-ltop.png) no-repeat;
+      background-size: 100% 100%;
+      top: -28px;
+      left: -28px;
+    }
+    .border_corner_right_top {
+      background: url(/@/assets/images//vent/sider/border-rtop.png) no-repeat;
+      background-size: 100% 100%;
+      top: -28px;
+      right: -28px;
+    }
+    .border_corner_left_bottom {
+      background: url(/@/assets/images//vent/sider/border-lbot.png) no-repeat;
+      background-size: 100% 100%;
+      bottom: -28px;
+      left: -28px;
+    }
+    .border_corner_right_bottom {
+      background: url(/@/assets/images//vent/sider/border-rbot.png) no-repeat;
+      background-size: 100% 100%;
+      bottom: -28px;
+      right: -28px;
+    }
+    .border_corner_left {
+      position: absolute;
+      width: 12px;
+      height: calc(100% - 222px);
+      background: url(/src/assets/images/vent/sider/border-left.png) no-repeat;
+      background-size: 100% 100%;
+      top: 110px;
+      left: -18px;
+    }
+    .border_corner_right {
+      position: absolute;
+      width: 12px;
+      height: calc(100% - 222px);
+      background: url(/src/assets/images/vent/sider/border-right.png) no-repeat;
+      background-size: 100% 100%;
+      top: 110px;
+      right: -18px;
+    }
+  }
+</style>

+ 515 - 0
src/layouts/default/sider/bottomSideder3.vue

@@ -0,0 +1,515 @@
+<template>
+  <div v-if="isShowMenu == -1" class="bottom-side" :class="{ 'bottom-size-show': isShowMenu }" @click="closeMenu">
+    <SiderBorderBg>
+      <div class="close-btn" @click.stop="closeMenu"></div>
+      <div class="menu-panel" @click.stop>
+        <!-- 关键修改1:panel-header 从flex默认的justify-content:flex-start(已满足),但内层wrapper改为inline-flex -->
+        <div class="panel-header">
+          <template v-for="(menu, index) in currentParentRoute.children" :key="index">
+            <div class="col-header-wrapper" v-if="!menu.hideMenu">
+              <div class="col-header">
+                <div class="col-header-inner">{{ menu.name }}</div>
+              </div>
+              <div class="col-arrow"></div>
+            </div>
+          </template>
+        </div>
+
+        <!-- 关键修改2:panel-body 改为inline-flex,取消flex:1均分,添加align-items:flex-start -->
+        <div class="panel-body">
+          <template v-for="(menu, index) in currentParentRoute.children" :key="index">
+            <div class="menu-col" v-if="!menu.hideMenu">
+              <div class="menu-col-bg">
+                <template v-for="(childMenu, childIndex) in menu.children" :key="childIndex">
+                  <template v-if="!childMenu.hideMenu">
+                    <div v-if="childMenu['ver'] == 1" class="menu-item" @click.stop="handleMenuClick(childMenu)">{{ childMenu.name }}</div>
+                    <div v-else class="menu-item menu-item-disabled" @click.stop="handleMenuClick(childMenu)">{{ childMenu.name }}</div>
+                  </template>
+                </template>
+              </div>
+            </div>
+          </template>
+        </div>
+
+        <div class="panel-footer">
+          <div class="tab-group">
+            <template v-for="(programMenu, key) in menuModules" :key="key">
+              <div
+                v-if="!programMenu.title.startsWith('首页')"
+                class="tab-btn"
+                :class="{ 'tab-btn-active': currentParentRoute == programMenu }"
+                @click.stop="selectMenu($event, programMenu)"
+                >{{ programMenu.title }}</div
+              >
+            </template>
+          </div>
+        </div>
+      </div>
+    </SiderBorderBg>
+  </div>
+  <div v-else-if="isShowMenu == 0" class="menu-show-icon">
+    <div class="icon" @click="openMenu"></div>
+  </div>
+</template>
+
+<script lang="ts">
+  import { defineComponent, nextTick, onMounted, ref, unref } from 'vue';
+  import type { Menu } from '/@/router/types';
+  import { SvgIcon } from '/@/components/Icon';
+  import { getMenus } from '/@/router/menus';
+  import { useGo } from '/@/hooks/web/usePage';
+  import { useRouter } from 'vue-router';
+  import { getActions } from '/@/qiankun/state';
+  import { PageEnum } from '/@/enums/pageEnum';
+  import { useGlobSetting } from '/@/hooks/setting';
+  import { unmountMicroApps } from '/@/qiankun';
+  import { useUserStoreWithOut } from '/@/store/modules/user';
+  import { useAppStore } from '/@/store/modules/app';
+  import { router } from '/@/router';
+  import SiderBorderBg from '/@/components/vent/siderBorderBg.vue';
+
+  export default defineComponent({
+    name: 'BottomSider',
+    components: { SvgIcon, SiderBorderBg },
+    setup() {
+      let menuModules = ref<Menu[]>([]);
+      const actions = getActions();
+      const currentParentRoute = ref<Menu>();
+      const { currentRoute } = useRouter();
+      const route = unref(currentRoute);
+      const go = useGo();
+      const glob = useGlobSetting();
+      const isShowMenu = ref(route.path.startsWith('/cad-viewer') ? 1 : 0);
+      const userStore = useUserStoreWithOut();
+      const themeIcon = ref('styleTwo');
+
+      function selectMenu(e: Event, programMenu) {
+        e.stopPropagation();
+        currentParentRoute.value = programMenu;
+      }
+
+      async function handleMenuClick(path: Menu) {
+        if (path.path == currentRoute.value.fullPath) {
+          return;
+        }
+        if (path.path.includes('sw/monitor-fanmain')) {
+          var url = window.open('_blank') as Window;
+          url.location = 'https://swkhmi.shendong.vip:9043/#SW_PW_NORTH';
+          return;
+        }
+        if (path.path.includes('sw/forcFan')) {
+          var url = window.open('_blank') as Window;
+          url.location = 'https://swkhmi.shendong.vip:9043/#SW_CA';
+          return;
+        }
+        if (path.path.includes('outlink/index')) {
+          var url = window.open('_blank') as Window;
+          url.location = path['frameSrc'];
+          return;
+        }
+        go(path.path);
+        isShowMenu.value = 0;
+      }
+
+      function geHome() {
+        if (userStore.getUserInfo.homePath) {
+          go(userStore.getUserInfo.homePath);
+        } else if (currentRoute.value.path.startsWith('/micro-need-air')) {
+          window.history.pushState({}, '', glob.homePath || PageEnum.BASE_HOME);
+        } else {
+          go(glob.homePath || PageEnum.BASE_HOME);
+        }
+      }
+      function closeMenu(e?: Event) {
+        e?.stopPropagation();
+        isShowMenu.value = 0;
+        document.removeEventListener('click', closeMenu);
+      }
+
+      function openMenu(e: Event) {
+        e.stopPropagation();
+        isShowMenu.value = -1;
+        document.addEventListener('click', closeMenu);
+      }
+
+      onMounted(async () => {
+        menuModules.value = await getMenus();
+        const index = menuModules.value.findIndex((menu) => menu.children && menu.children.length > 0);
+        currentParentRoute.value = menuModules.value[index];
+      });
+      return {
+        themeIcon,
+        menuModules,
+        isShowMenu,
+        handleMenuClick,
+        openMenu,
+        closeMenu,
+        selectMenu,
+        go,
+        geHome,
+        currentParentRoute,
+      };
+    },
+  });
+</script>
+
+<style lang="less" scoped>
+  @panel-bg: #091624;
+  @panel-border: #1a7aaa;
+  @accent: #00c8ff;
+  @accent-dim: #1a8aaa;
+  @header-bg: linear-gradient(180deg, #1b4e7a 0%, #0d3055 100%);
+  @header-border: #2a7aaa;
+  @item-bg: #071828;
+  @item-border: #155a80;
+  @item-text: #b0dcf0;
+  @tab-active-bg: #00b8d9;
+  @tab-active-text: #001f30;
+  @white: #ffffff;
+
+  @keyframes menuFadeIn {
+    from {
+      opacity: 0;
+    }
+    to {
+      opacity: 1;
+    }
+  }
+
+  @keyframes panelScaleIn {
+    from {
+      opacity: 0;
+      transform: scale(0.96);
+    }
+    to {
+      opacity: 1;
+      transform: scale(1);
+    }
+  }
+
+  .bottom-side {
+    position: fixed;
+    inset: 0;
+    z-index: 99999;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background: rgba(0, 8, 22, 0.7);
+    backdrop-filter: blur(3px);
+    color: #fff;
+    animation: panelScaleIn 0.3s ease forwards;
+
+    .menu-panel {
+      position: relative;
+      width: 92vw;
+      max-width: 1440px;
+      background: @panel-bg;
+      display: flex;
+      flex-direction: column;
+      height: 70%;
+      max-height: 70%;
+      overflow: hidden;
+      background: url(/@/assets/images//vent/sider/border.png) no-repeat;
+      background-size: 100% 100%;
+    }
+
+    .side-bar {
+      position: absolute;
+      top: 12%;
+      bottom: 12%;
+      width: 3px;
+      background: linear-gradient(180deg, transparent, @accent 25%, @accent 75%, transparent);
+      z-index: 10;
+      box-shadow: 0 0 6px @accent;
+
+      &.side-bar-left {
+        left: -2px;
+      }
+      &.side-bar-right {
+        right: -2px;
+      }
+    }
+
+    .close-btn {
+      position: absolute;
+      top: -18px;
+      right: 0px;
+      width: 22px;
+      height: 22px;
+      cursor: pointer;
+      background: url(/@/assets/images//vent/sider/svg-close.svg) no-repeat;
+      background-size: 100% 100%;
+    }
+
+    .panel-header {
+      display: flex;
+      align-items: center;
+      justify-content: flex-start;
+      padding: 0 24px;
+      flex-wrap: nowrap;
+      overflow-x: auto;
+      overflow-y: hidden;
+      position: relative;
+
+      .col-header-wrapper {
+        display: inline-flex;
+        align-items: center;
+        min-width: 100px;
+        width: 175px;
+        position: relative;
+        justify-content: center;
+      }
+
+      .col-header {
+        min-width: 100px;
+        width: 100%;
+        padding: 24px 12px 12px 12px;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+        margin: 0;
+        .col-header-inner {
+          width: 100%;
+          max-width: 135px;
+          height: 60px;
+          background: url(/@/assets/images//vent/sider/buttonTitle.png) no-repeat;
+          background-size: 100% 100%;
+          text-align: center;
+          font-size: 13px;
+          font-weight: 500;
+          letter-spacing: 1px;
+          white-space: nowrap;
+        }
+      }
+
+      .col-arrow {
+        width: 20px;
+        height: 12px;
+        position: absolute;
+        right: -10px;
+        top: 57%;
+        transform: translateY(-50%);
+        pointer-events: none;
+        background: url(/@/assets/images//vent/sider/svg-arrow.png) no-repeat;
+        background-size: 100% 100%;
+      }
+      .col-header-wrapper:last-of-type .col-arrow {
+        display: none;
+      }
+    }
+
+    .panel-body {
+      display: inline-flex;
+      align-items: flex-start;
+      width: 100%;
+      height: 100%;
+      overflow-y: auto;
+      overflow-x: auto;
+      padding: 14px 24px 10px;
+
+      // &::-webkit-scrollbar {
+      //   width: 2px;
+      //   height: 2px;
+      // }
+      // &::-webkit-scrollbar-track {
+      //   background: #071420;
+      // }
+      // &::-webkit-scrollbar-thumb {
+      //   background: @accent-dim;
+      //   border-radius: 2px;
+      // }
+
+      .menu-col {
+        width: 175px;
+        height: 100%;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+      }
+      .menu-col-bg {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        gap: 15px;
+        height: 500px;
+        width: 80%;
+        max-width: 175px;
+        max-height: 600px;
+        background: url(/@/assets/images//vent/sider/menu-bg.png) no-repeat;
+        background-size: 100% 100%;
+        padding: 10px;
+        overflow-y: auto;
+        overflow-x: hidden;
+
+        &::-webkit-scrollbar {
+          width: 6px !important;
+          border: 0;
+        }
+        // &::-webkit-scrollbar-track {
+        //   background: #071420;
+        // }
+        &::-webkit-scrollbar-thumb {
+          // width: 1px !important;
+          background: @accent-dim;
+        }
+      }
+
+      .menu-item {
+        width: 100%;
+        max-width: 128px;
+        min-height: 30px;
+        padding: 5px 6px;
+        text-align: center;
+        background: url(/@/assets/images//vent/sider/buttonCont.png) no-repeat;
+        background-size: 100% 100%;
+        font-size: 12px;
+        color: @item-text;
+        cursor: pointer;
+        transition: all 0.18s;
+        line-height: 1.5;
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+
+        &:hover {
+          background: url(/@/assets/images//vent/sider/buttonCont-hover.png) no-repeat;
+          background-size: 100% 100%;
+        }
+      }
+
+      .menu-item-disabled {
+        opacity: 0.45;
+        cursor: default;
+        background: #111a26;
+        border-color: #2a3a4a;
+        color: #6a8a9a;
+
+        &:hover {
+          background: #111a26;
+          border-color: #2a3a4a;
+          color: #6a8a9a;
+          box-shadow: none;
+        }
+      }
+    }
+
+    .panel-footer {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      padding: 10px 20px 0 20px;
+      position: relative;
+      flex-shrink: 0;
+
+      .tab-group {
+        width: 50%;
+        height: 35px;
+        display: flex;
+        align-items: center;
+        gap: 1px;
+        background: url(/@/assets/images/vent/sider/border-bottom.png) no-repeat;
+        background-size: 100% 100%;
+        padding: 0 20px;
+      }
+
+      .tab-btn {
+        width: 120px;
+        height: 25px;
+        color: @white;
+        font-size: 13px;
+        cursor: pointer;
+        background: url(/@/assets/images/vent/sider/buttonBot.png) no-repeat;
+        background-size: 100% 100%;
+        white-space: nowrap;
+        padding: 3px 5px 0 5px;
+        margin-bottom: 10px;
+        text-align: center;
+      }
+
+      .tab-btn-active {
+        width: 120px;
+        height: 35px;
+        background: url(/@/assets/images/vent/sider/buttonBot-active.png) no-repeat;
+        background-size: 105% 100%;
+        font-weight: 500;
+        margin: 0 0 4px -5px;
+      }
+
+      .setting-group {
+        position: absolute;
+        right: 20px;
+        display: flex;
+        align-items: center;
+        gap: 10px;
+        color: @accent-dim;
+
+        .icon-style {
+          cursor: pointer;
+          transition: color 0.18s;
+
+          &:hover {
+            color: @accent;
+          }
+        }
+      }
+    }
+  }
+
+  .bottom-size-show {
+    animation: menuFadeIn 0.3s ease forwards;
+  }
+
+  .menu-show-icon {
+    position: fixed;
+    bottom: 20px;
+    left: 25px;
+    z-index: 1000000;
+
+    .icon {
+      width: 60px;
+      height: 60px;
+      position: relative;
+
+      &:before {
+        content: '';
+        display: block;
+        width: 60px;
+        height: 60px;
+        position: absolute;
+        background: url('/@/assets/images/vent/sider/icon-outer.png') no-repeat;
+        background-size: 100% 100%;
+        background-position: center;
+      }
+
+      &:after {
+        content: '';
+        display: block;
+        width: 36px;
+        height: 35px;
+        position: absolute;
+        top: 18%;
+        right: 18%;
+        background: url('/@/assets/images/vent/sider/icon-inner.svg') no-repeat;
+        background-size: 100% 100%;
+        background-position: center;
+        animation-timing-function: ease-in;
+        animation: fadenum 8s infinite;
+      }
+
+      @keyframes fadenum {
+        0% {
+          transform: rotate(0deg);
+        }
+
+        10% {
+          transform: rotate(360deg);
+        }
+
+        100% {
+          transform: rotate(360deg);
+        }
+      }
+    }
+  }
+</style>

+ 4 - 1
src/layouts/default/sider/index.vue

@@ -14,6 +14,8 @@
   <BottomSider v-else-if="getIsBottomMenu" />
   <Sider v-else /> -->
   <BottomSider v-if="!noSiderLink.includes(routePath)" />
+  <!-- 新版样式 -->
+  <!-- <bottomSider3 v-if="!noSiderLink.includes(routePath)" /> -->
   <!-- <bottomSider2 v-if="!noChatLink.includes(routePath)" /> -->
   <!-- <bottomSider2 /> -->
 </template>
@@ -24,6 +26,7 @@
   import MixSider from './MixSider.vue';
   import BottomSider from './bottomSideder.vue';
   import bottomSider2 from './bottomSider2.vue';
+  import bottomSider3 from './bottomSideder3.vue';
   import { Drawer } from 'ant-design-vue';
 
   import { useAppInject } from '/@/hooks/web/useAppInject';
@@ -33,7 +36,7 @@
   import { noSiderLink, noChatLink } from '../layout.data';
   export default defineComponent({
     name: 'SiderWrapper',
-    components: { Sider, Drawer, MixSider, BottomSider, bottomSider2 },
+    components: { Sider, Drawer, MixSider, BottomSider, bottomSider2, bottomSider3 },
     setup() {
       const route = useRoute();
       const { prefixCls } = useDesign('layout-sider-wrapper');