Browse Source

功能点完善

yangyuxuan 1 month ago
parent
commit
ea4f2fac8a

+ 10 - 0
src/router/routes.ts

@@ -97,6 +97,16 @@ export const constantRoutes: Array<RouteRecordRaw> = [
       noCache: true
     }
   },
+  {
+    path: "/cityEmergencyDetails",
+    name: "CityEmergencyDetails",
+    component: () =>
+      import("@/views/disasterRiskMonitor/cityEmergencyDetails.vue"),
+    meta: {
+      title: "城市应急事件详情",
+      noCache: true
+    }
+  },
   {
     path: "/rainfallMonitoring",
     name: "RainfallMonitoring",

+ 480 - 0
src/views/disasterRiskMonitor/cityEmergencyDetails.vue

@@ -0,0 +1,480 @@
+<template>
+  <div class="container">
+    <div class="box">
+      <div class="title">事件详情</div>
+      <van-form disabled>
+        <van-cell-group inset>
+          <van-field v-model="detailsData.address" label="位置" />
+          <van-field v-model="detailsData.type" label="灾害类型" />
+          <van-field v-model="detailsData.data3" label="发生时间" />
+          <van-field v-model="detailsData.data4" label="受伤人数" />
+          <van-field v-model="detailsData.data5" label="死亡人数" />
+        </van-cell-group>
+      </van-form>
+    </div>
+    <div class="box">
+      <div class="title">事件回溯</div>
+      <div class="modern-timeline" style="margin-bottom: 20px">
+        <div
+          v-for="(event, index) in timelineEvents"
+          :key="index"
+          class="timeline-item"
+          :class="{ active: currentProgress >= event.progress }"
+        >
+          <div class="timeline-marker">
+            <div class="marker-dot" />
+            <div
+              v-if="index !== timelineEvents.length - 1"
+              class="marker-line"
+            />
+          </div>
+          <div class="timeline-content">
+            <div class="timeline-time">{{ event.time }}</div>
+            <div class="timeline-desc">{{ event.description }}</div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="box">
+      <div class="title">事件动态</div>
+      <div class="modern-timeline green-timeline" style="margin-bottom: 20px">
+        <div
+          v-for="(event, index) in timelineEvents2"
+          :key="index"
+          class="timeline-item"
+          :class="{ active: event.time }"
+        >
+          <div class="timeline-marker">
+            <div class="marker-dot" />
+            <div
+              v-if="index !== timelineEvents2.length - 1"
+              class="marker-line"
+            />
+          </div>
+          <div class="timeline-content">
+            <div class="timeline-time">{{ event.time }}</div>
+            <div class="timeline-desc">{{ event.description }}</div>
+            <div v-if="event.time" class="timeline-status">
+              <van-icon name="passed" color="#4CAF50" />
+              <span>已完成</span>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref } from "vue";
+
+const route = useRoute();
+const informId = ref(route.query.id);
+
+const detailsData = ref({
+  type: "自然灾害",
+  address: "茂名市电白区黄岭镇石头村",
+  data3: "2024-12-14 12:12:13",
+  data4: 1,
+  data5: 0,
+  longitude: "110.719914",
+  latitude: "21.609269",
+  dataType: "1"
+});
+const timelineEvents = ref([
+  {
+    time: "12:00:00",
+    description: "地震初波到达",
+    progress: 20
+  },
+  {
+    time: "12:00:05",
+    description: "强震波到达",
+    progress: 40
+  },
+  {
+    time: "12:00:15",
+    description: "首次余震发生",
+    progress: 60
+  },
+  {
+    time: "12:01:30",
+    description: "救援系统启动",
+    progress: 80
+  },
+  {
+    time: "12:05:00",
+    description: "现场救援到达",
+    progress: 100
+  }
+]);
+const timelineEvents2 = ref([
+  {
+    time: "12:00:00",
+    description: "地震发生"
+  },
+  {
+    time: "12:00:05",
+    description: "余震发生"
+  },
+  {
+    time: "12:00:15",
+    description: "救援系统启动"
+  },
+  {
+    time: "12:01:30",
+    description: "现场救援到达"
+  },
+  {
+    time: "12:05:00",
+    description: "后续处理1"
+  },
+  {
+    time: "14:05:00",
+    description: "后续处理2"
+  },
+  {
+    time: "16:05:00",
+    description: "后续处理3"
+  }
+]);
+
+const progress = ref(100); // 当前进度百分比
+const currentProgress = ref(100); // 当前激活的事件进度
+const progress1 = ref(30); // 当前进度百分比
+const currentProgress1 = ref(0); // 当前激活的事件进度
+
+const setProgress = (value: number) => {
+  progress1.value = value;
+  currentProgress1.value = value;
+};
+</script>
+
+<style scoped lang="scss">
+.container {
+  height: 100vh;
+  padding: 8px 16px;
+  .box {
+    background-color: #ffffff;
+    border: 1px solid #eaedf7;
+    box-shadow: 0 0 4px 0 #4554661a;
+    border-radius: 4px;
+    background-image: linear-gradient(
+      to bottom,
+      #f3f7fd 0%,
+      #f7fafe 20px,
+      #fcfdff 50px,
+      #ffffff 50px,
+      #ffffff 100%
+    );
+    padding: 10px 16px;
+    margin-bottom: 10px;
+    .icon-line {
+      display: inline-block;
+      width: 6px;
+      height: 16px;
+      background: url("@/assets/images/line.jpg") no-repeat;
+      background-size: 100% 100%;
+      margin-right: 3px;
+    }
+    .box-item {
+      display: flex;
+      align-items: center;
+      height: 30px;
+      .box-tag {
+        flex: 1;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+      }
+      .tag-active {
+        background-color: #5f9ff2;
+        border-radius: 4px;
+        color: #ffffff;
+      }
+    }
+  }
+}
+/* 移除表单容器背景 */
+:deep(.van-cell-group) {
+  background: transparent !important;
+}
+
+/* 移除每个表单项的背景 */
+:deep(.van-cell) {
+  background: transparent !important;
+}
+
+/* 移除内嵌容器的边距和阴影 */
+:deep(.van-cell-group--inset) {
+  margin: 0;
+  box-shadow: none;
+  &::after {
+    border: none !important;
+  }
+}
+:deep(.van-field--disabled) {
+  .van-field__label,
+  .van-field__control {
+    color: rgba(12, 12, 12, 0.93) !important;
+    -webkit-text-fill-color: #4a4848 !important;
+  }
+
+  /* 移除禁用蒙层 */
+  .van-field__disabled-mask {
+    display: none !important;
+  }
+}
+
+.title {
+  font-size: 18px;
+  font-weight: bold;
+  line-height: 32px;
+  width: 100%;
+  text-align: center;
+  margin-bottom: 8px;
+}
+.timeline-container {
+  display: flex;
+  margin-top: 16px;
+  position: relative;
+}
+
+/* 进度条轨道 */
+.progress-track {
+  width: 6px;
+  height: 300px;
+  background-color: #f0f0f0;
+  border-radius: 3px;
+  margin-right: 16px;
+  position: relative;
+}
+
+/* 进度条 */
+.progress-bar {
+  position: absolute;
+  bottom: 0;
+  width: 100%;
+  background: linear-gradient(to top, #4facfe 0%, #00f2fe 100%);
+  border-radius: 3px;
+  transition: height 0.5s ease;
+}
+
+/* 时间轴内容 */
+.timeline-content {
+  flex: 1;
+}
+
+.timeline-event {
+  display: flex;
+  margin-bottom: 24px;
+  cursor: pointer;
+  transition: all 0.3s ease;
+
+  &.active {
+    .event-dot {
+      background: #4facfe;
+      transform: scale(1.2);
+    }
+    .event-time {
+      color: #4facfe;
+      font-weight: bold;
+    }
+  }
+}
+
+.event-dot {
+  width: 12px;
+  height: 12px;
+  border-radius: 50%;
+  background: #ccc;
+  margin-right: 12px;
+  margin-top: 3px;
+  flex-shrink: 0;
+  transition: all 0.3s ease;
+  border: 2px solid white;
+  box-shadow: 0 0 0 2px #f0f0f0;
+}
+
+.event-content {
+  flex: 1;
+}
+
+.event-time {
+  font-size: 14px;
+  color: #666;
+  margin-bottom: 4px;
+}
+
+.event-desc {
+  font-size: 14px;
+  color: #333;
+  line-height: 1.4;
+}
+
+/* 动画效果 */
+@keyframes pulse {
+  0% {
+    box-shadow: 0 0 0 0 rgba(79, 172, 254, 0.4);
+  }
+  70% {
+    box-shadow: 0 0 0 6px rgba(79, 172, 254, 0);
+  }
+  100% {
+    box-shadow: 0 0 0 0 rgba(79, 172, 254, 0);
+  }
+}
+
+.active .event-dot {
+  animation: pulse 1.5s infinite;
+}
+.modern-timeline {
+  position: relative;
+  padding-left: 40px;
+  margin-top: 16px;
+}
+
+.timeline-item {
+  position: relative;
+  padding-bottom: 24px;
+  cursor: pointer;
+  transition: all 0.3s ease;
+  min-height: 36px;
+
+  &:last-child {
+    padding-bottom: 0;
+  }
+}
+
+.timeline-marker {
+  position: absolute;
+  left: -32px;
+  top: 0;
+  width: 32px;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+.marker-dot {
+  width: 14px;
+  height: 14px;
+  border-radius: 50%;
+  background: #e0e0e0;
+  border: 3px solid white;
+  box-shadow: 0 0 0 2px #e0e0e0;
+  z-index: 2;
+  transition: all 0.3s ease;
+  margin-top: 4px;
+}
+
+.marker-line {
+  flex: 1;
+  width: 2px;
+  background: #e0e0e0;
+  margin-top: 4px;
+  transition: all 0.3s ease;
+}
+
+.timeline-content {
+  padding-left: 16px;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  min-height: 36px;
+}
+
+.timeline-time {
+  font-size: 14px;
+  font-weight: 500;
+  color: #666;
+  margin-bottom: 4px;
+  transition: all 0.3s ease;
+  line-height: 1.2;
+  margin-top: -2px;
+}
+
+.timeline-desc {
+  font-size: 14px;
+  color: #333;
+  line-height: 1.4;
+  transition: all 0.3s ease;
+}
+
+/* 激活状态样式 */
+.timeline-item.active {
+  .marker-dot {
+    background: #4facfe;
+    box-shadow: 0 0 0 2px #4facfe;
+    transform: scale(1.1);
+  }
+
+  .marker-line {
+    background: linear-gradient(to bottom, #4facfe, #00f2fe);
+  }
+
+  .timeline-time {
+    color: #4facfe;
+    font-weight: bold;
+  }
+
+  .timeline-desc {
+    color: #222;
+    font-weight: 500;
+  }
+}
+
+.timeline-item.active .marker-dot {
+  animation: pulse 1.5s infinite;
+}
+
+.green-timeline {
+  .timeline-item.active {
+    .marker-dot {
+      background: #4caf50;
+      box-shadow: 0 0 0 2px #4caf50;
+      animation: pulse-green 1.5s infinite;
+    }
+
+    .marker-line {
+      background: linear-gradient(to bottom, #4caf50, #8bc34a);
+    }
+
+    .timeline-time {
+      color: #4caf50;
+      font-weight: bold;
+    }
+
+    .timeline-desc {
+      color: #222;
+      font-weight: 500;
+    }
+  }
+
+  .timeline-status {
+    display: flex;
+    align-items: center;
+    margin-top: 4px;
+    font-size: 12px;
+    color: #4caf50;
+
+    .van-icon {
+      margin-right: 4px;
+    }
+  }
+}
+
+/* 绿色脉冲动画 */
+@keyframes pulse-green {
+  0% {
+    box-shadow: 0 0 0 0 rgba(76, 175, 80, 0.4);
+  }
+  70% {
+    box-shadow: 0 0 0 8px rgba(76, 175, 80, 0);
+  }
+  100% {
+    box-shadow: 0 0 0 0 rgba(76, 175, 80, 0);
+  }
+}
+</style>

+ 46 - 28
src/views/disasterRiskMonitor/cityEmergencyEvent.vue

@@ -14,12 +14,12 @@
     </div>
     <div ref="searchBoxRef" class="search-box">
       <van-search
-          v-model="queryParams.keywords"
-          placeholder="请输入位置信息"
-          class="common-search"
-          :left-icon="searchImg"
-          show-action
-          @search="onSearchKeyword"
+        v-model="queryParams.keywords"
+        placeholder="请输入位置信息"
+        class="common-search"
+        :left-icon="searchImg"
+        show-action
+        @search="onSearchKeyword"
       >
         <template #action>
           <div class="search-btn" @click="onSearchKeyword">搜索</div>
@@ -46,13 +46,13 @@
         </van-list>
       </div>
     </div>
-    <div class="content" style="margin-top: 0;">
+    <div class="content" style="margin-top: 0">
       <Map
-          ref="mapRef"
-          class="map"
-          active-map="satellite"
-          :event-details="eventDetails"
-          @onLoadCompleted="initData"
+        ref="mapRef"
+        class="map"
+        active-map="satellite"
+        :event-details="eventDetails"
+        @onLoadCompleted="initData"
       />
     </div>
     <div class="content">
@@ -73,7 +73,7 @@
         <div class="select-box" @click="showPicker = true">
           <div class="text1">年度</div>
           <div class="select-item">
-            <div class="label">{{ yearLabel ? yearLabel : '请选择' }}</div>
+            <div class="label">{{ yearLabel ? yearLabel : "请选择" }}</div>
             <i class="icon-down" />
           </div>
         </div>
@@ -83,6 +83,17 @@
           <el-table-column label="发生时间" prop="data3" align="center" />
           <el-table-column label="受伤人数" prop="data4" align="center" />
           <el-table-column label="死亡人数" prop="data5" align="center" />
+          <!--          <el-table-column label="操作" align="center" width="50px">-->
+          <!--            <template #default="scope">-->
+          <!--              <div-->
+          <!--                class="btn"-->
+          <!--                style="color: #1d92ff"-->
+          <!--                @click="showDetails(scope.row)"-->
+          <!--              >-->
+          <!--                详情-->
+          <!--              </div>-->
+          <!--            </template>-->
+          <!--          </el-table-column>-->
         </el-table>
       </div>
     </div>
@@ -112,8 +123,9 @@ const router = useRouter();
 const noticeBarState = reactive({
   show: false,
   event_id: "",
-  time: '2024-03-01 12:12:12',
-  event_title: "茂名市茂南区xxx高速路口发生交通事故,今日凌晨三点在xx高速路口,由于突降暴雨路面湿滑,导致路面积水严重,不少路过车辆都减速慢行…"
+  time: "2024-03-01 12:12:12",
+  event_title:
+    "茂名市茂南区xxx高速路口发生交通事故,今日凌晨三点在xx高速路口,由于突降暴雨路面湿滑,导致路面积水严重,不少路过车辆都减速慢行…"
 });
 const handleNoticeBar = () => {};
 // 搜索
@@ -217,6 +229,9 @@ const onPickerConfirm = ({ selectedOptions }) => {
   yearLabel.value = selectedOptions[0].text;
   queryParams.year = selectedOptions[0].value;
 };
+const showDetails = row => {
+  router.push({ name: "CityEmergencyDetails", query: { id: row.id } });
+};
 const initData = () => {
   const dom = mapRef.value;
   // getActiveEventList().then(res => {
@@ -392,9 +407,10 @@ const initData = () => {
     position: relative;
     width: 375px;
     height: 117px;
-    background: url('@/assets/images/disasterRiskMonitor/cityEmergencyEvent/box1.png') no-repeat;
+    background: url("@/assets/images/disasterRiskMonitor/cityEmergencyEvent/box1.png")
+      no-repeat;
     background-size: 100% 100%;
-    box-shadow:0 2px 4px 0 rgba(228, 240, 255, 1);
+    box-shadow: 0 2px 4px 0 rgba(228, 240, 255, 1);
     .box-header {
       display: flex;
       justify-content: space-between;
@@ -402,32 +418,33 @@ const initData = () => {
       padding: 0 6px;
       .more {
         font-size: 12px;
-        color: #2C81FF;
+        color: #2c81ff;
       }
     }
     .title-box {
       height: 30px;
       background-color: #ffffff; /* 背景颜色 */
       transform: skewX(-20deg); /* 斜切变形 */
-      box-shadow:0 2px 4px 0 rgba(250, 217, 97, 0.18);
+      box-shadow: 0 2px 4px 0 rgba(250, 217, 97, 0.18);
       padding: 0 10px;
       display: flex;
       align-items: center;
       border-radius: 2px;
       &::after {
-        content: '';
+        content: "";
         position: absolute;
         top: 0;
         right: -6px;
         transform: skewX(20deg);
         width: 11px;
         height: 27px;
-        background: url('@/assets/images/disasterRiskMonitor/riverMonitor/thickness.png') no-repeat;
+        background: url("@/assets/images/disasterRiskMonitor/riverMonitor/thickness.png")
+          no-repeat;
         background-size: 100% 100%;
       }
       .title {
         font-size: 14px;
-        color: #FFAF00;
+        color: #ffaf00;
         transform: skewX(20deg);
         display: flex;
         align-items: center;
@@ -435,7 +452,8 @@ const initData = () => {
           display: inline-block;
           width: 16px;
           height: 16px;
-          background: url('@/assets/images/disasterRiskMonitor/riverMonitor/speaker.png') no-repeat;
+          background: url("@/assets/images/disasterRiskMonitor/riverMonitor/speaker.png")
+            no-repeat;
           background-size: 100% 100%;
           margin-right: 5px;
         }
@@ -451,7 +469,7 @@ const initData = () => {
       overflow: hidden;
       text-overflow: ellipsis;
       font-size: 14px;
-      color: #414F64;
+      color: #414f64;
     }
     .text2 {
       font-size: 12px;
@@ -530,7 +548,7 @@ const initData = () => {
     align-items: center;
     border-top-left-radius: 4px;
     border-top-right-radius: 4px;
-    background-image: linear-gradient(180deg, #F3F7FD 0%, #FFFFFF 100%);
+    background-image: linear-gradient(180deg, #f3f7fd 0%, #ffffff 100%);
     .icon-line {
       display: inline-block;
       width: 6px;
@@ -553,7 +571,7 @@ const initData = () => {
   padding-right: 20px;
   .text1 {
     font-size: 14px;
-    color: #414F64;
+    color: #414f64;
     margin-right: 5px;
   }
   .select-item {
@@ -563,7 +581,7 @@ const initData = () => {
     height: 32px;
     border-raduis: 4px;
     font-size: 14px;
-    color: #414F64;
+    color: #414f64;
     display: flex;
     align-items: center;
     .label {
@@ -574,7 +592,7 @@ const initData = () => {
       display: inline-block;
       width: 14px;
       height: 14px;
-      background: url('@/assets/images/down.png') no-repeat;
+      background: url("@/assets/images/down.png") no-repeat;
       background-size: 100% 100%;
       margin-left: 5px;
     }

+ 3 - 3
src/views/disasterRiskMonitor/emergencyTrafficAccidents.vue

@@ -101,7 +101,7 @@
           </div>
         </div>
         <el-table :data="detailsData.dataList" border table-layout="auto">
-          <el-table-column label="类" prop="data1" align="center" />
+          <el-table-column label="类" prop="data1" align="center" />
           <el-table-column label="位置" prop="data2" align="center" />
           <el-table-column label="发生时间" prop="data3" align="center" />
           <el-table-column label="受伤人数" prop="data4" align="center" />
@@ -192,7 +192,7 @@ const initData = () => {
   // 事件列表
   detailsData.value.dataList = [
     {
-      data1: "一般事故",
+      data1: "追尾",
       data2: "茂名市电白区黄岭镇石头村",
       data3: "2024-12-14 12:12:13",
       data4: 1,
@@ -202,7 +202,7 @@ const initData = () => {
       dataType: "1"
     },
     {
-      data1: "重大事故",
+      data1: "碰撞行人",
       data2: "茂名市茂南区羊角镇",
       data3: "2024-10-07 08:00:00",
       data4: 2,

+ 3 - 3
src/views/leader/index.vue

@@ -152,8 +152,8 @@ const menu2 = ref([
       { name: "隐患点雨量", icon: "geologicalDisasterRainfall", url: "RainfallMonitoring" },
       { name: "雨窝点雨量", icon: "rainShelter", url: "RainfallInRainShelter" },
       { name: "危化企业雨量", icon: "hazardousChemicalEnterprises", url: "HazardousChemicalEnterprises" },
-      { name: "烟花事故", icon: "hazardousChemicalEnterprises", url: "FireworksEmergency" },
-      { name: "交通事故", icon: "hazardousChemicalEnterprises", url: "EmergencyTrafficAccidents" }
+      // { name: "烟花事故", icon: "hazardousChemicalEnterprises", url: "FireworksEmergency" },
+      // { name: "交通事故", icon: "hazardousChemicalEnterprises", url: "EmergencyTrafficAccidents" }
     ]
   }
 ]);
@@ -412,7 +412,7 @@ onUnmounted(() => {
   .box,
   .box2 {
     width: 100%;
-    height: 210px;
+    height: 150px;
     background: url("@/assets/images/index/boxBg.png") no-repeat;
     background-size: 100% 100%;
     margin-bottom: 12px;