Bläddra i källkod

恢复 frontLayout 组件(浅色主题)

Lin Qilong 5 dagar sedan
förälder
incheckning
d54b76d365

+ 25 - 0
gw-ui/src/frontLayout/index.vue

@@ -0,0 +1,25 @@
+<template>
+  <div id="mainPage">
+    <pageHeader @addSystemMenuView="addSystemMenuViewHandler" />
+    <div id="mainTabViewsContainer">
+      <tabsViewContain ref="tabsView" />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted } from 'vue'
+import pageHeader from './systemHeader.vue'
+import tabsViewContain from './tabViewContainerWithRouter.vue'
+
+const tabsView = ref(null)
+
+const addSystemMenuViewHandler = (params) => {
+  if (tabsView.value) tabsView.value.addView?.(params.viewItem)
+}
+</script>
+
+<style>
+#mainPage { width: 100%; height: 100vh; overflow: hidden; display: flex; flex-direction: column; background: #f5f9fc; }
+#mainTabViewsContainer { flex: 1; overflow: hidden; }
+</style>

+ 50 - 0
gw-ui/src/frontLayout/systemHeader.vue

@@ -0,0 +1,50 @@
+<template>
+  <div id="systemHeader">
+    <div id="systemInformation">
+      <img class="logoImg" src="@/assets/thlogo.png" alt="">
+      <span>太湖流域河湖管理系统</span>
+    </div>
+    <div id="systemMenuContainer">
+      <systemMenu @addSystemMenuView='menuItemClick'></systemMenu>
+    </div>
+    <div class="user-area">
+      <span class="user-name" @click="loginHzz">{{ name || '登录' }}</span>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted } from 'vue'
+import { useRouter } from 'vue-router'
+import Cookies from 'js-cookie'
+import systemMenu from './systemMenuBar.vue'
+
+const router = useRouter()
+const name = ref('')
+const loginHzz = () => { if (Cookies.get('isLogin') !== 'true') router.push('/login') }
+const emit = defineEmits(['addSystemMenuView'])
+const menuItemClick = (menuItem) => { emit('addSystemMenuView', { viewItem: menuItem.viewItem }) }
+onMounted(() => { if (Cookies.get('isLogin') === 'true') name.value = Cookies.get('name') })
+</script>
+
+<style scoped>
+#systemHeader {
+  height: 56px; width: 100%;
+  background: linear-gradient(135deg, #e8f4fd 0%, #d4ecfb 50%, #c5e5fa 100%);
+  display: flex; align-items: center; color: #1a3a5c;
+  box-shadow: 0 1px 6px rgba(0,0,0,.06); position: relative; z-index: 500;
+  border-bottom: 2px solid #b8d8f0;
+}
+#systemInformation {
+  display: flex; align-items: center; gap: 10px; padding: 0 16px;
+  min-width: 340px; flex-shrink: 0; font-size: 17px; font-weight: 600; color: #0d4b80;
+}
+.logoImg { width: 36px; height: 36px; border-radius: 8px; }
+#systemMenuContainer { flex: 1; height: 100%; display: flex; align-items: center; }
+.user-area { flex-shrink: 0; padding: 0 20px; }
+.user-name {
+  font-size: 13px; cursor: pointer; color: #4682b4;
+  padding: 6px 18px; border-radius: 20px; border: 1px solid #b0d0e8; background: #fff;
+}
+.user-name:hover { color: #0d4b80; border-color: #6baed6; background: #f0f8ff; }
+</style>

+ 93 - 0
gw-ui/src/frontLayout/systemMenuBar.vue

@@ -0,0 +1,93 @@
+<template>
+  <div id="systemMenuBar">
+    <div class="menu-item" :class="{ active: menuItem.id === 'sy' }"
+      v-for="(menuItem, idx) in menuInfos" :key="idx"
+      v-show="menuItem && menuItem.menuName != '数据维护'"
+      @mouseenter="onHover(menuItem)" @mouseleave="onLeave" @click="onClick(menuItem)">
+      <span class="menu-label">{{ menuItem.menuName }}</span>
+      <span class="menu-arrow" v-if="menuItem.children">▾</span>
+    </div>
+    <div class="menu-item" v-for="(menuItem, idx) in menuInfos" :key="'m-'+idx"
+      v-show="menuItem && menuItem.menuName == '数据维护' && isLogin == 'true'"
+      @click="onClick(menuItem)">
+      <span class="menu-label">{{ menuItem.menuName }}</span>
+    </div>
+    <transition name="fade-drop">
+      <div class="dropdown-panel" v-show="showDropdown" @mouseenter="keepOpen" @mouseleave="onLeave">
+        <div class="dropdown-col" v-for="sub in dropdownChildren" :key="sub.menuName">
+          <div class="dropdown-title" @click="onClick(sub)">{{ sub.menuName }}</div>
+          <div class="dropdown-link" v-for="ch in sub.children" :key="ch.menuName" @click="onClick(ch)">{{ ch.menuName }}</div>
+        </div>
+      </div>
+    </transition>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import Cookies from 'js-cookie'
+
+const emit = defineEmits(['addSystemMenuView'])
+const isLogin = ref(Cookies.get('isLogin') || '')
+const showDropdown = ref(false)
+const keepShow = ref(false)
+const dropdownChildren = ref([])
+
+const menuInfos = ref([
+  { menuName: '首页', name: '首页', href: '/hlgl/onemap', path: '/hlgl/onemap', haveView: true, id: 'sy' },
+  { menuName: '河湖长制', name: '河湖长制', haveView: true, id: 'hhzz',
+    children: [{ menuName: '河湖长制', children: [
+      { menuName: '工作制度', href: '/gzfa', path: '/gzfa', haveView: true },
+    ]}]
+  },
+  { menuName: '水域岸线', name: '水域岸线', haveView: true, id: 'syax',
+    children: [{ menuName: '水域岸线', children: [
+      { menuName: '涉河项目', href: '/shjsxm', path: '/shjsxm', haveView: true },
+      { menuName: '水域岸线', href: '/syaxgl', path: '/syaxgl', haveView: true },
+    ]}]
+  },
+  { menuName: '考核评估', name: '考核评估', haveView: true, id: 'khpg',
+    children: [{ menuName: '考核评估', children: [
+      { menuName: '考核结果', href: '/khpg', path: '/khpg', haveView: true },
+      { menuName: '相关文件', href: '/khwj', path: '/khwj', haveView: true },
+    ]}]
+  },
+  { menuName: '督导检查', name: '督导检查', haveView: true, id: 'ddjc',
+    children: [{ menuName: '督导检查', children: [
+      { menuName: '涉河项目督察', href: '/ddlb', path: '/ddlb', haveView: true },
+      { menuName: '河湖管理督察', href: '/ddsh', path: '/ddsh', haveView: true },
+      { menuName: '一湖两河清四乱', href: '/sjml', path: '/sjml', haveView: true },
+    ]}]
+  },
+  { menuName: '数据维护', name: '数据维护', href: '/sjwh', path: '/sjwh', haveView: true, id: 'sjwh' }
+])
+
+const onHover = (item) => { if (item.children) { dropdownChildren.value = item.children; showDropdown.value = true } }
+const onLeave = () => { keepShow.value = false; setTimeout(() => { if (!keepShow.value) showDropdown.value = false }, 150) }
+const keepOpen = () => { keepShow.value = true }
+const onClick = (item) => { showDropdown.value = false; if (item.href) emit('addSystemMenuView', { viewItem: item }) }
+</script>
+
+<style scoped>
+#systemMenuBar { height: 100%; display: flex; align-items: center; gap: 2px; padding: 0 8px; }
+.menu-item {
+  height: 38px; padding: 0 16px; border-radius: 6px; display: flex; align-items: center; gap: 4px;
+  cursor: pointer; transition: all .2s; color: #3a5f80; font-size: 13px; font-weight: 500; white-space: nowrap;
+}
+.menu-item:hover { background: #cde4f7; color: #0d4b80; }
+.menu-item.active { background: #b5d8f0; color: #0a3a6e; font-weight: 600; }
+.menu-arrow { font-size: 9px; opacity: .4; }
+.dropdown-panel {
+  position: fixed; top: 56px; left: 0; right: 0; z-index: 499; background: #fff;
+  box-shadow: 0 6px 20px rgba(0,0,0,.08); display: flex; gap: 40px; padding: 18px 60px;
+  animation: slideDown .18s ease; border-bottom: 2px solid #e0eef8;
+}
+@keyframes slideDown { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } }
+.dropdown-col { min-width: 100px; }
+.dropdown-title { font-size: 14px; font-weight: 600; color: #0d4b80; padding: 5px 0; margin-bottom: 4px; border-bottom: 2px solid #6baed6; }
+.dropdown-link { font-size: 13px; color: #5a7a95; padding: 5px 4px; cursor: pointer; border-radius: 4px; }
+.dropdown-link:hover { color: #0d6efd; background: #eef6fc; padding-left: 8px; }
+.fade-drop-enter-active { transition: all .18s ease; }
+.fade-drop-leave-active { transition: all .12s ease; }
+.fade-drop-enter-from, .fade-drop-leave-to { opacity: 0; transform: translateY(-4px); }
+</style>

+ 25 - 0
gw-ui/src/frontLayout/tabViewContainerWithRouter.vue

@@ -0,0 +1,25 @@
+<template>
+  <div id="tabViewContainer">
+    <div id="viewsItemBar">
+      <transition name="fade-transform" mode="out-in">
+        <router-view :key="key" />
+      </transition>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { computed } from 'vue'
+import { useRoute } from 'vue-router'
+const route = useRoute()
+const key = computed(() => route.fullPath)
+</script>
+
+<style scoped>
+#tabViewContainer { width: 100%; height: 100%; display: flex; flex-direction: column; }
+#viewsItemBar { flex: 1; overflow: auto; }
+.fade-transform-enter-active { transition: all .2s ease; }
+.fade-transform-leave-active { transition: all .15s ease; }
+.fade-transform-enter-from { opacity: 0; transform: translateY(8px); }
+.fade-transform-leave-to { opacity: 0; }
+</style>