Prechádzať zdrojové kódy

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	src/views/leader/index.vue
Hwf 7 mesiacov pred
rodič
commit
2220252d6d

+ 37 - 30
src/api/emergencyCommandMap/JointDuty.ts

@@ -1,22 +1,24 @@
-import request from '@/utils/request';
-import CryptoJS from 'crypto-js';
-import { nanoid } from 'nanoid';
+import request from "@/utils/request";
+import CryptoJS from "crypto-js";
+import { nanoid } from "nanoid";
 
 // 二维码
-export const getMapProduct = (data) => {
+export const getMapProduct = data => {
   const nonce = nanoid();
   const timestampHeader = (Date.now() / 1000).toFixed();
-  const token = 'dsfsdfsdfsf';
-  const signatureHeader = CryptoJS.SHA256(timestampHeader + token + nonce + timestampHeader).toString(CryptoJS.enc.Hex);
+  const token = "dsfsdfsdfsf";
+  const signatureHeader = CryptoJS.SHA256(
+    timestampHeader + token + nonce + timestampHeader
+  ).toString(CryptoJS.enc.Hex);
   return request({
-    url: 'https://yzh.gdgov.cn/yzm-generator/generateCode',
-    method: 'POST',
+    url: "https://yzh.gdgov.cn/yzm-generator/generateCode",
+    method: "POST",
     headers: {
-      'x-yzm-nonce': nonce,
-      'x-yzm-signature': signatureHeader,
-      'x-yzm-paasid': token,
-      'x-yzm-timestamp': timestampHeader,
-      'Content-Type': 'application/json;charset=utf-8'
+      "x-yzm-nonce": nonce,
+      "x-yzm-signature": signatureHeader,
+      "x-yzm-paasid": token,
+      "x-yzm-timestamp": timestampHeader,
+      "Content-Type": "application/json;charset=utf-8"
     },
     data: {
       id: data.id,
@@ -30,8 +32,8 @@ export const getMapProduct = (data) => {
 // 获取签名列表
 export function getCheckinList(eventId: string) {
   return request({
-    url: '/api/event_management/checkin/list',
-    method: 'get',
+    url: "/api/event_management/checkin/list",
+    method: "get",
     params: {
       event_id: eventId
     }
@@ -39,10 +41,15 @@ export function getCheckinList(eventId: string) {
 }
 
 // 更新事发地点 (用于将表单数据发送到服务器以更新某个事件的位置信息)
-export function updateEventLocation(eventId: string, address: string, longitude: string, latitude: string) {
+export function updateEventLocation(
+  eventId: string,
+  address: string,
+  longitude: string,
+  latitude: string
+) {
   return request({
-    url: '/api/event_management/event/save_address',
-    method: 'post',
+    url: "/api/event_management/event/save_address",
+    method: "post",
     params: {
       eventId: eventId,
       address: address,
@@ -55,32 +62,32 @@ export function updateEventLocation(eventId: string, address: string, longitude:
 // 新建事件
 export function addEvent(data) {
   return request({
-    url: '/api/event_management/event/create',
-    method: 'post',
+    url: "/api/event_management/event/create",
+    method: "post",
     data: data
   });
 }
 // 任务新增
 export function addTask(data) {
   return request({
-    url: '/api/taskRegistration/create',
-    method: 'post',
+    url: "/api/taskRegistration/create",
+    method: "post",
     data: data
   });
 }
 // 任务查询
 export function selectTask(params) {
   return request({
-    url: '/api/taskRegistration/select',
-    method: 'get',
+    url: "/api/taskRegistration/select",
+    method: "get",
     params: params
   });
 }
 // 任务更新
 export function updateTaskRegistration(data) {
   return request({
-    url: '/api/taskRegistration/update',
-    method: 'put',
+    url: "/api/taskRegistration/update",
+    method: "put",
     data: data
   });
 }
@@ -88,8 +95,8 @@ export function updateTaskRegistration(data) {
 // 查看事业单位
 export function getUnits(params) {
   return request({
-    url: '/api/taskRegistration/selectUnit',
-    method: 'get',
+    url: "/api/taskRegistration/selectUnit",
+    method: "get",
     params: params
   });
 }
@@ -97,8 +104,8 @@ export function getUnits(params) {
 // 任务删除
 export function deleteTask(data) {
   return request({
-    url: '/api/taskRegistration/delete',
-    method: 'post',
+    url: "/api/taskRegistration/delete",
+    method: "post",
     data: data
   });
 }

+ 42 - 6
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",
@@ -139,7 +139,8 @@ const routes: Array<RouteRecordRaw> = [
   {
     path: "/districtCountyRollCall",
     name: "DistrictCountyRollCall",
-    component: () => import("@/views/onlineRollCall/districtCountyRollCall.vue"),
+    component: () =>
+      import("@/views/onlineRollCall/districtCountyRollCall.vue"),
     meta: {
       title: "分区县点名",
       noCache: true
@@ -167,14 +168,32 @@ const routes: Array<RouteRecordRaw> = [
     path: "/worker",
     name: "Worker",
     component: Layout,
-    redirect: { name: "WokerIndex" },
+    redirect: { name: "WorkerIndex" },
     children: [
       {
         path: "index2",
-        name: "WokerIndex",
+        name: "WorkerIndex",
         component: () => import("@/views/worker/index.vue"),
         meta: {
-          title: "主页3"
+          title: "首页"
+        }
+      },
+      {
+        path: "event",
+        name: "Event",
+        component: () => import("@/views/event/detail.vue"),
+        meta: {
+          title: "事件管理",
+          noCache: true
+        }
+      },
+      {
+        path: "duty",
+        name: "DutyIndex",
+        component: () => import("@/views/duty/index.vue"),
+        meta: {
+          title: "值班管理",
+          noCache: true
         }
       },
       {
@@ -182,7 +201,16 @@ const routes: Array<RouteRecordRaw> = [
         name: "About",
         component: () => import("@/views/about/index.vue"),
         meta: {
-          title: "关于3",
+          title: "我的",
+          noCache: true
+        }
+      },
+      {
+        path: "inspectionWork",
+        name: "inspectionWork",
+        component: () => import("@/views/worker/inspectionWork/index.vue"),
+        meta: {
+          title: "巡查工作",
           noCache: true
         }
       }
@@ -220,6 +248,14 @@ const routes: Array<RouteRecordRaw> = [
     meta: {
       title: "签到签退成功"
     }
+  },
+  {
+    path: "/InformationReception",
+    name: "InformationReception",
+    component: () => import("@/views/InformationReception/index.vue"),
+    meta: {
+      title: "信息发布"
+    }
   }
 ];
 

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

@@ -0,0 +1,263 @@
+<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, onUnmounted, watch } 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,
+  event_code: "YJSJ0000000001"
+});
+// 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 params = {
+      event_code: selectedTask.value.event_code, // 确保这里的 props.eventId 是字符串类型,如果是数字类型需要转换为字符串
+      sortOrder: sortOrder.value, // 假设 sortOrder 是响应式的
+      sortBy: selectedTask.value.sortBy // 假设 sortBy 是 selectedTask 的一个属性
+    };
+    const res = await selectTask(params); // 确保 selectTask 函数正确处理了这些参数
+    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>

+ 5 - 0
src/views/duty/index.vue

@@ -0,0 +1,5 @@
+<script setup lang="ts" name="About"></script>
+
+<template>
+  <div>值班管理</div>
+</template>

+ 160 - 133
src/views/leader/index.vue

@@ -3,26 +3,31 @@
     <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"
-            :clearable="false"
-            placeholder="请输入搜索内容"
-            @search="on_search_keyword"
-            @click-right-icon.stop="on_search_cancel"
+          v-model="queryParams.keywords"
+          class="common-search"
+          :left-icon="searchImg"
+          :right-icon="closeImg"
+          :clearable="false"
+          placeholder="请输入搜索内容"
+          @search="on_search_keyword"
+          @click-right-icon.stop="on_search_cancel"
         />
         <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>
@@ -31,19 +36,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>
@@ -55,7 +64,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(item2.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>
@@ -64,58 +78,71 @@
         </div>
       </div>
     </div>
-    <van-dialog class="custom-dialog" v-model:show="show" title="在线点名提醒" confirmButtonText="确认点名"  @confirm="handleToRollCall">
+    <van-dialog
+      v-model:show="show"
+      class="custom-dialog"
+      title="在线点名提醒"
+      confirmButtonText="确认点名"
+      @confirm="handleToRollCall"
+    >
       <div class="btn" @click="handleHideDialog">浮窗显示</div>
       <div class="line">
         <i class="icon-tip" />
         <div class="text1">{{ durationTime }}</div>
       </div>
     </van-dialog>
-    <van-dialog class="custom-dialog2" v-model:show="show2" title="在线点名提醒" :showConfirmButton="false">
+    <van-dialog
+      v-model:show="show2"
+      class="custom-dialog2"
+      title="在线点名提醒"
+      :showConfirmButton="false"
+    >
       <div class="dialog-content">
-        <div class="img-box"></div>
+        <div class="img-box" />
         <div v-show="!img" class="text1">即将通过摄像头捕捉画面</div>
         <div v-show="!img" class="text2">请稍等</div>
-        <div v-show="img" class="btn" @click="handleToRollCall2">上传视频截图</div>
+        <div v-show="img" class="btn" @click="handleToRollCall2">
+          上传视频截图
+        </div>
         <div v-show="img" class="text3">已完成</div>
       </div>
     </van-dialog>
-    <div v-if="!!rollCallData.id" class="float-box" @click="show = true"></div>
+    <div v-if="!!rollCallData.id" class="float-box" @click="show = true" />
   </dic>
 </template>
 
 <script lang="ts" setup>
-import {onClickOutside} from "@vueuse/core";
-import {ref, reactive, onMounted, onUnmounted} from 'vue';
+import { onClickOutside } from "@vueuse/core";
+import { ref, reactive, onMounted, onUnmounted } 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: 'OnlineRollCall' },
-  { 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: "OnlineRollCall" },
+  { name: "事件管理", icon: "icon4", num: 0, url: "EventList" }
 ]);
 
 // 综合应用菜单
 const menu2 = ref([
   {
-    name: '自然灾害风险监测',
+    name: "自然灾害风险监测",
     children: [
       { name: '预警态势', icon: 'monitor', url: 'WarningSituation' },
       { name: '大风灾害', icon: 'wind', url: 'GaleDisaster' },
@@ -125,33 +152,33 @@ const menu2 = ref([
     ]
   },
   {
-    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();
@@ -162,83 +189,86 @@ 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 on_search_cancel = () => {
   showSearch.value = false;
-  queryParams.keywords = '';
+  queryParams.keywords = "";
   queryParams.page = 0;
   finished.value = false;
   searchList.value = [];
-}
-const handleClickItem = (item) => {
+};
+const handleClickItem = item => {
   showSearch.value = false;
-  queryParams.keywords = '';
+  queryParams.keywords = "";
   queryParams.page = 0;
   finished.value = false;
   searchList.value = [];
-}
+};
 // 在线点名弹窗
 let timer;
 let show = ref();
-let durationTime = ref('');
+let durationTime = ref("");
 let rollCallData = ref({
-  id: '',
-  time1: ''
-})
+  id: "",
+  time1: ""
+});
 // 在线点名
 let show2 = ref();
-let img = ref('');
+let img = ref("");
 const handleToRollCall = () => {
   show.value = false;
   show2.value = true;
   setTimeout(() => {
-    img.value = '2';
-  }, 3000)
-}
+    img.value = "2";
+  }, 3000);
+};
 const handleToRollCall2 = () => {
   router.push({
-    name: 'RollCallDetails',
+    name: "RollCallDetails",
     query: { id: rollCallData.value.id }
   });
-}
-const calculateDuration = (startTimeStr) => {
+};
+const calculateDuration = startTimeStr => {
   // 将起始时间字符串转换为日期对象
   const startTime = new Date(startTimeStr);
 
@@ -247,7 +277,7 @@ const calculateDuration = (startTimeStr) => {
 
   // 确保起始时间在结束时间之前(可选,用于验证输入)
   if (startTime > endTime) {
-    return '';
+    return "";
   }
 
   // 计算时间差(以毫秒为单位)
@@ -256,36 +286,36 @@ const calculateDuration = (startTimeStr) => {
   // 将毫秒转换为秒、分钟和小时
   const seconds = Math.floor((timeDifference / 1000) % 60);
   const minutes = Math.floor((timeDifference / (1000 * 60)) % 60);
-  const hours = Math.floor((timeDifference / (1000 * 60 * 60)));
+  const hours = Math.floor(timeDifference / (1000 * 60 * 60));
 
   // 格式化时间为 HH:MM:SS
-  const formattedDuration = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
+  const formattedDuration = `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`;
 
   // 返回格式化的持续时间
   return formattedDuration;
 };
 const updateTime = () => {
-  durationTime.value = calculateDuration(rollCallData.value.time1)
-}
+  durationTime.value = calculateDuration(rollCallData.value.time1);
+};
 const handleHideDialog = () => {
   show.value = false;
 };
 onMounted(() => {
-  initData()
-  rollCallData.value = {
-    id: '11111',
-    time1: '2024-10-22 12:00:00'
-  };
-  show.value = true;
+  initData();
+  // rollCallData.value = {
+  //   id: '11111',
+  //   time1: '2024-10-22 12:00:00'
+  // };
+  // show.value = true;
   if (!timer && !!rollCallData.value.time1) {
-    timer = setInterval(updateTime, 1000)
+    timer = setInterval(updateTime, 1000);
   }
-})
+});
 onUnmounted(() => {
   if (!!timer) {
-    clearInterval(timer)
+    clearInterval(timer);
   }
-})
+});
 </script>
 
 <style lang="scss" scoped>
@@ -298,7 +328,7 @@ onUnmounted(() => {
 .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;
@@ -326,7 +356,6 @@ onUnmounted(() => {
     border-top-width: 0 !important;
   }
   :deep(.van-grid) {
-
     .van-grid-item {
       &:nth-child(1) {
         padding-right: 12px;
@@ -362,7 +391,7 @@ onUnmounted(() => {
         }
         .card-title {
           font-size: 14px;
-          color: #414F64;
+          color: #414f64;
         }
       }
       .icon1 {
@@ -380,8 +409,7 @@ onUnmounted(() => {
       .icon1,
       .icon2,
       .icon3,
-      .icon4
-      {
+      .icon4 {
         width: 67px;
         height: 67px;
         background-size: 100% 100%;
@@ -403,7 +431,7 @@ onUnmounted(() => {
     height: 26px;
     font-weight: bold;
     font-size: 18px;
-    color: #414F64;
+    color: #414f64;
     letter-spacing: 0;
     margin-bottom: 4px;
   }
@@ -457,7 +485,6 @@ onUnmounted(() => {
 }
 .common-search {
   :deep(.van-field__left-icon) {
-
     .van-icon__image {
       width: 12px;
       height: 12px;
@@ -480,7 +507,7 @@ onUnmounted(() => {
     top: 10px;
     right: 6px;
     font-size: 12px;
-    color: #2C81FF;
+    color: #2c81ff;
   }
   .line {
     display: flex;
@@ -490,12 +517,12 @@ onUnmounted(() => {
     .icon-tip {
       width: 30px;
       height: 31px;
-      background: url('@/assets/images/onlineRollCall/tip.png') no-repeat;
+      background: url("@/assets/images/onlineRollCall/tip.png") no-repeat;
       background-size: 100% 100%;
     }
     .text1 {
       font-size: 24px;
-      color: #2C81FF;
+      color: #2c81ff;
     }
   }
 }
@@ -524,24 +551,24 @@ onUnmounted(() => {
   }
   .text1 {
     font-size: 14px;
-    color: #2C81FF;
+    color: #2c81ff;
     line-height: 26px;
   }
   .text2 {
     font-size: 12px;
-    color: #FFAF00;
+    color: #ffaf00;
     line-height: 26px;
   }
   .text3 {
     font-size: 12px;
-    color: #40C75F;
+    color: #40c75f;
     line-height: 26px;
   }
   .btn {
-    background: #2C81FF;
+    background: #2c81ff;
     border-radius: 2px;
     font-size: 12px;
-    color: #FFFFFF;
+    color: #ffffff;
     padding: 3px 14px;
   }
 }

+ 470 - 2
src/views/worker/index.vue

@@ -1,9 +1,477 @@
 <template>
-    工作人员首页
+  <dic class="container">
+    <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"
+          @click-right-icon.stop="on_search_cancel"
+        />
+        <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"
+          >
+            <div
+              v-for="(item, index) in searchList"
+              :key="index"
+              class="item"
+              @click="handleClickItem(item)"
+            >
+              {{ item.name }}
+            </div>
+          </van-list>
+        </div>
+      </div>
+    </div>
+    <div class="container-content">
+      <div class="notice-bar">
+        <!-- 静态的预警信息 -->
+        <div class="notice-item">
+          <span class="notice-label">预警信息</span>
+          <div class="notice-time">2023-10-10 10:00:00</div>
+          <div class="notice-content">
+            这里是静态的预警信息内容,不需要从变量中获取。
+          </div>
+        </div>
+        <!-- 查看更多的链接 -->
+        <div class="notice-more" @click="goToInformationReception">
+          查看更多 >>
+        </div>
+      </div>
+      <!--      <div v-if="noticeBarState.show" class="notice-bar">-->
+      <!--        <van-swipe :autoplay="false" indicator-color="back">-->
+      <!--          <van-swipe-item-->
+      <!--            v-for="(message, index) in latestMessages"-->
+      <!--            :key="index"-->
+      <!--          >-->
+      <!--            <div class="notice-item">-->
+      <!--              <span class="notice-label">预警信息</span>-->
+      <!--              <div class="notice-content">-->
+      <!--                {{ message.event_title }}-->
+      <!--              </div>-->
+      <!--              <div class="notice-time">-->
+      <!--                {{ message.event_time }}-->
+      <!--              </div>-->
+      <!--            </div>-->
+      <!--          </van-swipe-item>-->
+      <!--        </van-swipe>-->
+      <!--        <div class="notice-more" @click="goToInformationReception">-->
+      <!--          查看更多 >>-->
+      <!--        </div>-->
+      <!--      </div>-->
+      <div class="padding-content">
+        <van-grid :column-num="2">
+          <van-grid-item
+            v-for="(item, index) in menu"
+            :key="index"
+            @click="handleClickMenu(item.url)"
+          >
+            <div class="card">
+              <div :class="item.icon" />
+              <van-badge :content="item.num" max="99" :show-zero="false">
+                <div class="card-title">{{ item.name }}</div>
+              </van-badge>
+            </div>
+          </van-grid-item>
+        </van-grid>
+        <div class="app_panel">
+          <div class="app_panel_title">综合应用</div>
+          <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)"
+              >
+                <img class="icon" :src="getImageUrl(item2.icon)" alt="" />
+                <span>{{ item2.name }}</span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </dic>
 </template>
 
 <script lang="ts" setup>
+import { onClickOutside } from "@vueuse/core";
+import { onMounted, reactive, ref } from "vue";
+import { selectTask } from "@/api/emergencyCommandMap/JointDuty";
+import searchImg from "@/assets/images/search.png";
+import { useRouter } from "vue-router";
+import closeImg from "@/assets/images/close.png";
+import { getPointInfoComprehensiveSearch } from "@/api/globalMap";
+
+const router = useRouter();
+const noticeBarState = reactive({
+  show: false,
+  latestMessages: []
+});
+
+const goToInformationReception = () => {
+  router.push({ name: "InformationReception" });
+};
+// 菜单数据
+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: "" }
+]);
+
+// 综合应用菜单
+const menu2 = ref([
+  {
+    name: "自然灾害风险监测",
+    children: [
+      { name: "灾害监测", icon: "monitor", url: "" },
+      { name: "大风灾害", icon: "wind", url: "" },
+      { name: "森林火灾", icon: "forestFire", url: "" },
+      { name: "台风实况", icon: "typhoon", url: "" },
+      { name: "水文监测", icon: "hydrology", url: "" }
+    ]
+  },
+  {
+    name: "应急事件场景专题",
+    children: [
+      { name: "自然灾害", icon: "nature", url: "" },
+      { name: "事故灾害", icon: "accident", url: "" },
+      { name: "城市事件", icon: "city", url: "" }
+    ]
+  }
+]);
+const handleClickMenu = url => {
+  if (!url) return;
+  router.push({ name: url });
+};
+const getImageUrl = name => {
+  return new URL(`../../assets/images/index/${name}.png`, import.meta.url).href;
+};
+
+// 请求数据
+const initData = async () => {
+  try {
+    const sortOrder = "desc";
+    const sortBy = "creation_time";
+    const event_code = "YJSJ0000000001";
+
+    console.log("请求任务数据:", event_code);
+    const res = await selectTask({
+      sortOrder: sortOrder,
+      sortBy: sortBy,
+      event_code: event_code
+    });
+    if (res && res.data) {
+      noticeBarState.latestMessages = res.data.slice(0, 3).map(msg => ({
+        event_title: msg.event_title,
+        event_time: msg.event_time
+      }));
+      noticeBarState.show = true;
+    } else {
+      console.error("API response data is empty or invalid");
+    }
+  } catch (error) {
+    console.error("请求任务数据失败:", error);
+    noticeBarState.show = false; // 如果请求失败,不显示通知栏
+  }
+};
+// 搜索
+const searchBoxRef = ref();
+let showSearch = ref();
+const total = ref(0);
+let loading = ref(false);
+let error = ref(false);
+let finished = ref(false);
+const queryParams = reactive({
+  page: 0,
+  page_size: 15,
+  keywords: ""
+});
+const searchList = ref([]);
+onClickOutside(searchBoxRef, event => {
+  showSearch.value = false;
+});
+const getSearchList = () => {
+  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);
+      });
+      finished.value = queryParams.page_size * queryParams.page >= total.value;
+      showSearch.value = true;
+    })
+    .catch(() => {
+      error.value = true;
+      finished.value = false;
+    })
+    .finally(() => {
+      loading.value = false;
+    });
+};
+const on_search_keyword = val => {
+  queryParams.keywords = val;
+  queryParams.page = 0;
+  getSearchList();
+};
+const on_search_cancel = () => {
+  showSearch.value = false;
+  queryParams.keywords = "";
+  queryParams.page = 0;
+  finished.value = false;
+  searchList.value = [];
+};
+const handleClickItem = item => {
+  showSearch.value = false;
+  queryParams.keywords = "";
+  queryParams.page = 0;
+  finished.value = false;
+  searchList.value = [];
+};
+onMounted(() => {
+  initData();
+});
 </script>
 
 <style lang="scss" scoped>
-</style>
+.container {
+  display: block;
+  width: 100%;
+  height: 100%;
+  padding-bottom: 20px;
+}
+.container-header {
+  width: 100%;
+  height: 370px;
+  background: url("@/assets/images/") no-repeat;
+  background-size: 100% 100%;
+  display: flex;
+  flex-direction: column;
+  justify-content: flex-end;
+  align-items: center;
+  padding-bottom: 70px;
+  .search-box {
+    width: 100%;
+    position: relative;
+  }
+  .van-search {
+    width: 100%;
+  }
+}
+.container-content {
+  margin-top: -70px;
+  .van-notice-bar {
+    width: 100%;
+    margin-bottom: 11px;
+  }
+  .padding-content {
+    padding: 0 16px;
+  }
+  .van-hairline--top:after {
+    border-top-width: 0 !important;
+  }
+  :deep(.van-grid) {
+    .van-grid-item {
+      &:nth-child(1) {
+        padding-right: 12px;
+        padding-bottom: 12px;
+      }
+      &:nth-child(2) {
+        padding-bottom: 12px;
+      }
+      &:nth-child(3) {
+        padding-right: 12px;
+      }
+      .card {
+        width: 100%;
+        height: 89px;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 9px 15px 9px 0;
+        font-size: 14px;
+        background: url(@/assets/images/index/cardBg1.png) no-repeat;
+        background-size: 100% 100%;
+        &:nth-child(2) {
+          background: url(@/assets/images/index/cardBg2.png) no-repeat;
+          background-size: 100% 100%;
+        }
+        &:nth-child(3) {
+          background: url(@/assets/images/index/cardBg3.png) no-repeat;
+          background-size: 100% 100%;
+        }
+        &:nth-child(4) {
+          background: url(@/assets/images/index/cardBg4.png) no-repeat;
+          background-size: 100% 100%;
+        }
+        .card-title {
+          font-size: 14px;
+          color: #414f64;
+        }
+      }
+      .icon1 {
+        background: url(@/assets/images/index/icon1.png) no-repeat;
+      }
+      .icon2 {
+        background: url(@/assets/images/index/icon2.png) no-repeat;
+      }
+      .icon3 {
+        background: url(@/assets/images/index/icon3.png) no-repeat;
+      }
+      .icon4 {
+        background: url(@/assets/images/index/icon4.png) no-repeat;
+      }
+      .icon1,
+      .icon2,
+      .icon3,
+      .icon4 {
+        width: 67px;
+        height: 67px;
+        background-size: 100% 100%;
+      }
+    }
+    .van-grid-item__content {
+      padding: 0;
+      background: transparent;
+      &::after {
+        border: none;
+      }
+    }
+  }
+}
+
+.app_panel {
+  padding-top: 12px;
+  .app_panel_title {
+    height: 26px;
+    font-weight: bold;
+    font-size: 18px;
+    color: #414f64;
+    letter-spacing: 0;
+    margin-bottom: 4px;
+  }
+  .box {
+    width: 100%;
+    height: 72px;
+    background: url("@/assets/images/index/boxBg.png") no-repeat;
+    background-size: 100% 100%;
+    margin-bottom: 12px;
+    &:last-child {
+      margin-bottom: 0;
+    }
+    .box-title {
+      font-size: 12px;
+      color: #3687fe;
+      padding: 0 10px;
+    }
+    .box-content {
+      display: flex;
+      flex-wrap: wrap;
+      padding-top: 3px;
+      .box-item {
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+        width: 20%;
+        font-size: 12px;
+        .icon {
+          width: 32px;
+          height: 34px;
+        }
+      }
+    }
+  }
+}
+.search-list {
+  position: absolute;
+  top: 50px;
+  left: 0;
+  z-index: 9;
+  width: 100%;
+  height: calc(100vh - 400px);
+  overflow-y: auto;
+  background-color: #ffffff;
+  border-top: 1px solid #eeeeee;
+  .item {
+    padding: 8px 15px;
+    border-bottom: 1px solid #eeeeee;
+  }
+}
+.common-search {
+  :deep(.van-field__left-icon) {
+    .van-icon__image {
+      width: 12px;
+      height: 12px;
+    }
+  }
+  :deep(.van-field__right-icon) {
+    width: 30px;
+    height: 30px;
+    padding: 0;
+    .van-icon__image {
+      width: 30px;
+      height: 30px;
+    }
+  }
+}
+.notice-bar {
+  background-color: #f3f7ff;
+  padding: 10px;
+  border-radius: 5px;
+  margin-bottom: 10px;
+}
+
+.notice-item {
+  margin-bottom: 10px;
+}
+
+.notice-label {
+  background-color: orange;
+  color: white;
+  padding: 5px;
+  border-radius: 3px;
+  margin-right: 5px;
+}
+
+.notice-content {
+  max-height: 45px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  display: -webkit-box;
+  -webkit-line-clamp: 3;
+  -webkit-box-orient: vertical;
+}
+
+.notice-time {
+  font-size: 12px;
+  color: #888;
+}
+
+.notice-more {
+  float: right;
+  color: #007aff;
+  cursor: pointer;
+}
+</style>

+ 12 - 0
src/views/worker/inspectionWork/index.vue

@@ -0,0 +1,12 @@
+<template>
+  <van-tabs v-model:active="active" type="card">
+    <van-tab title="巡查任务"> <PatrolTask /></van-tab>
+    <van-tab title="巡查记录"><InspectionRecord /></van-tab>
+    <van-tab title="巡查日历"><PatrolCalendar /></van-tab>
+  </van-tabs>
+</template>
+<script setup lang="ts">
+import InspectionRecord from "./inspectionRecord.vue";
+import PatrolCalendar from "./patrolCalendar.vue";
+import PatrolTask from "./patrolTask.vue";
+</script>

+ 11 - 0
src/views/worker/inspectionWork/inspectionRecord.vue

@@ -0,0 +1,11 @@
+<script setup lang="ts">
+
+</script>
+
+<template>
+
+</template>
+
+<style scoped lang="scss">
+
+</style>

+ 11 - 0
src/views/worker/inspectionWork/patrolCalendar.vue

@@ -0,0 +1,11 @@
+<script setup lang="ts">
+
+</script>
+
+<template>
+
+</template>
+
+<style scoped lang="scss">
+
+</style>

+ 251 - 0
src/views/worker/inspectionWork/patrolTask.vue

@@ -0,0 +1,251 @@
+<template>
+  <div class="container">
+    <van-search
+      v-model="queryParams.search_keyword"
+      class="common-search"
+      :left-icon="searchImg"
+      :right-icon="closeImg"
+      @search="on_search_keyword"
+      @click-right-icon.stop="on_search_cancel"
+    />
+    <van-list
+      v-model:loading="loading"
+      v-model:error="error"
+      error-text="请求失败,点击重新加载"
+      :finished="finished"
+      finished-text="没有更多事件了"
+      @load="getList"
+    >
+      <div
+        v-for="(item, index) in event_list"
+        :key="item.id"
+        class="event-list-item"
+      >
+        <div class="item-title">
+          <div class="item-title-text">
+            {{ item.title }}
+          </div>
+          <div class="item-title-control">
+            <van-button type="primary" @click="handleView(item)">
+              巡查上报
+            </van-button>
+          </div>
+        </div>
+        <div class="item-content">
+          <div class="item-data">
+            <div class="item-left">
+              <i class="icon4" />
+              <div class="item-data-label">巡查周期:</div>
+            </div>
+            <div class="item-data-value">{{ item.cycle }}</div>
+          </div>
+          <div class="item-data">
+            <div class="item-left">
+              <i class="icon4" />
+              <div class="item-data-label">巡查范围:</div>
+            </div>
+            <div class="item-data-value">{{ item.scope }}</div>
+          </div>
+          <div class="item-data">
+            <div class="item-left">
+              <i class="icon4" />
+              <div class="item-data-label">要求巡检时间:</div>
+            </div>
+            <div class="item-data-value">{{ item.time }}</div>
+          </div>
+        </div>
+      </div>
+    </van-list>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { getCurrentInstance, reactive, ref, toRefs, onMounted } from "vue";
+import { useRouter } from "vue-router";
+import searchImg from "@/assets/images/search.png";
+import closeImg from "@/assets/images/close.png";
+const proxy = getCurrentInstance()?.proxy;
+const router = useRouter();
+const event_list = ref([]);
+const total = ref(0);
+const loading = ref(false);
+const error = ref(false);
+const finished = ref(false);
+const initFormData = reactive({
+  scope: "",
+  cycle: "",
+  time: "",
+  event_title: "",
+  id: ""
+});
+const data = reactive({
+  form: { ...initFormData },
+  queryParams: {
+    page: 1,
+    pageSize: 10
+  }
+});
+const { queryParams, form } = toRefs(data);
+// 获取列表数据的方法
+async function getList() {
+  loading.value = true;
+  try {
+    // 这里是获取列表数据的逻辑,可以根据实际需求进行修改
+    const res = await fetchListData(
+      queryParams.value.page,
+      queryParams.value.pageSize
+    );
+    event_list.value = res.data.list;
+    total.value = res.data.total;
+  } catch (err) {
+    console.error("获取列表数据出错", err);
+    error.value = true;
+  } finally {
+    loading.value = false;
+  }
+}
+// 搜索关键字变化时触发的方法
+function on_search_keyword(keyword) {
+  // 根据搜索关键字更新查询参数
+  queryParams.value.search_keyword = keyword;
+  // 刷新列表数据
+  getList();
+}
+
+// 右侧关闭按钮点击时触发的方法
+function on_search_cancel() {
+  // 清空搜索关键字
+  queryParams.value.search_keyword = "";
+  // 刷新列表数据
+  getList();
+}
+</script>
+
+<style lang="scss" scoped>
+.van-doc-block__title {
+  color: var(--van-doc-text-color-4);
+  margin: 0;
+  padding: 32px 16px 16px;
+  font-size: 14px;
+  font-weight: 400;
+  line-height: 16px;
+}
+
+.event-list-item {
+  position: relative;
+  margin: 16px 16px 0;
+  background: #ffffff;
+  border-radius: 4px;
+  border: 0.5px solid #eaedf7;
+  box-shadow: 0 0 4px 0 #4554661a;
+  &:first-child {
+    margin-top: 0;
+  }
+  .item-title {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    min-height: 46px;
+    background-image: linear-gradient(180deg, #f3f7fd 0%, #ffffff 100%);
+    padding: 0 12px;
+    .item-title-text {
+      font-size: 16px;
+      color: #414f64;
+      font-weight: 600;
+    }
+
+    .item-title-control {
+      display: inline-flex;
+      justify-content: center;
+      align-items: center;
+    }
+    .van-button {
+      width: 73px;
+      height: 24px;
+      padding: 0;
+    }
+  }
+  .item-content {
+    padding: 0 12px 12px;
+  }
+  .item-data {
+    font-size: 14px;
+    display: flex;
+    flex-direction: row;
+    align-items: flex-start;
+    justify-content: start;
+    line-height: 26px;
+    .item-left {
+      display: flex;
+      align-items: center;
+      flex-shrink: 0;
+    }
+    .item-data-label {
+      flex-shrink: 0;
+      color: #414f64;
+    }
+
+    .item-data-value {
+      color: #414f64;
+    }
+  }
+}
+.van-dropdown-menu {
+  :deep(.van-dropdown-menu__bar) {
+    background: transparent;
+    box-shadow: none;
+  }
+}
+.common-search {
+  :deep(.van-field__left-icon) {
+    .van-icon__image {
+      width: 12px;
+      height: 12px;
+    }
+  }
+  :deep(.van-field__right-icon) {
+    width: 30px;
+    height: 30px;
+    padding: 0;
+    .van-icon__image {
+      width: 30px;
+      height: 30px;
+    }
+  }
+}
+.icon1 {
+  width: 17px;
+  height: 16px;
+  background: url("@/assets/images/event/icon1.png") no-repeat;
+  background-size: 100% 100%;
+  margin-right: 7px;
+}
+.icon2 {
+  width: 17px;
+  height: 16px;
+  background: url("@/assets/images/event/icon2.png") no-repeat;
+  background-size: 100% 100%;
+  margin-right: 7px;
+}
+.icon3 {
+  width: 17px;
+  height: 16px;
+  background: url("@/assets/images/event/icon3.png") no-repeat;
+  background-size: 100% 100%;
+  margin-right: 7px;
+}
+.icon4 {
+  width: 17px;
+  height: 16px;
+  background: url("@/assets/images/event/icon4.png") no-repeat;
+  background-size: 100% 100%;
+  margin-right: 7px;
+}
+.icon5 {
+  width: 16px;
+  height: 16px;
+  background: url("@/assets/images/event/icon5.png") no-repeat;
+  background-size: 100% 100%;
+  margin-right: 7px;
+}
+</style>