Ryuiso 8 mēneši atpakaļ
vecāks
revīzija
89c9220531

+ 34 - 0
web/src/components/PageHeader/index.vue

@@ -0,0 +1,34 @@
+<script setup lang="ts">
+defineProps<{
+  title: string;
+  description: string;
+}>()
+</script>
+
+<template>
+  <div class="page-header">
+    <h1>{{ title }}</h1>
+    <p class="description">{{ description }}</p>
+  </div>
+</template>
+
+<style scoped lang="scss">
+@use '@/assets/styles/variables' as v;
+@use '@/assets/styles/mixins' as m;
+
+.page-header {
+  text-align: center;
+  margin-bottom: v.$spacing-xl * 2;
+
+  h1 {
+    font-size: v.$font-size-xxl;
+    color: v.$text-primary;
+    margin-bottom: v.$spacing-md;
+  }
+
+  .description {
+    font-size: v.$font-size-lg;
+    color: v.$text-secondary;
+  }
+}
+</style>

+ 59 - 0
web/src/components/SubNavigation/index.vue

@@ -0,0 +1,59 @@
+<script setup lang="ts">
+import { useRoute } from 'vue-router'
+import { computed } from 'vue'
+
+const props = defineProps<{
+  items: Array<{ path: string; title: string }>
+}>()
+
+const route = useRoute()
+const currentPath = computed(() => route.path)
+</script>
+
+<template>
+  <nav class="sub-nav">
+    <router-link
+      v-for="item in items"
+      :key="item.path"
+      :to="item.path"
+      class="nav-item"
+      :class="{ active: currentPath === item.path }"
+    >
+      {{ item.title }}
+    </router-link>
+  </nav>
+</template>
+
+<style scoped lang="scss">
+@use '@/assets/styles/variables' as v;
+@use '@/assets/styles/mixins' as m;
+
+.sub-nav {
+  display: flex;
+  justify-content: center;
+  gap: v.$spacing-md;
+  margin-bottom: v.$spacing-xl;
+  padding: v.$spacing-md;
+  background-color: v.$background-light;
+  border-radius: v.$border-radius-lg;
+  box-shadow: v.$shadow-sm;
+
+  .nav-item {
+    padding: v.$spacing-sm v.$spacing-md;
+    color: v.$text-primary;
+    text-decoration: none;
+    border-radius: v.$border-radius-md;
+    transition: all v.$transition-fast;
+
+    &:hover {
+      background-color: rgba(v.$primary-color, 0.1);
+      color: v.$primary-color;
+    }
+
+    &.active {
+      background-color: v.$primary-color;
+      color: white;
+    }
+  }
+}
+</style>

+ 9 - 69
web/src/views/Enterprise/Emergency/index.vue

@@ -1,8 +1,6 @@
 <script setup lang="ts">
-import { useRoute } from 'vue-router'
-import { computed } from 'vue'
-
-const route = useRoute()
+import PageHeader from '@/components/PageHeader/index.vue'
+import SubNavigation from '@/components/SubNavigation/index.vue'
 
 const subMenuItems = [
   { path: '/enterprise/emergency/flood', title: '洪涝灾害救援' },
@@ -10,29 +8,16 @@ const subMenuItems = [
   { path: '/enterprise/emergency/earthquake', title: '地震与地质灾害救援' },
   { path: '/enterprise/emergency/mountain-rescue', title: '山岳搜救' }
 ]
-
-const currentPath = computed(() => route.path)
 </script>
 
 <template>
-  <div class="emergency-view">
-    <div class="header">
-      <h1>应急救援解决方案</h1>
-      <p class="description">为应急救援提供高效、精准的数字化支持</p>
-    </div>
+  <div class="page-view">
+    <PageHeader
+      title="应急救援解决方案"
+      description="为应急救援提供高效、精准的数字化支持"
+    />
 
-    <!-- 子菜单导航 -->
-    <nav class="sub-nav">
-      <router-link
-        v-for="item in subMenuItems"
-        :key="item.path"
-        :to="item.path"
-        class="nav-item"
-        :class="{ active: currentPath === item.path }"
-      >
-        {{ item.title }}
-      </router-link>
-    </nav>
+    <SubNavigation :items="subMenuItems" />
 
     <!-- 子路由视图 -->
     <div class="content">
@@ -45,54 +30,9 @@ const currentPath = computed(() => route.path)
 @use '@/assets/styles/variables' as v;
 @use '@/assets/styles/mixins' as m;
 
-.emergency-view {
+.page-view {
   padding: v.$spacing-xl v.$spacing-xl * 2;
 
-  .header {
-    text-align: center;
-    margin-bottom: v.$spacing-xl * 2;
-
-    h1 {
-      font-size: v.$font-size-xxl;
-      color: v.$text-primary;
-      margin-bottom: v.$spacing-md;
-    }
-
-    .description {
-      font-size: v.$font-size-lg;
-      color: v.$text-secondary;
-    }
-  }
-
-  .sub-nav {
-    display: flex;
-    justify-content: center;
-    gap: v.$spacing-md;
-    margin-bottom: v.$spacing-xl;
-    padding: v.$spacing-md;
-    background-color: v.$background-light;
-    border-radius: v.$border-radius-lg;
-    box-shadow: v.$shadow-sm;
-
-    .nav-item {
-      padding: v.$spacing-sm v.$spacing-md;
-      color: v.$text-primary;
-      text-decoration: none;
-      border-radius: v.$border-radius-md;
-      transition: all v.$transition-fast;
-
-      &:hover {
-        background-color: rgba(v.$primary-color, 0.1);
-        color: v.$primary-color;
-      }
-
-      &.active {
-        background-color: v.$primary-color;
-        color: white;
-      }
-    }
-  }
-
   .content {
     max-width: 1200px;
     margin: 0 auto;

+ 101 - 0
web/src/views/Enterprise/Emergency/index_bk.vue

@@ -0,0 +1,101 @@
+<script setup lang="ts">
+import { useRoute } from 'vue-router'
+import { computed } from 'vue'
+
+const route = useRoute()
+
+const subMenuItems = [
+  { path: '/enterprise/emergency/flood', title: '洪涝灾害救援' },
+  { path: '/enterprise/emergency/forest-fire', title: '森林火灾救援' },
+  { path: '/enterprise/emergency/earthquake', title: '地震与地质灾害救援' },
+  { path: '/enterprise/emergency/mountain-rescue', title: '山岳搜救' }
+]
+
+const currentPath = computed(() => route.path)
+</script>
+
+<template>
+  <div class="emergency-view">
+    <div class="header">
+      <h1>应急救援解决方案</h1>
+      <p class="description">为应急救援提供高效、精准的数字化支持</p>
+    </div>
+
+    <!-- 子菜单导航 -->
+    <nav class="sub-nav">
+      <router-link
+        v-for="item in subMenuItems"
+        :key="item.path"
+        :to="item.path"
+        class="nav-item"
+        :class="{ active: currentPath === item.path }"
+      >
+        {{ item.title }}
+      </router-link>
+    </nav>
+
+    <!-- 子路由视图 -->
+    <div class="content">
+      <router-view></router-view>
+    </div>
+  </div>
+</template>
+
+<style scoped lang="scss">
+@use '@/assets/styles/variables' as v;
+@use '@/assets/styles/mixins' as m;
+
+.emergency-view {
+  padding: v.$spacing-xl v.$spacing-xl * 2;
+
+  .header {
+    text-align: center;
+    margin-bottom: v.$spacing-xl * 2;
+
+    h1 {
+      font-size: v.$font-size-xxl;
+      color: v.$text-primary;
+      margin-bottom: v.$spacing-md;
+    }
+
+    .description {
+      font-size: v.$font-size-lg;
+      color: v.$text-secondary;
+    }
+  }
+
+  .sub-nav {
+    display: flex;
+    justify-content: center;
+    gap: v.$spacing-md;
+    margin-bottom: v.$spacing-xl;
+    padding: v.$spacing-md;
+    background-color: v.$background-light;
+    border-radius: v.$border-radius-lg;
+    box-shadow: v.$shadow-sm;
+
+    .nav-item {
+      padding: v.$spacing-sm v.$spacing-md;
+      color: v.$text-primary;
+      text-decoration: none;
+      border-radius: v.$border-radius-md;
+      transition: all v.$transition-fast;
+
+      &:hover {
+        background-color: rgba(v.$primary-color, 0.1);
+        color: v.$primary-color;
+      }
+
+      &.active {
+        background-color: v.$primary-color;
+        color: white;
+      }
+    }
+  }
+
+  .content {
+    max-width: 1200px;
+    margin: 0 auto;
+  }
+}
+</style>

+ 9 - 68
web/src/views/Enterprise/LawEnforcement/index.vue

@@ -1,8 +1,6 @@
 <script setup lang="ts">
-import { useRoute } from 'vue-router'
-import { computed } from 'vue'
-
-const route = useRoute()
+import PageHeader from '@/components/PageHeader/index.vue'
+import SubNavigation from '@/components/SubNavigation/index.vue'
 
 const subMenuItems = [
   { path: '/enterprise/law-enforcement/investigation', title: '侦查取证' },
@@ -11,28 +9,16 @@ const subMenuItems = [
   { path: '/enterprise/law-enforcement/city-management', title: '城管巡查' }
 ]
 
-const currentPath = computed(() => route.path)
 </script>
 
 <template>
-  <div class="law-enforcement-view">
-    <div class="header">
-      <h1>执法解决方案</h1>
-      <p class="description">为执法部门提供智能化、数字化的解决方案</p>
-    </div>
+  <div class="page-view">
+    <PageHeader
+      title="执法解决方案"
+      description="为执法部门提供智能化、数字化的解决方案"
+    />
 
-    <!-- 子菜单导航 -->
-    <nav class="sub-nav">
-      <router-link
-        v-for="item in subMenuItems"
-        :key="item.path"
-        :to="item.path"
-        class="nav-item"
-        :class="{ active: currentPath === item.path }"
-      >
-        {{ item.title }}
-      </router-link>
-    </nav>
+    <SubNavigation :items="subMenuItems" />
 
     <!-- 子路由视图 -->
     <div class="content">
@@ -45,54 +31,9 @@ const currentPath = computed(() => route.path)
 @use '@/assets/styles/variables' as v;
 @use '@/assets/styles/mixins' as m;
 
-.law-enforcement-view {
+.page-view {
   padding: v.$spacing-xl v.$spacing-xl * 2;
 
-  .header {
-    text-align: center;
-    margin-bottom: v.$spacing-xl * 2;
-
-    h1 {
-      font-size: v.$font-size-xxl;
-      color: v.$text-primary;
-      margin-bottom: v.$spacing-md;
-    }
-
-    .description {
-      font-size: v.$font-size-lg;
-      color: v.$text-secondary;
-    }
-  }
-
-  .sub-nav {
-    display: flex;
-    justify-content: center;
-    gap: v.$spacing-md;
-    margin-bottom: v.$spacing-xl;
-    padding: v.$spacing-md;
-    background-color: v.$background-light;
-    border-radius: v.$border-radius-lg;
-    box-shadow: v.$shadow-sm;
-
-    .nav-item {
-      padding: v.$spacing-sm v.$spacing-md;
-      color: v.$text-primary;
-      text-decoration: none;
-      border-radius: v.$border-radius-md;
-      transition: all v.$transition-fast;
-
-      &:hover {
-        background-color: rgba(v.$primary-color, 0.1);
-        color: v.$primary-color;
-      }
-
-      &.active {
-        background-color: v.$primary-color;
-        color: white;
-      }
-    }
-  }
-
   .content {
     max-width: 1200px;
     margin: 0 auto;

+ 10 - 69
web/src/views/Enterprise/PublicSafety/index.vue

@@ -1,39 +1,25 @@
 <script setup lang="ts">
-import { useRoute } from 'vue-router'
-import { computed } from 'vue'
-
-const route = useRoute()
+import PageHeader from '@/components/PageHeader/index.vue'
+import SubNavigation from '@/components/SubNavigation/index.vue'
 
 const subMenuItems = [
   { path: '/enterprise/public-safety/mapping', title: '测绘' },
   { path: '/enterprise/public-safety/power', title: '电力' },
   { path: '/enterprise/public-safety/oil-gas', title: '石油与天然气' },
   { path: '/enterprise/public-safety/water', title: '水利' },
-  { path: '/enterprise/public-safety/forestry', title: '林业' }
+  { path: '/enterprise/public-safety/forestry', title: '林业' },
 ]
 
-const currentPath = computed(() => route.path)
 </script>
 
 <template>
-  <div class="public-safety-view">
-    <div class="header">
-      <h1>公共安全解决方案</h1>
-      <p class="description">为公共安全领域提供全面的数字化解决方案</p>
-    </div>
+  <div class="page-view">
+    <PageHeader
+      title="公共安全解决方案"
+      description="为公共安全领域提供全面的数字化解决方案"
+    />
 
-    <!-- 子菜单导航 -->
-    <nav class="sub-nav">
-      <router-link
-        v-for="item in subMenuItems"
-        :key="item.path"
-        :to="item.path"
-        class="nav-item"
-        :class="{ active: currentPath === item.path }"
-      >
-        {{ item.title }}
-      </router-link>
-    </nav>
+    <SubNavigation :items="subMenuItems" />
 
     <!-- 子路由视图 -->
     <div class="content">
@@ -46,54 +32,9 @@ const currentPath = computed(() => route.path)
 @use '@/assets/styles/variables' as v;
 @use '@/assets/styles/mixins' as m;
 
-.public-safety-view {
+.page-view {
   padding: v.$spacing-xl v.$spacing-xl * 2;
 
-  .header {
-    text-align: center;
-    margin-bottom: v.$spacing-xl * 2;
-
-    h1 {
-      font-size: v.$font-size-xxl;
-      color: v.$text-primary;
-      margin-bottom: v.$spacing-md;
-    }
-
-    .description {
-      font-size: v.$font-size-lg;
-      color: v.$text-secondary;
-    }
-  }
-
-  .sub-nav {
-    display: flex;
-    justify-content: center;
-    gap: v.$spacing-md;
-    margin-bottom: v.$spacing-xl;
-    padding: v.$spacing-md;
-    background-color: v.$background-light;
-    border-radius: v.$border-radius-lg;
-    box-shadow: v.$shadow-sm;
-
-    .nav-item {
-      padding: v.$spacing-sm v.$spacing-md;
-      color: v.$text-primary;
-      text-decoration: none;
-      border-radius: v.$border-radius-md;
-      transition: all v.$transition-fast;
-
-      &:hover {
-        background-color: rgba(v.$primary-color, 0.1);
-        color: v.$primary-color;
-      }
-
-      &.active {
-        background-color: v.$primary-color;
-        color: white;
-      }
-    }
-  }
-
   .content {
     max-width: 1200px;
     margin: 0 auto;

+ 9 - 68
web/src/views/Enterprise/SafetyProduction/index.vue

@@ -1,8 +1,6 @@
 <script setup lang="ts">
-import { useRoute } from 'vue-router'
-import { computed } from 'vue'
-
-const route = useRoute()
+import PageHeader from '@/components/PageHeader/index.vue'
+import SubNavigation from '@/components/SubNavigation/index.vue'
 
 const subMenuItems = [
   { path: '/enterprise/safety-production/supervision', title: '安全生产部门监管' },
@@ -10,28 +8,16 @@ const subMenuItems = [
   { path: '/enterprise/safety-production/accident-handling', title: '安全生产事故处置' }
 ]
 
-const currentPath = computed(() => route.path)
 </script>
 
 <template>
-  <div class="safety-production-view">
-    <div class="header">
-      <h1>安全生产解决方案</h1>
-      <p class="description">为企业和监管部门提供全面的安全生产管理解决方案</p>
-    </div>
+  <div class="page-view">
+    <PageHeader
+      title="安全生产解决方案"
+      description="为企业和监管部门提供全面的安全生产管理解决方案"
+    />
 
-    <!-- 子菜单导航 -->
-    <nav class="sub-nav">
-      <router-link
-        v-for="item in subMenuItems"
-        :key="item.path"
-        :to="item.path"
-        class="nav-item"
-        :class="{ active: currentPath === item.path }"
-      >
-        {{ item.title }}
-      </router-link>
-    </nav>
+    <SubNavigation :items="subMenuItems" />
 
     <!-- 子路由视图 -->
     <div class="content">
@@ -44,54 +30,9 @@ const currentPath = computed(() => route.path)
 @use '@/assets/styles/variables' as v;
 @use '@/assets/styles/mixins' as m;
 
-.safety-production-view {
+.page-view {
   padding: v.$spacing-xl v.$spacing-xl * 2;
 
-  .header {
-    text-align: center;
-    margin-bottom: v.$spacing-xl * 2;
-
-    h1 {
-      font-size: v.$font-size-xxl;
-      color: v.$text-primary;
-      margin-bottom: v.$spacing-md;
-    }
-
-    .description {
-      font-size: v.$font-size-lg;
-      color: v.$text-secondary;
-    }
-  }
-
-  .sub-nav {
-    display: flex;
-    justify-content: center;
-    gap: v.$spacing-md;
-    margin-bottom: v.$spacing-xl;
-    padding: v.$spacing-md;
-    background-color: v.$background-light;
-    border-radius: v.$border-radius-lg;
-    box-shadow: v.$shadow-sm;
-
-    .nav-item {
-      padding: v.$spacing-sm v.$spacing-md;
-      color: v.$text-primary;
-      text-decoration: none;
-      border-radius: v.$border-radius-md;
-      transition: all v.$transition-fast;
-
-      &:hover {
-        background-color: rgba(v.$primary-color, 0.1);
-        color: v.$primary-color;
-      }
-
-      &.active {
-        background-color: v.$primary-color;
-        color: white;
-      }
-    }
-  }
-
   .content {
     max-width: 1200px;
     margin: 0 auto;