Browse Source

Merge branch 'test' of http://47.97.161.140:10080/zhangchuang/ocean-engineer into test

Mr. Robot 3 months ago
parent
commit
10bbd3b5c8
3 changed files with 399 additions and 184 deletions
  1. 240 0
      src/layout/home.vue
  2. 146 182
      src/layout/index.vue
  3. 13 2
      src/style.css

+ 240 - 0
src/layout/home.vue

@@ -0,0 +1,240 @@
+<template>
+    <el-container class="layout-container">
+      <div class="layout-container-header">
+        <div class="navigation-bar">
+          <div class="nav-title">动力装备健康状态数据评估</div>
+          <!-- <div style="flex: 1;display: flex;justify-content: space-between;padding: 0 60px;"> -->
+          <div
+            class="nav-item nav-all"
+            v-for="(item, index) in navItems"
+            :key="index"
+            :class="{ active: activeTab.parent === index }"
+      @click="() => setActiveTab({ parent: index, child: null }, item)"
+  
+            :ref="`navItem-${index}`"
+          >
+            {{ item.name }}
+            <div
+              v-if="item.children && item.children.length"
+              class="dropdown-menu"
+            >
+              <div
+                class="dropdown-item"
+                v-for="(child, childIndex) in item.children"
+                :key="childIndex"
+          :class="{ 'active-child': activeTab.parent === index && activeTab.child === childIndex }"
+  
+          @click="(event) => { event.stopPropagation(); setActiveTab({ parent: index, child: childIndex }, child); }"
+              >
+                {{ child.meta.title }}
+              </div>
+            </div>
+          </div>
+          <!-- </div> -->
+        </div>
+      </div>
+      <el-main>
+        <router-view></router-view>
+      </el-main>
+    </el-container>
+  </template>
+  
+  <script lang="ts" setup>
+  import { ref, onMounted, nextTick, computed, watch } from "vue";
+  import { useRoute, useRouter } from "vue-router";
+  interface RouteType {
+    path: string;
+    name: string;
+    index: number;
+    children: any;
+  }
+  const router = useRouter();
+  const route = useRoute(); // 获取当前路由对象
+  const navItems = computed<RouteType[]>(() => {
+    console.log(router.getRoutes());
+  
+    return router
+      .getRoutes()
+      .map((route, index) => {
+        if (route.meta && route.meta.show && !!!route.meta.child) {
+          return {
+            path: route.path,
+            name: route.meta.title || route.name,
+            index: index,
+            children:route.meta.children==false? []:route.children,
+          };
+        }
+        return null;
+      })
+      .filter((item) => item !== null);
+  });
+  console.log(navItems);
+  const activeTab = ref({ parent: 0, child: null });
+  
+  const setActiveTab = (tab, item: RouteType) => {
+    activeTab.value = tab;
+    router.push({ path: item.path });
+  };
+  
+  const findActiveTab = (items, path) => {
+    for (const [index, item] of items.entries()) {
+      if (item.children) {
+        for (const [childIndex, child] of item.children.entries()) {
+          if (path.startsWith(child.path)) {
+            return { parent: index, child: childIndex };
+          }
+        }
+      }
+      if (path.startsWith(item.path)) {
+        return { parent: index, child: null };
+      }
+    }
+    return { parent: 0, child: null };
+  };
+  
+  const setActiveTabByPath = (path: string) => {
+    const foundTab = findActiveTab(navItems.value, path);
+    activeTab.value = foundTab;
+  };
+  
+  watch(
+    () => route.path,
+    (newPath) => {
+      setActiveTabByPath(newPath);
+    }
+  );
+  onMounted(() => {
+    nextTick(() => {
+      // 在组件创建时和路由变化时更新 activeTab
+      setActiveTabByPath(route.path);
+    });
+  });
+  </script>
+  
+  <style scoped>
+  .layout-container {
+    width: 100%;
+    height: 100vh;
+    display: flex;
+    flex-direction: column;
+    background: rgba(0, 0, 0, 0.86);
+  }
+  .layout-container-header {
+    height: 53px;
+    width: 100%;
+  }
+  .navigation-bar {
+    width: 100%;
+    display: flex;
+    background: url("@/assets/img/nav.png") no-repeat;
+    background-size: 100% 100%;
+    height: 53px;
+    font-family: "YouSheTitleHei";
+  }
+  
+  .nav-title {
+    width: 750px;
+    padding-left: 36px;
+  
+    background: linear-gradient(
+      180deg,
+      rgb(1, 251, 187),
+      rgb(255, 255, 255),
+      rgb(9, 167, 255)
+    );
+  
+    font-size: 28px;
+    font-weight: 400;
+    line-height: 53px;
+    letter-spacing: 0%;
+    text-align: left;
+    -webkit-background-clip: text;
+    -webkit-text-fill-color: transparent;
+    background-clip: text;
+    text-fill-color: transparent;
+  }
+  
+  .nav-all{
+    /* margin-left: 15px; */
+  }
+  .nav-item {
+  padding: 0 30px;
+    cursor: pointer;
+    color: rgba(255, 255, 255, 0.75);
+    font-size: 20px;
+    font-weight: 400;
+    line-height: 53px;
+    letter-spacing: 0%;
+    text-align: center;
+    position: relative;
+  }
+  .nav-item:hover .dropdown-menu{
+    display: block !important;
+  } 
+  .dropdown-menu {
+    position: absolute;
+    top: 53px; 
+  left: 50%;
+  font-size: 16px;
+    transform: translateX(-50%);
+    background: rgba(0, 0, 0, 0.66);
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
+    z-index: 1000;
+    display: none;
+    flex-wrap: nowrap;
+    flex-direction: column;
+    overflow: hidden;
+    white-space: nowrap
+     /* min-width: 150px; */
+  }
+  
+  .dropdown-item {
+    padding: 8px 16px;
+    cursor: pointer;
+    color: rgba(255, 255, 255, 0.85);
+    font-size: 18px;
+    font-weight: 400;
+    line-height: 40px;
+    text-align: center;
+    /* background: rgba(0, 0, 0, 0.86); */
+  }
+  
+  .dropdown-item:hover,.active-child {
+    background: linear-gradient(180deg, rgb(92, 255, 213), rgb(255, 255, 255));
+    -webkit-background-clip: text;
+    -webkit-text-fill-color: transparent;
+    background-clip: text;
+    text-fill-color: transparent;
+  }
+  
+  .nav-item>.active {
+    width: 100%;
+    background: linear-gradient(180deg, rgb(92, 255, 213), rgb(255, 255, 255));
+    -webkit-background-clip: text;
+    -webkit-text-fill-color: transparent;
+    background-clip: text;
+    text-fill-color: transparent;
+    font-size: 24px;
+    font-weight: 400;
+    line-height: 53px;
+    letter-spacing: 0%;
+    text-align: center;
+    position: relative;
+  }
+  
+  .active::after {
+  content: " ";
+    position: absolute;
+    left: 50%;
+    transform: translateX(-50%);
+    width: var(--after-width, 74px);
+    height: 3px;
+    bottom: 3px;
+    /* bottom: -19px; */
+    /* transform: rotate(180deg); */
+    border-radius: 8px;
+    box-shadow: 0px -6px 10px 0px rgb(2, 251, 188), 0px -4px 16px 0px rgb(2, 251, 188);
+    background: rgb(2, 251, 188);
+  }
+  </style>
+  

+ 146 - 182
src/layout/index.vue

@@ -1,239 +1,203 @@
 <template>
-  <el-container class="layout-container">
-    <div class="layout-container-header">
-      <div class="navigation-bar">
-        <div class="nav-title">动力装备健康状态数据评估</div>
-        <!-- <div style="flex: 1;display: flex;justify-content: space-between;padding: 0 60px;"> -->
+  <div class="container">
+    <div class="container-header">
+      <div class="container-header-name">动力装备健康状态数据评估</div>
+      <div class="container-header-menu">
         <div
-          class="nav-item nav-all"
-          v-for="(item, index) in navItems"
-          :key="index"
-          :class="{ active: activeTab.parent === index }"
-    @click="() => setActiveTab({ parent: index, child: null }, item)"
-
-          :ref="`navItem-${index}`"
+          class="menu"
+          v-for="(menu, index) in menuList"
+          :key="menu.path"
+          :class="{ active: activeIndex === index }"
+          @mouseenter="showPopup(index)"
+          @click="setActive(menu, index)"
         >
-          {{ item.name }}
-          <div
-            v-if="item.children && item.children.length"
-            class="dropdown-menu"
-          >
-            <div
-              class="dropdown-item"
-              v-for="(child, childIndex) in item.children"
-              :key="childIndex"
-        :class="{ 'active-child': activeTab.parent === index && activeTab.child === childIndex }"
-
-        @click="(event) => { event.stopPropagation(); setActiveTab({ parent: index, child: childIndex }, child); }"
-            >
-              {{ child.meta.title }}
-            </div>
+          {{ menu.name }}
+        </div>
+        <div @mouseleave="hidePopup" class="popup" v-show="isPopup">
+          <div class="popup-item" v-for="item in menuList[0].children">
+            <div @click="setMenu(item, 0)">{{ item.name }}</div>
           </div>
         </div>
-        <!-- </div> -->
       </div>
     </div>
-    <el-main>
+    <div class="container-main">
       <router-view></router-view>
-    </el-main>
-  </el-container>
+    </div>
+  </div>
 </template>
+<script setup lang="ts">
+import { ref } from "vue";
+import { useRouter } from "vue-router";
+
+const activeIndex = ref(4);
+const isPopup = ref(false);
+const router = useRouter();
 
-<script lang="ts" setup>
-import { ref, onMounted, nextTick, computed, watch } from "vue";
-import { useRoute, useRouter } from "vue-router";
-interface RouteType {
+interface menuListType {
   path: string;
   name: string;
-  index: number;
-  children: any;
+  children?: menuListType[];
 }
-const router = useRouter();
-const route = useRoute(); // 获取当前路由对象
-const navItems = computed<RouteType[]>(() => {
-  console.log(router.getRoutes());
-
-  return router
-    .getRoutes()
-    .map((route, index) => {
-      if (route.meta && route.meta.show && !!!route.meta.child) {
-        return {
-          path: route.path,
-          name: route.meta.title || route.name,
-          index: index,
-          children:route.meta.children==false? []:route.children,
-        };
-      }
-      return null;
-    })
-    .filter((item) => item !== null);
-});
-console.log(navItems);
-const activeTab = ref({ parent: 0, child: null });
-
-const setActiveTab = (tab, item: RouteType) => {
-  activeTab.value = tab;
-  router.push({ path: item.path });
-};
 
-const findActiveTab = (items, path) => {
-  for (const [index, item] of items.entries()) {
-    if (item.children) {
-      for (const [childIndex, child] of item.children.entries()) {
-        if (path.startsWith(child.path)) {
-          return { parent: index, child: childIndex };
-        }
-      }
-    }
-    if (path.startsWith(item.path)) {
-      return { parent: index, child: null };
-    }
+const menuList: menuListType[] = [
+  {
+    path: "/Set",
+    name: "设置",
+    children: [
+      {
+        path: "/ConditionClassification",
+        name: "工况分类展示",
+      },
+      {
+        path: "/HealthSettings",
+        name: "健康指标偏离值设置",
+      },
+      {
+        path: "/WarningSettings",
+        name: "警告信息与维修建议设置",
+      },
+    ],
+  },
+  {
+    path: "/FileManagement",
+    name: "数据文件管理",
+  },
+  {
+    path: "/repair",
+    name: "维修策略辅助决策",
+  },
+  {
+    path: "/OperationalReliabilityPrediction",
+    name: "运行可靠性预测",
+  },
+  {
+    path: "/HealthStatusAnalysis",
+    name: "健康状态分析",
+  },
+];
+
+// 选择父菜单
+const setActive = (menu: menuListType, index: number) => {
+  if (index > 0) {
+    activeIndex.value = index;
+    router.push({ path: menu.path });
   }
-  return { parent: 0, child: null };
 };
 
-const setActiveTabByPath = (path: string) => {
-  const foundTab = findActiveTab(navItems.value, path);
-  activeTab.value = foundTab;
+// 选择子菜单
+const setMenu = (menu: menuListType, index: number) => {
+  activeIndex.value = index;
+  isPopup.value = false;
+  router.push({ path: menu.path });
 };
 
-watch(
-  () => route.path,
-  (newPath) => {
-    setActiveTabByPath(newPath);
+// 显示弹出菜单
+const showPopup = (index: number) => {
+  if (index === 0) {
+    isPopup.value = true;
   }
-);
-onMounted(() => {
-  nextTick(() => {
-    // 在组件创建时和路由变化时更新 activeTab
-    setActiveTabByPath(route.path);
-  });
-});
-</script>
+};
 
-<style scoped>
-.layout-container {
-  width: 100%;
+// 隐藏弹出菜单
+const hidePopup = () => {
+  isPopup.value = false;
+};
+</script>
+<style lang="scss" scoped>
+.container {
+  width: 100vw;
   height: 100vh;
-  display: flex;
-  flex-direction: column;
-  background: rgba(0, 0, 0, 0.86);
-}
-.layout-container-header {
-  height: 53px;
-  width: 100%;
+  user-select: none;
 }
-.navigation-bar {
-  width: 100%;
+
+.container-header {
   display: flex;
-  background: url("@/assets/img/nav.png") no-repeat;
-  background-size: 100% 100%;
+  align-items: center;
+  width: 100vw;
   height: 53px;
   font-family: "YouSheTitleHei";
+  background: url("@/assets/img/nav.png") no-repeat 100% 100%;
 }
 
-.nav-title {
-  width: 750px;
-  padding-left: 36px;
-
+.container-header-name {
+  width: 500px;
+  height: 53px;
+  text-align: center;
+  line-height: 53px;
+  font-size: 32px;
   background: linear-gradient(
     180deg,
     rgb(1, 251, 187),
     rgb(255, 255, 255),
     rgb(9, 167, 255)
   );
-
-  font-size: 28px;
-  font-weight: 400;
-  line-height: 53px;
-  letter-spacing: 0%;
-  text-align: left;
-  -webkit-background-clip: text;
-  -webkit-text-fill-color: transparent;
   background-clip: text;
-  text-fill-color: transparent;
+  color: transparent;
 }
 
-.nav-all{
-  /* margin-left: 15px; */
-}
-.nav-item {
-padding: 0 30px;
-  cursor: pointer;
-  color: rgba(255, 255, 255, 0.75);
+.container-header-menu {
+  display: flex;
+  flex-direction: row-reverse;
+  align-items: center;
+  width: calc(100vw - 500px);
+  height: 53px;
   font-size: 20px;
   font-weight: 400;
-  line-height: 53px;
-  letter-spacing: 0%;
-  text-align: center;
+  gap: 80px;
+  padding-right: 60px;
+  color: rgba(255, 255, 255, 0.75);
   position: relative;
 }
-.nav-item:hover .dropdown-menu{
-  display: block !important;
-} 
-.dropdown-menu {
-  position: absolute;
-  top: 53px; 
-left: 50%;
-font-size: 16px;
-  transform: translateX(-50%);
-  background: rgba(0, 0, 0, 0.66);
-  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
-  z-index: 1000;
-  display: none;
-  flex-wrap: nowrap;
-  flex-direction: column;
-  overflow: hidden;
-  white-space: nowrap
-   /* min-width: 150px; */
-}
 
-.dropdown-item {
-  padding: 8px 16px;
+.menu {
   cursor: pointer;
-  color: rgba(255, 255, 255, 0.85);
-  font-size: 18px;
-  font-weight: 400;
-  line-height: 40px;
-  text-align: center;
-  /* background: rgba(0, 0, 0, 0.86); */
 }
 
-.dropdown-item:hover,.active-child {
-  background: linear-gradient(180deg, rgb(92, 255, 213), rgb(255, 255, 255));
-  -webkit-background-clip: text;
-  -webkit-text-fill-color: transparent;
+.menu.active {
+  background: linear-gradient(180deg, rgb(1, 251, 187), rgb(255, 255, 255));
   background-clip: text;
-  text-fill-color: transparent;
-}
-
-.nav-item>.active {
-  width: 100%;
-  background: linear-gradient(180deg, rgb(92, 255, 213), rgb(255, 255, 255));
-  -webkit-background-clip: text;
-  -webkit-text-fill-color: transparent;
-  background-clip: text;
-  text-fill-color: transparent;
-  font-size: 24px;
-  font-weight: 400;
-  line-height: 53px;
-  letter-spacing: 0%;
-  text-align: center;
+  color: transparent;
   position: relative;
 }
 
-.active::after {
-content: " ";
+.menu.active::after {
+  content: "";
   position: absolute;
   left: 50%;
   transform: translateX(-50%);
-  width: var(--after-width, 74px);
+  width: 74px;
   height: 3px;
-  bottom: 3px;
-  /* bottom: -19px; */
-  /* transform: rotate(180deg); */
+  bottom: -10px;
   border-radius: 8px;
-  box-shadow: 0px -6px 10px 0px rgb(2, 251, 188), 0px -4px 16px 0px rgb(2, 251, 188);
+  box-shadow: 0px -6px 10px 0px rgb(2, 251, 188),
+    0px -4px 16px 0px rgb(2, 251, 188);
   background: rgb(2, 251, 188);
 }
+
+.popup {
+  width: 250px;
+  box-sizing: border-box;
+  padding: 0 20px;
+  position: absolute;
+  top: 53px;
+  right: 20px;
+  z-index: 999;
+  display: flex;
+  flex-direction: column;
+  background-color: #333;
+}
+
+.popup-item {
+  width: 100%;
+  height: 50px;
+  line-height: 50px;
+  text-align: right;
+}
+
+.popup-item:hover {
+  background: linear-gradient(180deg, rgb(1, 251, 187), rgb(255, 255, 255));
+  background-clip: text;
+  color: transparent;
+  position: relative;
+}
 </style>

+ 13 - 2
src/style.css

@@ -19,10 +19,21 @@
 }
 body {
   font-family: "AliPuHui", sans-serif;
+  position: relative;
   background: url(./assets/img/body.png);
-
-
+  background-size: cover;  /* 让背景图片铺满整个区域 */
 }
+
+body:after {
+  content: "";
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: rgba(0, 0, 0, 0.8); /* 磨砂效果用黑色rgba(0, 0, 0, 0.5) */
+  z-index: -10000;
+} 
 /* 搜索框自定义样式 */
 .custom-search-input  .el-input__wrapper {