lizhouming před 7 měsíci
rodič
revize
e0ecb6a295

+ 9 - 1
src/router/routes.ts

@@ -13,7 +13,7 @@ const routes: Array<RouteRecordRaw> = [
   {
     path: "/yzy/callback",
     name: "YzyCallback",
-    component: () => import('@/components/YzyCallback/index.vue')
+    component: () => import("@/components/YzyCallback/index.vue")
   },
   {
     path: "/leader",
@@ -125,6 +125,14 @@ const routes: Array<RouteRecordRaw> = [
     meta: {
       title: "签到签退成功"
     }
+  },
+  {
+    path: "/InformationReception/index",
+    name: "InformationReception",
+    component: () => import("@/views/InformationReception/index.vue"),
+    meta: {
+      title: "信息接报"
+    }
   }
 ];
 

+ 256 - 0
src/views/InformationReception/index.vue

@@ -0,0 +1,256 @@
+<template>
+  <div class="table-content">
+    <!-- 筛选和排序区域 -->
+    <div class="filter-sort-area">
+      <div class="filter-item">
+        <span>类型:</span>
+        <el-select
+          v-model="selectedType"
+          placeholder="请选择类型"
+          @change="fetchData"
+        >
+          <el-option
+            v-for="type in types"
+            :key="type"
+            :label="type"
+            :value="type"
+          />
+        </el-select>
+      </div>
+      <div class="filter-item">
+        <span>时间:</span>
+        <el-date-picker
+          v-model="selectedTime"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          @change="fetchData"
+        />
+      </div>
+      <div class="filter-item">
+        <span>排序:</span>
+        <el-radio-group v-model="sortOrder" @change="fetchData">
+          <el-radio-button :label="'asc'">正序</el-radio-button>
+          <el-radio-button :label="'desc'">倒序</el-radio-button>
+        </el-radio-group>
+      </div>
+    </div>
+
+    <!-- 信息列表 -->
+    <div v-for="(item, index) in dataList" :key="index" class="info-box">
+      <div class="status-icon" :class="item.statusClass" />
+      <div class="info-content">
+        <div class="info-header">
+          <div class="info-title">{{ item.title }}</div>
+          <div class="info-time">{{ item.time }}</div>
+        </div>
+        <div class="info-description">{{ item.description }}</div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { ref, onMounted, reactive } from "vue";
+import { selectTask } from "@/api/emergencyCommandMap/JointDuty";
+import { parseTime } from "@/utils/ruoyi";
+
+const newSectionState = reactive({
+  showListDialog: false
+});
+
+// 选中的任务
+const selectedTask = ref({
+  task_id: "",
+  sortBy: "creation_time",
+  pageNum: 2,
+  pageSize: 20
+});
+// ref()创建一个响应式对象
+const dataList = ref([]);
+const showScroll = ref(false);
+
+const props = defineProps<{
+  eventId?: string; // 使用可选属性
+}>();
+
+// 事件接报
+const eventManageState = reactive({
+  showListDialog: false
+});
+
+// 请求数据
+const fetchData = async () => {
+  try {
+    console.log("请求任务数据:", props.eventId);
+    const res = await selectTask({ event_code: props.eventId });
+    res.data.forEach(item => {
+      item.update_time = parseTime(item.update_time);
+      item.statusClass = getStatusClass(item.status);
+    });
+    dataList.value = res.data;
+  } catch (error) {
+    console.error("请求任务数据失败:", error);
+  }
+};
+
+const openUpdateDialog = task => {
+  selectedTask.value = { ...task };
+  newSectionState.showListDialog = true;
+};
+
+const handleUpdateSuccess = updatedData => {
+  console.log("任务进度更新成功:", updatedData);
+  fetchData(); // 重新加载任务列表
+};
+
+const toggleScroll = () => {
+  showScroll.value = !showScroll.value;
+};
+
+// 设置定时器
+const fetchInterval = process.env.NODE_ENV === "development" ? 60000 : 3000; // 每60秒刷新一次(刷新太频繁影响调试)
+let intervalId: number | null = null;
+
+const startFetchingData = () => {
+  if (!intervalId) {
+    intervalId = setInterval(() => {
+      fetchData();
+    }, fetchInterval);
+  }
+};
+
+const stopFetchingData = () => {
+  if (intervalId) {
+    clearInterval(intervalId);
+    intervalId = null;
+  }
+};
+
+// 在组件挂载时开始定时获取数据
+onMounted(() => {
+  if (props.eventId) {
+    fetchData();
+    startFetchingData();
+  }
+});
+
+// 在组件卸载时清除定时器
+onUnmounted(() => {
+  stopFetchingData();
+});
+
+watch(
+  () => props.eventId,
+  newValue => {
+    if (newValue) {
+      fetchData();
+      startFetchingData();
+    } else {
+      stopFetchingData();
+    }
+  },
+  { immediate: true }
+);
+
+// 类型筛选
+const selectedType = ref("");
+const types = ref(["预警", "灾情", "处置", "指挥救援", "公众防范"]);
+
+// 时间筛选
+const selectedTime = ref([null, null]);
+
+// 排序
+const sortOrder = ref("desc");
+
+// 根据状态设置类名的方法
+const getStatusClass = (status: string): string => {
+  switch (status) {
+    case "预警":
+      return "warning-icon";
+    case "灾情":
+      return "disaster-icon";
+    case "处置":
+      return "disposal-icon";
+    case "指挥救援":
+      return "rescue-icon";
+    case "公众防范":
+      return "public-defense-icon";
+    default:
+      return "";
+  }
+};
+</script>
+
+<style scoped>
+.table-content {
+  display: flex;
+  flex-direction: column;
+}
+
+.filter-sort-area {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 16px;
+}
+
+.filter-item {
+  display: flex;
+  align-items: center;
+  margin-right: 16px;
+}
+
+.info-box {
+  display: flex;
+  margin-bottom: 16px;
+}
+
+.status-icon {
+  margin-right: 10px;
+}
+
+.info-content {
+  flex: 1;
+}
+
+.info-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.info-title {
+  font-weight: bold;
+}
+
+.info-time {
+  font-size: 0.8em;
+  color: #888;
+}
+
+.info-description {
+  color: #333;
+}
+
+/* 添加状态图标的样式 */
+.warning-icon {
+  /* 预警图标样式 */
+}
+
+.disaster-icon {
+  /* 灾情图标样式 */
+}
+
+.disposal-icon {
+  /* 处置图标样式 */
+}
+
+.rescue-icon {
+  /* 指挥救援图标样式 */
+}
+
+.public-defense-icon {
+  /* 公众防范图标样式 */
+}
+</style>

+ 111 - 96
src/views/leader/index.vue

@@ -3,24 +3,29 @@
     <div class="container-header">
       <div ref="searchBoxRef" class="search-box">
         <van-search
-            v-model="queryParams.keywords"
-            class="common-search"
-            :left-icon="searchImg"
-            :right-icon="closeImg"
-            placeholder="请输入搜索内容"
-            @search="on_search_keyword"
+          v-model="queryParams.keywords"
+          class="common-search"
+          :left-icon="searchImg"
+          :right-icon="closeImg"
+          placeholder="请输入搜索内容"
+          @search="on_search_keyword"
         />
         <div v-show="showSearch" class="search-list">
           <van-list
-              v-model:loading="loading"
-              v-model:error="error"
-              error-text="请求失败,点击重新加载"
-              :finished="finished"
-              finished-text="没有更多事件了"
-              :immediate-check="false"
-              @load="getSearchList"
+            v-model:loading="loading"
+            v-model:error="error"
+            error-text="请求失败,点击重新加载"
+            :finished="finished"
+            finished-text="没有更多事件了"
+            :immediate-check="false"
+            @load="getSearchList"
           >
-            <div v-for="(item, index) in searchList" :key="index" class="item" @click="handleClickItem(item)">
+            <div
+              v-for="(item, index) in searchList"
+              :key="index"
+              class="item"
+              @click="handleClickItem(item)"
+            >
               {{ item.name }}
             </div>
           </van-list>
@@ -29,19 +34,23 @@
     </div>
     <div class="container-content">
       <van-notice-bar
-          @click="handleNoticeBar"
-          v-show="noticeBarState.show"
-          :left-icon="noticeImg"
-          scrollable
-          background="linear-gradient(180deg, #F3F7FF 0%, #FDFEFF 100%)"
-          mode="closeable"
-          :text="noticeBarState.event_title"
+        v-show="noticeBarState.show"
+        :left-icon="noticeImg"
+        scrollable
+        background="linear-gradient(180deg, #F3F7FF 0%, #FDFEFF 100%)"
+        mode="closeable"
+        :text="noticeBarState.event_title"
+        @click="handleNoticeBar"
       />
       <div class="padding-content">
         <van-grid :column-num="2">
-          <van-grid-item v-for="(item, index) in menu" :key="index" @click="handleClickMenu(item.url)">
+          <van-grid-item
+            v-for="(item, index) in menu"
+            :key="index"
+            @click="handleClickMenu(item.url)"
+          >
             <div class="card">
-              <div :class="item.icon"></div>
+              <div :class="item.icon" />
               <van-badge :content="item.num" max="99" :show-zero="false">
                 <div class="card-title">{{ item.name }}</div>
               </van-badge>
@@ -53,7 +62,12 @@
           <div v-for="(item, index) in menu2" :key="index" class="box">
             <div class="box-title">{{ item.name }}</div>
             <div class="box-content">
-              <div v-for="(item2, index2) in item.children" :key="index2" class="box-item"  @click="handleClickMenu(item.url)">
+              <div
+                v-for="(item2, index2) in item.children"
+                :key="index2"
+                class="box-item"
+                @click="handleClickMenu(item.url)"
+              >
                 <img class="icon" :src="getImageUrl(item2.icon)" alt="" />
                 <span>{{ item2.name }}</span>
               </div>
@@ -66,73 +80,73 @@
 </template>
 
 <script lang="ts" setup>
-import {onClickOutside} from "@vueuse/core";
-import { ref, reactive, onMounted } from 'vue';
+import { onClickOutside } from "@vueuse/core";
+import { ref, reactive, onMounted } from "vue";
 import { getActiveEventList } from "@/api/event";
-import noticeImg from '@/assets/images/notice.png'
-import searchImg from '@/assets/images/search.png'
-import {useRouter} from "vue-router";
+import noticeImg from "@/assets/images/notice.png";
+import searchImg from "@/assets/images/search.png";
+import { useRouter } from "vue-router";
 import closeImg from "@/assets/images/close.png";
-import {getPointInfoComprehensiveSearch} from "@/api/globalMap";
+import { getPointInfoComprehensiveSearch } from "@/api/globalMap";
 
 const router = useRouter();
 const noticeBarState = reactive({
   show: false,
-  event_id: '',
-  event_title: ''
-})
+  event_id: "",
+  event_title: ""
+});
 
 const handleNoticeBar = () => {
   console.log(noticeBarState.event_title);
-}
+};
 // 菜单数据
 const menu = ref([
-  { name: '工作审批', icon: 'icon1', num: 0, url: '' },
-  { name: '信息接报', icon: 'icon2', num: 0, url: '' },
-  { name: '在线点名', icon: 'icon3', num: 0, url: '' },
-  { name: '事件管理', icon: 'icon4', num: 0, url: 'EventList' },
+  { name: "工作审批", icon: "icon1", num: 0, url: "" },
+  { name: "信息接报", icon: "icon2", num: 0, url: "InformationReception" },
+  { name: "在线点名", icon: "icon3", num: 0, url: "" },
+  { name: "事件管理", icon: "icon4", num: 0, url: "EventList" }
 ]);
 
 // 综合应用菜单
 const menu2 = ref([
   {
-    name: '自然灾害风险监测',
+    name: "自然灾害风险监测",
     children: [
-      { name: '灾害监测', icon: 'monitor', url: '' },
-      { name: '大风灾害', icon: 'wind', url: '' },
-      { name: '森林火灾', icon: 'forestFire', url: '' },
-      { name: '台风实况', icon: 'typhoon', url: '' },
-      { name: '水文监测', icon: 'hydrology', url: '' }
+      { name: "灾害监测", icon: "monitor", url: "" },
+      { name: "大风灾害", icon: "wind", url: "" },
+      { name: "森林火灾", icon: "forestFire", url: "" },
+      { name: "台风实况", icon: "typhoon", url: "" },
+      { name: "水文监测", icon: "hydrology", url: "" }
     ]
   },
   {
-    name: '应急事件场景专题',
+    name: "应急事件场景专题",
     children: [
-      { name: '自然灾害', icon: 'nature', url: '' },
-      { name: '事故灾害', icon: 'accident', url: '' },
-      { name: '城市事件', icon: 'city', url: '' }
+      { name: "自然灾害", icon: "nature", url: "" },
+      { name: "事故灾害", icon: "accident", url: "" },
+      { name: "城市事件", icon: "city", url: "" }
     ]
   }
-])
-const handleClickMenu = (url) => {
+]);
+const handleClickMenu = url => {
   if (!url) return;
   router.push({ name: url });
-}
-const getImageUrl = (name) => {
+};
+const getImageUrl = name => {
   return new URL(`../../assets/images/index/${name}.png`, import.meta.url).href;
 };
 
 const initData = () => {
   // 通知栏数据
-  getActiveEventList().then((res) => {
-    if(res.data.event_id != noticeBarState.event_id) {
-      noticeBarState.show = true
+  getActiveEventList().then(res => {
+    if (res.data.event_id != noticeBarState.event_id) {
+      noticeBarState.show = true;
       noticeBarState.event_id = res.data.event_id;
       noticeBarState.event_title = res.data.event_title;
     }
-  })
+  });
   // 菜单数据
-}
+};
 // 搜索
 const searchBoxRef = ref();
 let showSearch = ref();
@@ -143,54 +157,57 @@ let finished = ref(false);
 const queryParams = reactive({
   page: 0,
   page_size: 15,
-  keywords: ''
+  keywords: ""
 });
 const searchList = ref([]);
-onClickOutside(searchBoxRef, (event) => {
+onClickOutside(searchBoxRef, event => {
   showSearch.value = false;
-})
+});
 const getSearchList = () => {
-  if (!queryParams.keywords){
-    return loading.value = false;
+  if (!queryParams.keywords) {
+    return (loading.value = false);
   }
   queryParams.page++;
-  getPointInfoComprehensiveSearch(queryParams).then((res) => {
-    const items = res.data.list || [];
-    total.value = res.data.total;
-    if (queryParams.page == 1) {
-      searchList.value = [];
-    }
-    items.forEach((val) => {
-      searchList.value.push(val)
-    });
-    if (queryParams.page_size * queryParams.page >= total.value) {
-      finished.value = true;
-    } else {
+  getPointInfoComprehensiveSearch(queryParams)
+    .then(res => {
+      const items = res.data.list || [];
+      total.value = res.data.total;
+      if (queryParams.page == 1) {
+        searchList.value = [];
+      }
+      items.forEach(val => {
+        searchList.value.push(val);
+      });
+      if (queryParams.page_size * queryParams.page >= total.value) {
+        finished.value = true;
+      } else {
+        finished.value = false;
+      }
+      showSearch.value = true;
+    })
+    .catch(() => {
+      error.value = true;
       finished.value = false;
-    }
-    showSearch.value = true;
-  }).catch(() => {
-    error.value = true;
-    finished.value = false;
-  }).finally(() => {
-    loading.value = false;
-  });
-}
-const on_search_keyword = (val) => {
+    })
+    .finally(() => {
+      loading.value = false;
+    });
+};
+const on_search_keyword = val => {
   queryParams.keywords = val;
   queryParams.page = 0;
   getSearchList();
-}
-const handleClickItem = (item) => {
+};
+const handleClickItem = item => {
   showSearch.value = false;
-  queryParams.keywords = '';
+  queryParams.keywords = "";
   queryParams.page = 0;
   finished.value = false;
   searchList.value = [];
-}
+};
 onMounted(() => {
-  initData()
-})
+  initData();
+});
 </script>
 
 <style lang="scss" scoped>
@@ -203,7 +220,7 @@ onMounted(() => {
 .container-header {
   width: 100%;
   height: 370px;
-  background: url('@/assets/images/index/banner.png') no-repeat;
+  background: url("@/assets/images/index/banner.png") no-repeat;
   background-size: 100% 100%;
   display: flex;
   flex-direction: column;
@@ -231,7 +248,6 @@ onMounted(() => {
     border-top-width: 0 !important;
   }
   :deep(.van-grid) {
-
     .van-grid-item {
       &:nth-child(1) {
         padding-right: 12px;
@@ -267,7 +283,7 @@ onMounted(() => {
         }
         .card-title {
           font-size: 14px;
-          color: #414F64;
+          color: #414f64;
         }
       }
       .icon1 {
@@ -285,8 +301,7 @@ onMounted(() => {
       .icon1,
       .icon2,
       .icon3,
-      .icon4
-      {
+      .icon4 {
         width: 67px;
         height: 67px;
         background-size: 100% 100%;
@@ -308,7 +323,7 @@ onMounted(() => {
     height: 26px;
     font-weight: bold;
     font-size: 18px;
-    color: #414F64;
+    color: #414f64;
     letter-spacing: 0;
     margin-bottom: 4px;
   }