yangyuxuan hai 2 meses
pai
achega
f2b973e686

+ 65 - 66
src/api/event.ts

@@ -1,116 +1,115 @@
-import request from '@/utils/request';
+import request from "@/utils/request";
 
 // 获取当前活动事件列表
 export function getActiveEventList() {
-    return request({
-        url: '/api/event_management/event/notice_bar',
-        method: 'get'
-    });
+  return request({
+    url: "/api/event_management/event/notice_bar",
+    method: "get"
+  });
 }
 
 // 获取事件列表
 export function getEventList(params) {
-    return request({
-        url: '/api/event_management/event/list',
-        method: 'get',
-        params: params
-    });
+  return request({
+    url: "/api/event_management/event/list",
+    method: "get",
+    params: params
+  });
 }
 
 // 获取事件详情
 export function getEventDetail(params) {
-    return request({
-        url: '/api/event_management/event/detail',
-        method: 'get',
-        params: params
-    });
+  return request({
+    url: "/api/event_management/event/detail",
+    method: "get",
+    params: params
+  });
 }
 
 // 开始指挥事件
 export function startEvent(data) {
-    return request({
-        url: '/api/event_management/event/start',
-        method: 'post',
-        data: data
-    });
+  return request({
+    url: "/api/event_management/event/start",
+    method: "post",
+    data: data
+  });
 }
 
 // 关闭事件
 export function closeEvent(data) {
-    return request({
-        url: '/api/event_management/event/close',
-        method: 'post',
-        data: data
-    });
+  return request({
+    url: "/api/event_management/event/close",
+    method: "post",
+    data: data
+  });
 }
 
 // 签到/签退
 export function getSignInfo(data) {
-    return request({
-        url: '/api/event_management/checkin/getInfo',
-        method: 'post',
-        data: data
-    });
+  return request({
+    url: "/api/event_management/checkin/getInfo",
+    method: "post",
+    data: data
+  });
 }
 
 export function signEvent(data) {
-    return request({
-        url: '/api/event_management/checkin/check',
-        method: 'post',
-        data: data
-    });
+  return request({
+    url: "/api/event_management/checkin/check",
+    method: "post",
+    data: data
+  });
 }
 
 export function uploadCasualties(data) {
-    return request({
-        url: '/api/event_management/event/upload_casualties',
-        method: 'post',
-        data: data
-    });
+  return request({
+    url: "/api/event_management/event/upload_casualties",
+    method: "post",
+    data: data
+  });
 }
 
 // 事件简报
 export function createEventBriefing(data) {
-    return request({
-        url: '/api/event_management/event_xp/creat_event_briefing',
-        method: 'post',
-        data: data
-    });
+  return request({
+    url: "/api/event_management/event_xp/creat_event_briefing",
+    method: "post",
+    data: data
+  });
 }
 
 // 获取事件简报列表
 export function getEventBriefingList(params) {
-    return request({
-        url: '/api/event_management/event_xp/event_briefing/list',
-        method: 'get',
-        params: params
-    });
+  return request({
+    url: "/api/event_management/event_xp/event_briefing/list",
+    method: "get",
+    params: params
+  });
 }
 
 // 获取预案通知详情
 export function getEmergencyNotifyDetail(params) {
-    return request({
-        url: '/api/event_management/event_xp/emergency_notify/detail',
-        method: 'get',
-        params: params
-    });
+  return request({
+    url: "/api/event_management/event_xp/emergency_notify/detail",
+    method: "get",
+    params: params
+  });
 }
 
-
 // 更新指挥人员
 export function createEventLeaderUser(data) {
-    return request({
-        url: '/api/event_management/event_xp/create_leader_user',
-        method: 'post',
-        data: data
-    });
+  return request({
+    url: "/api/event_management/event_xp/create_leader_user",
+    method: "post",
+    data: data
+  });
 }
 
 // 获取任务详情
 export function getTaskRegistrationDetail(params) {
-    return request({
-        url: '/api/event_management/event_xp/task_registration/detail',
-        method: 'get',
-        params: params
-    });
+  return request({
+    url: "/api/event_management/event_xp/task_registration/detail",
+    method: "get",
+    params: params
+  });
 }

+ 12 - 0
src/router/routes.ts

@@ -148,6 +148,18 @@ export const constantRoutes: Array<RouteRecordRaw> = [
       noCache: true
     }
   },
+  {
+    path: "/hazardousChemicalEnterprisesView",
+    name: "HazardousChemicalEnterprisesView",
+    component: () =>
+      import(
+        "@/views/disasterRiskMonitor/hazardousChemicalEnterprisesView.vue"
+      ),
+    meta: {
+      title: "危化企业雨量详情",
+      noCache: true
+    }
+  },
   {
     path: "/forestFirePrevention",
     name: "ForestFirePrevention",

+ 17 - 5
src/views/disasterRiskMonitor/hazardousChemicalEnterprises.vue

@@ -1,8 +1,6 @@
 <template>
   <div v-if="!isShowView" class="container">
-    <div style="font-weight: bold; text-align: center; margin-bottom: 10px">
-      危化企业雨量监测
-    </div>
+    <div class="title">危化企业雨量监测</div>
     <div class="box">
       <div class="box-item">
         <div class="box-label">实况:</div>
@@ -84,7 +82,13 @@
           />
           <el-table-column label="操作" align="center" width="50px">
             <template #default="scope">
-              <div class="btn" @click="showDetails(scope.row)">查看视频</div>
+              <div
+                class="btn"
+                @click="showDetails(scope.row)"
+                style="color: #1d92ff"
+              >
+                播放
+              </div>
             </template>
           </el-table-column>
         </el-table>
@@ -127,7 +131,7 @@ const getTableRowClass = ({ rowIndex }) => {
 };
 const showDetails = row => {
   router.push({
-    name: "RainfallInRainShelterView",
+    name: "HazardousChemicalEnterprisesView",
     query: {
       latitude: row.latitude,
       longitude: row.longitude,
@@ -468,4 +472,12 @@ getData();
     padding: 10px;
   }
 }
+.title {
+  font-size: 18px;
+  font-weight: bold;
+  line-height: 32px;
+  width: 100%;
+  text-align: center;
+  margin-bottom: 8px;
+}
 </style>

+ 31 - 4
src/views/disasterRiskMonitor/hazardousChemicalEnterprisesView.vue

@@ -1,10 +1,13 @@
 <template>
   <div class="container">
-    <div style="font-weight: bold; text-align: center; margin-bottom: 10px">
+    <div class="title">
       {{ name }}
     </div>
     <div class="box">
-      视频
+      <div class="card-header">
+        <i class="icon-line" />
+        <div class="text">视频</div>
+      </div>
       <HKVideo
         v-if="!!video1"
         :dot_data="video1"
@@ -13,7 +16,10 @@
       />
     </div>
     <div class="box">
-      周边视频
+      <div class="card-header">
+        <i class="icon-line" />
+        <div class="text">周边视频</div>
+      </div>
       <el-table
         :data="videoList"
         header-cell-class-name="common-table-header"
@@ -31,7 +37,7 @@
         />
         <el-table-column label="操作" align="center" width="50px">
           <template #default="scope">
-            <div class="btn" @click="switchVideo(scope.row)">切换</div>
+            <div class="btn" @click="switchVideo(scope.row)" style="color: #1d92ff">切换</div>
           </template>
         </el-table-column>
       </el-table>
@@ -91,6 +97,14 @@ const switchVideo = row => {
       #ffffff 50px,
       #ffffff 100%
     );
+    .icon-line {
+      display: inline-block;
+      width: 6px;
+      height: 16px;
+      background: url("@/assets/images/line.jpg") no-repeat;
+      background-size: 100% 100%;
+      margin-right: 3px;
+    }
     padding: 10px 16px;
     margin-bottom: 10px;
     .box-item {
@@ -141,4 +155,17 @@ const switchVideo = row => {
     display: none !important;
   }
 }
+.title {
+  font-size: 18px;
+  font-weight: bold;
+  line-height: 32px;
+  width: 100%;
+  text-align: center;
+  margin-bottom: 8px;
+}
+.card-header {
+  display: flex;
+  align-items: center;
+  gap: 6px;
+}
 </style>

+ 18 - 3
src/views/disasterRiskMonitor/rainfallInRainShelter.vue

@@ -1,6 +1,6 @@
 <template>
   <div v-if="!isShowView" class="container">
-    <div style="font-weight: bold; text-align: center; margin-bottom: 10px">
+    <div class="title">
       雨窝点雨量监测
     </div>
     <div class="box">
@@ -84,7 +84,7 @@
           />
           <el-table-column label="操作" align="center" width="50px">
             <template #default="scope">
-              <div class="btn" @click="showDetails(scope.row)">查看视频</div>
+              <div class="btn" @click="showDetails(scope.row)" style="color: #1d92ff">播放</div>
             </template>
           </el-table-column>
         </el-table>
@@ -126,7 +126,14 @@ const getTableRowClass = ({ rowIndex }) => {
   return rowIndex % 2 === 0 ? "" : "common-table-tr";
 };
 const showDetails = row => {
-  router.push({ name: "RainfallInRainShelterView", query: { latitude: row.latitude, longitude: row.longitude, name: encodeURIComponent(row.name) } });
+  router.push({
+    name: "RainfallInRainShelterView",
+    query: {
+      latitude: row.latitude,
+      longitude: row.longitude,
+      name: encodeURIComponent(row.name)
+    }
+  });
 };
 const getData = () => {
   getPointInfo("16").then(res => {
@@ -444,4 +451,12 @@ getData();
     padding: 10px;
   }
 }
+.title {
+  font-size: 18px;
+  font-weight: bold;
+  line-height: 32px;
+  width: 100%;
+  text-align: center;
+  margin-bottom: 8px;
+}
 </style>

+ 31 - 4
src/views/disasterRiskMonitor/rainfallInRainShelterView.vue

@@ -1,10 +1,13 @@
 <template>
   <div class="container">
-    <div style="font-weight: bold; text-align: center; margin-bottom: 10px">
+    <div class="title">
       {{ name }}
     </div>
     <div class="box">
-      视频
+      <div class="card-header">
+        <i class="icon-line" />
+        <div class="text">视频</div>
+      </div>
       <HKVideo
         v-if="!!video1"
         :dot_data="video1"
@@ -13,7 +16,10 @@
       />
     </div>
     <div class="box">
-      周边视频
+      <div class="card-header">
+        <i class="icon-line" />
+        <div class="text">周边视频</div>
+      </div>
       <el-table
         :data="videoList"
         header-cell-class-name="common-table-header"
@@ -31,7 +37,7 @@
         />
         <el-table-column label="操作" align="center" width="50px">
           <template #default="scope">
-            <div class="btn" @click="switchVideo(scope.row)">切换</div>
+            <div class="btn" @click="switchVideo(scope.row)" style="color: #1d92ff">切换</div>
           </template>
         </el-table-column>
       </el-table>
@@ -93,6 +99,14 @@ const switchVideo = row => {
       #ffffff 50px,
       #ffffff 100%
     );
+    .icon-line {
+      display: inline-block;
+      width: 6px;
+      height: 16px;
+      background: url("@/assets/images/line.jpg") no-repeat;
+      background-size: 100% 100%;
+      margin-right: 3px;
+    }
     padding: 10px 16px;
     margin-bottom: 10px;
     .box-item {
@@ -143,4 +157,17 @@ const switchVideo = row => {
     display: none !important;
   }
 }
+.title {
+  font-size: 18px;
+  font-weight: bold;
+  line-height: 32px;
+  width: 100%;
+  text-align: center;
+  margin-bottom: 8px;
+}
+.card-header {
+  display: flex;
+  align-items: center;
+  gap: 6px;
+}
 </style>

+ 10 - 2
src/views/disasterRiskMonitor/rainfallMonitoring.vue

@@ -1,6 +1,6 @@
 <template>
   <div v-if="!isShowView" class="container">
-    <div style="font-weight: bold; text-align: center; margin-bottom: 10px">
+    <div class="title">
       地质灾害隐患点雨量监测
     </div>
     <div class="box">
@@ -84,7 +84,7 @@
           />
           <el-table-column label="操作" align="center" width="50px">
             <template #default="scope">
-              <div class="btn" @click="showDetails(scope.row)">查看</div>
+              <div class="btn" @click="showDetails(scope.row)" style="color: #1d92ff">播放</div>
             </template>
           </el-table-column>
         </el-table>
@@ -447,4 +447,12 @@ getData();
     padding: 10px;
   }
 }
+.title {
+  font-size: 18px;
+  font-weight: bold;
+  line-height: 32px;
+  width: 100%;
+  text-align: center;
+  margin-bottom: 8px;
+}
 </style>

+ 27 - 3
src/views/disasterRiskMonitor/rainfallMonitoringView.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="container">
-    <div style="font-weight: bold; text-align: center; margin-bottom: 10px">
+    <div class="title">
       {{ detailsData.address }}
     </div>
     <div class="box">
@@ -26,7 +26,10 @@
       </van-form>
     </div>
     <div class="box">
-      视频
+      <div class="card-header">
+        <i class="icon-line" />
+        <div class="text">视频</div>
+      </div>
       <HKVideo
         v-if="!!video1"
         :dot_data="video1"
@@ -47,7 +50,7 @@
         <el-table-column label="距离" prop="distance" align="center" width="60px" />
         <el-table-column label="操作" align="center" width="50px">
           <template #default="scope">
-            <div class="btn" @click="switchVideo(scope.row)">切换</div>
+            <div class="btn" @click="switchVideo(scope.row)" style="color: #1d92ff">切换</div>
           </template>
         </el-table-column>
       </el-table>
@@ -127,6 +130,14 @@ const switchVideo = row => {
     );
     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;
@@ -175,4 +186,17 @@ const switchVideo = row => {
     display: none !important;
   }
 }
+.title {
+  font-size: 18px;
+  font-weight: bold;
+  line-height: 32px;
+  width: 100%;
+  text-align: center;
+  margin-bottom: 8px;
+}
+.card-header {
+  display: flex;
+  align-items: center;
+  gap: 6px;
+}
 </style>

+ 107 - 82
src/views/duty/uploadRota.vue

@@ -4,123 +4,146 @@
       <van-form @submit="onSubmit">
         <div class="van-doc-block__title">上传值班表</div>
         <van-field
-            v-model="formLabel.area"
-            is-link
-            readonly
-            name="area"
-            label="区划"
-            placeholder="请选择"
-            :rules="[{ required: true, message: '请选择区划', trigger: 'change' }]"
-            @click="showPicker2 = true"
+          v-model="formLabel.area"
+          is-link
+          readonly
+          name="area"
+          label="区划"
+          placeholder="请选择"
+          :rules="[
+            { required: true, message: '请选择区划', trigger: 'change' }
+          ]"
+          @click="showPicker2 = true"
         />
         <van-field
-            v-model="form.year"
-            is-link
-            readonly
-            name="year"
-            label="年份"
-            placeholder="请选择"
-            :rules="[{ required: true, message: '请选择年份', trigger: 'change' }]"
-            @click="showPicker3 = true"
+          v-model="form.year"
+          is-link
+          readonly
+          name="year"
+          label="年份"
+          placeholder="请选择"
+          :rules="[
+            { required: true, message: '请选择年份', trigger: 'change' }
+          ]"
+          @click="showPicker3 = true"
         />
         <van-field
-            v-model="form.month"
-            is-link
-            readonly
-            name="month"
-            label="月份"
-            placeholder="请选择"
-            :rules="[{ required: true, message: '请选择月份', trigger: 'change' }]"
-            @click="showPicker4 = true"
+          v-model="form.month"
+          is-link
+          readonly
+          name="month"
+          label="月份"
+          placeholder="请选择"
+          :rules="[
+            { required: true, message: '请选择月份', trigger: 'onChange' }
+          ]"
+          @click="showPicker4 = true"
         />
         <van-field
-            name="files"
-            label="值班表"
-            label-align="top"
-            :rules="[{ validator: validatorFile, message: '请上传值班表', trigger: 'change' }]"
+          name="files"
+          label="值班表"
+          label-align="top"
+          :rules="[
+            {
+              validator: validatorFile,
+              message: '请上传值班表',
+              trigger: 'change'
+            }
+          ]"
         >
           <template #input>
-            <FileUpload v-model="form.files" :limit="1" :fileType="['xls', 'xlsx']" :isShowTip="false">
-              <van-button type="primary" class="button" @click="handleDownload">模板下载</van-button>
+            <FileUpload
+              v-model="form.files"
+              :limit="1"
+              :fileType="['xls', 'xlsx']"
+              :isShowTip="false"
+            >
+              <van-button type="primary" class="button" @click="handleDownload"
+                >模板下载</van-button
+              >
             </FileUpload>
           </template>
         </van-field>
         <div class="popup-footer">
-          <van-button @click="handleCancel" class="cancel-btn">取 消</van-button>
-          <van-button type="primary" native-type="submit" class="confirm-btn">确 定</van-button>
+          <van-button class="cancel-btn" @click="handleCancel"
+            >取 消</van-button
+          >
+          <van-button type="primary" native-type="submit" class="confirm-btn"
+            >确 定</van-button
+          >
         </div>
       </van-form>
     </van-popup>
     <van-popup v-model:show="showPicker2" round position="bottom">
       <van-picker
-          title="选择区划"
-          :columns="columns"
-          @confirm="onConfirm"
-          @cancel="showPicker2 = false"
+        title="选择区划"
+        :columns="columns"
+        @confirm="onConfirm"
+        @cancel="showPicker2 = false"
       />
     </van-popup>
     <van-popup v-model:show="showPicker3" round position="bottom">
       <van-date-picker
-          v-model="formLabel.year"
-          title="选择年份"
-          :columns-type="['year']"
-          @confirm="onConfirm2"
-          @cancel="showPicker3 = false"
+        v-model="formLabel.year"
+        title="选择年份"
+        :columns-type="['year']"
+        @confirm="onConfirm2"
+        @cancel="showPicker3 = false"
       />
     </van-popup>
     <van-popup v-model:show="showPicker4" round position="bottom">
       <van-date-picker
-          v-model="formLabel.month"
-          title="选择月份"
-          :columns-type="['month']"
-          @confirm="onConfirm3"
-          @cancel="showPicker4 = false"
+        v-model="formLabel.month"
+        title="选择月份"
+        :columns-type="['month']"
+        @confirm="onConfirm3"
+        @cancel="showPicker4 = false"
       />
     </van-popup>
   </div>
 </template>
 
 <script lang="ts" setup name="uploadRota">
-import {computed, ref} from "vue";
+import { computed, ref } from "vue";
 import dayjs from "dayjs";
 import FileUpload from "@/components/FileUpload/index.vue";
-import {download2} from "@/utils/request";
+import { download2 } from "@/utils/request";
 import { upload_duty_book } from "@/api/duty/duty";
 
-const emits = defineEmits(['update:show']);
+const emits = defineEmits(["update:show"]);
 const props = defineProps({
-  show: Boolean,
+  show: Boolean
 });
-const showPicker = computed( {
+const showPicker = computed({
   get() {
-    return props.show
+    return props.show;
   },
   set(newValue) {
-    emits('update:show', newValue);
+    emits("update:show", newValue);
   }
 });
 const columns = [
-  { text: '茂名市', value: '440900' },
-  { text: '茂南区', value: '440902' },
-  { text: '电白区', value: '440904' },
-  { text: '高州市', value: '440981' },
-  { text: '化州市', value: '440982' },
-  { text: '信宜市', value: '440983' },
-  { text: '滨海新区', value: '440984' },
-  { text: '高新区', value: '440983' },
+  { text: "茂名市", value: "440900" },
+  { text: "茂南区", value: "440902" },
+  { text: "电白区", value: "440904" },
+  { text: "高州市", value: "440981" },
+  { text: "化州市", value: "440982" },
+  { text: "信宜市", value: "440983" },
+  { text: "滨海新区", value: "440984" },
+  { text: "高新区", value: "440983" }
 ];
 let showPicker2 = ref(false);
 let showPicker3 = ref(false);
 let showPicker4 = ref(false);
 let formLabel = ref({
-  area: '',
+  area: "",
   year: [dayjs().year()],
   month: [dayjs().month() + 1]
-})
+});
 let form = ref({
-  area: '',
-  year: '',
-  month: '',
+  area: "",
+  year: "",
+  month: "",
   files: []
 });
 
@@ -145,42 +168,44 @@ const onConfirm3 = ({ selectedValues }) => {
 
 // 下载模板
 const handleDownload = () => {
-  download2(import.meta.env.VITE_BASE_API + '/file/download/' + 'duty_book.xlsx', '值班表模板.xlsx');
-}
+  download2(
+    import.meta.env.VITE_BASE_API + "/file/download/" + "duty_book.xlsx",
+    "值班表模板.xlsx"
+  );
+};
 const validatorFile = () => {
-
   return !!form.value.files && form.value.files.length > 0;
-}
+};
 const reset = () => {
   formLabel.value = {
-    area: '',
+    area: "",
     year: [dayjs().year()],
     month: []
   };
   form.value = {
-    area: '',
-    year: '',
-    month: '',
+    area: "",
+    year: "",
+    month: "",
     files: []
   };
-}
+};
 const handleCancel = () => {
   reset();
-  showPicker.value = false
-}
+  showPicker.value = false;
+};
 const onSubmit = () => {
-  console.log('提交', form.value);
-  upload_duty_book(form.value).then((res)=>{
+  console.log("提交", form.value);
+  upload_duty_book(form.value).then(res => {
     handleCancel();
   });
-}
+};
 </script>
 
-<style  lang="scss" scoped>
+<style lang="scss" scoped>
 .button {
   padding: 0 10px;
   height: 26px;
-  background: #2C81FF;
+  background: #2c81ff;
   border-radius: 2px;
   margin-bottom: 3px;
   margin-left: 10px;

+ 6 - 0
src/views/mobileControl/EventBox.vue

@@ -26,6 +26,7 @@
       v-show="tabActive === '0'"
       :eventId="eventId"
       :eventDetails="eventDetails"
+      @confirm="getDetail"
     />
     <TaskCommand v-show="tabActive === '1'" :eventId="eventId" />
     <Briefing v-if="tabActive === '2'" :eventId="eventId" />
@@ -37,6 +38,11 @@ import EventInfo from "./EventInfo.vue";
 import { ref } from "vue";
 import TaskCommand from "./TaskCommand.vue";
 import Briefing from "./Briefing.vue";
+import PositionSelect from "@/views/mobileControl/PositionSelect.vue";
+const emits = defineEmits(["confirm"]);
+const getDetail = () => {
+  emits("confirm");
+};
 interface EventDetails {
   event_id: String;
   event_title: String;

+ 66 - 8
src/views/mobileControl/EventInfo.vue

@@ -26,7 +26,12 @@
     <div style="display: flex; justify-content: space-between">
       <div class="info-data">
         <div class="info-data-label">持续时长:</div>
-        <div class="info-data-value">{{ eventDetails.keep_time }}</div>
+        <div class="time-duration">
+          <span v-if="duration.days > 0">{{ duration.days }}天</span>
+          <span>{{ duration.hours }}时</span>
+          <span>{{ duration.minutes }}分</span>
+          <span>{{ duration.seconds }}秒</span>
+        </div>
       </div>
       <van-button
         v-if="eventDetails.event_status == '1'"
@@ -70,21 +75,23 @@
       <div class="info-data-value">{{ eventDetails.event_source }}</div>
     </div>
     <PositionSelect
-      v-if="isChangeAddress"
+      v-show="isChangeAddress"
       :id="props.eventDetails.event_id"
       v-model:visible="isChangeAddress"
+      @confirm="getDetail"
     />
   </div>
 </template>
 
 <script lang="ts" setup name="EventInfo">
-import { closeEvent, getEventDetail } from "@/api/event";
-import { reactive, ref, toRefs, watch } from "vue";
+import { closeEvent } from "@/api/event";
 import { useDict } from "@/utils/dict";
 import { useRouter } from "vue-router";
 import { showConfirmDialog, showSuccessToast } from "vant";
 import PositionSelect from "@/views/mobileControl/PositionSelect.vue";
 
+
+
 interface EventDetails {
   event_id: String;
   event_title: String;
@@ -101,29 +108,34 @@ interface EventDetails {
 interface Props {
   eventDetails: EventDetails;
 }
+const emits = defineEmits(["confirm"]);
 const props = withDefaults(defineProps<Props>(), {});
 const router = useRouter();
 const { mm_event_type, mm_event_level, mm_event_state } = toRefs<any>(
   useDict("mm_event_type", "mm_event_level", "mm_event_state")
 );
-
+const getDetail = () => {
+  emits("confirm");
+  isChangeAddress.value = false;
+};
 const isChangeAddress = ref(false);
 const changeAddress = () => {
   isChangeAddress.value = true;
 };
 
 const handleStartEvent = () => {};
-
+const params = ref({});
 const handleCloseEvent = () => {
   showConfirmDialog({
     title: "结束指挥",
     message: "是否确定结束指挥?"
   }).then(() => {
-    const params = {
+    params.value = {
       eventId: props.eventDetails.event_id,
       address: props.eventDetails.address,
       latitude: props.eventDetails.latitude,
-      longitude: props.eventDetails.longitude
+      longitude: props.eventDetails.longitude,
+      eventTime: props.eventDetails.event_time
     };
     // 如果 flag 为 true,则直接调用 closeEvent 接口关闭事件
     closeEvent(params).then(() => {
@@ -132,6 +144,52 @@ const handleCloseEvent = () => {
     });
   });
 };
+
+// 时间解析(兼容iOS且保持本地时区)
+const parseTime = str => {
+  if (!str) return new Date(); // 空值返回当前时间
+  const [datePart, timePart] = str.split(" ");
+  return new Date(`${datePart}T${timePart}`);
+};
+
+// 事件时间戳
+const eventTime = computed(() =>
+  parseTime(params.value?.eventTime || props.eventDetails?.event_time || "")
+);
+const eventTimestamp = computed(() => eventTime.value.getTime());
+
+// 响应式当前时间
+const now = ref(Date.now());
+
+// 定时器管理
+let timer;
+onMounted(() => {
+  timer = setInterval(() => (now.value = Date.now()), 1000);
+});
+onUnmounted(() => clearInterval(timer));
+
+// 时间差分解计算
+const duration = computed(() => {
+  if (!eventTimestamp.value)
+    return { days: 0, hours: 0, minutes: 0, seconds: 0 }; // 空值保护
+
+  const diff = Math.abs(now.value - eventTimestamp.value);
+  const seconds = Math.floor(diff / 1000);
+
+  return {
+    days: Math.floor(seconds / 86400),
+    hours: Math.floor((seconds % 86400) / 3600),
+    minutes: Math.floor((seconds % 3600) / 60),
+    seconds: seconds % 60
+  };
+});
+
+// 调试日志
+if (import.meta.env.DEV) {
+  console.log("事件时间:", eventTime.toLocaleString());
+  console.log("当前时间:", new Date(now.value).toLocaleString());
+  console.log("时间差:", duration.value);
+}
 </script>
 
 <style lang="scss" scoped>

+ 187 - 108
src/views/mobileControl/PositionSelect.vue

@@ -6,92 +6,117 @@
     @close="handleClose"
     @confirm="submit"
   >
-    <div class="position-container">
-      <div style="position: relative">
-        <div class="box">
-          <van-search
-            v-model="form.address"
-            show-action
-            label="详细地址"
-            left-icon="none"
-            placeholder="请输入"
-            @search="handleInput"
-          >
-            <template #action>
-              <div @click="handleInput">搜索</div>
-            </template>
-          </van-search>
-        </div>
-        <van-field
-          v-model="form.event_title"
-          label="灾害事件"
-          placeholder="请输入"
-        />
-        <div class="custom-vant-field">
-          <div class="van-field__label">事件级别</div>
-          <el-select
-            v-model="form.event_level"
-            :teleported="false"
-            placeholder="请选择"
-            class="van-style-select"
-          >
-            <el-option
-              v-for="item in mm_event_level"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
-          </el-select>
-        </div>
-        <div class="custom-line" />
-        <div v-if="searchPop" class="scroll_box">
-          <div class="scroll-header">
-            <span>搜索结果列表</span>
-            <i class="close-icon" @click="closeSearchList()" />
+    <van-form ref="formRef">
+      <div class="position-container">
+        <div style="position: relative">
+          <div class="box">
+            <div class="custom-vant-field">
+              <div class="van-field__label">详细地址</div>
+              <van-field
+                v-model="form.address"
+                placeholder="请输入地址"
+                :rules="[
+                  {
+                    required: true,
+                    message: '地址不能为空',
+                    trigger: 'onChange'
+                  }
+                ]"
+                class="address-field"
+                clearable
+              >
+                <template #button>
+                  <van-button
+                    size="small"
+                    type="primary"
+                    style="height: 28px"
+                    @click="handleInput"
+                  >
+                    搜索
+                  </van-button>
+                </template>
+              </van-field>
+            </div>
           </div>
-
-          <div class="scroll">
-            <div
-              v-for="(item, index) in searchList"
-              v-show="searchList.length"
-              :key="index"
-              class="item"
-              @click="handlePanTo(index)"
+          <van-field
+            v-model="form.event_title"
+            label="灾害事件"
+            placeholder="请输入"
+          />
+          <div class="custom-vant-field">
+            <div class="van-field__label">事件级别</div>
+            <el-select
+              v-model="form.event_level"
+              :teleported="false"
+              placeholder="请选择"
+              class="van-style-select"
             >
-              <van-image
-                width="50"
-                height="50"
-                fit="fill"
-                :src="item.img"
-                style="flex-shrink: 0; margin-right: 8px"
+              <el-option
+                v-for="item in mm_event_level"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
               />
-              <div>
-                <div class="text">{{ item.name }}</div>
-                <div>{{ item.address }}</div>
-              </div>
+            </el-select>
+          </div>
+          <div class="custom-line" />
+          <div v-if="searchPop" class="scroll_box">
+            <div class="scroll-header">
+              <span>搜索结果列表</span>
+              <i class="close-icon" @click="closeSearchList()" />
             </div>
-            <div
-              v-show="!searchList.length"
-              class="empty"
-              style="text-align: center"
-            >
-              没有搜索到内容
+
+            <div class="scroll">
+              <div
+                v-for="(item, index) in searchList"
+                v-show="searchList.length"
+                :key="index"
+                class="item"
+                @click="handlePanTo(index)"
+              >
+                <van-image
+                  width="50"
+                  height="50"
+                  fit="fill"
+                  :src="item.img"
+                  style="flex-shrink: 0; margin-right: 8px"
+                />
+                <div>
+                  <div class="text">{{ item.name }}</div>
+                  <div>{{ item.address }}</div>
+                </div>
+              </div>
+              <div
+                v-show="!searchList.length"
+                class="empty"
+                style="text-align: center"
+              >
+                没有搜索到内容
+              </div>
             </div>
           </div>
         </div>
+        <van-field
+          v-model="form.longitude"
+          label="经&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp度"
+          placeholder="请输入"
+          :rules="[
+            { required: true, message: '经度不能为空', trigger: 'onBlur' }
+          ]"
+          required
+        />
+        <van-field
+          v-model="form.latitude"
+          label="纬&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp度"
+          placeholder="请输入"
+          :rules="[
+            { required: true, message: '纬度不能为空', trigger: 'onBlur' }
+          ]"
+          required
+        />
+        <div id="map" class="map" />
       </div>
-      <van-field
-        v-model="form.longitude"
-        label="经&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp度"
-        placeholder="请输入"
-      />
-      <van-field
-        v-model="form.latitude"
-        label="纬&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp度"
-        placeholder="请输入"
-      />
-      <div id="map" class="map" />
-    </div>
+    </van-form>
   </van-dialog>
 </template>
 
@@ -100,11 +125,11 @@ import AMapLoader from "@amap/amap-jsapi-loader";
 import { useRouter } from "vue-router";
 import { addEvent } from "@/api/emergencyCommandMap/JointDuty";
 import { nextTick, onUnmounted, reactive, ref, watch } from "vue";
-import { showFailToast } from "vant";
+import {showFailToast, showSuccessToast} from "vant";
 import { ElOption, ElSelect } from "element-plus";
 import { getEventDetail } from "@/api/event";
-import {editEvent} from "@/api/duty/eventing";
-import {deepClone} from "@/utils";
+import { editEvent } from "@/api/duty/eventing";
+import { deepClone } from "@/utils";
 
 const props = defineProps({
   visible: {
@@ -128,6 +153,7 @@ let contextMenu = null;
 let lnglatPosition = ref([]); //选中的新坐标
 let rules = reactive({
   address: [{ required: true, message: "详细地址不能为空", trigger: "blur" }],
+  event_title: [{ required: true, message: "名称不能为空", trigger: "blur" }],
   longitude: [{ required: true, message: "经度不能为空", trigger: "blur" }],
   latitude: [{ required: true, message: "纬度不能为空", trigger: "blur" }]
 });
@@ -366,33 +392,44 @@ let queryFormRef = ref();
 
 function submit() {
   if (!!props.id) {
-    let temp = {};
-    temp.address = form.value.address;
-    temp.casualties = form.value.casualties;
-    temp.contact = form.value.contact;
-    temp.create_time = form.value.create_time;
-    temp.deaths = form.value.deaths;
-    temp.del_flag = form.value.del_flag;
-    temp.eventId = form.value.event_id;
-    temp.event_code = temp.eventId;
-    temp.description = form.value.description;
-    temp.event_level = form.value.event_level;
-    temp.event_source = form.value.event_source;
-    temp.event_status = form.value.event_status;
-    temp.event_time = form.value.event_time;
-    temp.event_title = form.value.event_title;
-    temp.event_type = form.value.event_type;
-    temp.id = form.value.id;
-    temp.injuries = form.value.injuries;
-    temp.latitude = form.value.latitude;
-    temp.longitude = form.value.longitude;
-    temp.missing = form.value.missing;
-    temp.plan_id = form.value.plan_id;
-    temp.recorded_by = form.value.recorded_by;
-    temp.region_code = form.value.region_code;
-    temp.report_time = form.value.report_time;
-    temp.response_level = form.value.response_level;
-    editEvent(temp);
+    if (!form.value.address) {
+      showFailToast("详细地址不能为空");
+    } else if (!form.value.longitude) {
+      showFailToast("经度不能为空");
+    } else if (!form.value.latitude) {
+      showFailToast("纬度不能为空");
+    } else {
+      let temp = {};
+      temp.address = form.value.address;
+      temp.casualties = form.value.casualties;
+      temp.contact = form.value.contact;
+      temp.create_time = form.value.create_time;
+      temp.deaths = form.value.deaths;
+      temp.del_flag = form.value.del_flag;
+      temp.eventId = form.value.event_id;
+      temp.event_code = temp.eventId;
+      temp.description = form.value.description;
+      temp.event_level = form.value.event_level;
+      temp.event_source = form.value.event_source;
+      temp.event_status = form.value.event_status;
+      temp.event_time = form.value.event_time;
+      temp.event_title = form.value.event_title;
+      temp.event_type = form.value.event_type;
+      temp.id = form.value.id;
+      temp.injuries = form.value.injuries;
+      temp.latitude = form.value.latitude;
+      temp.longitude = form.value.longitude;
+      temp.missing = form.value.missing;
+      temp.plan_id = form.value.plan_id;
+      temp.recorded_by = form.value.recorded_by;
+      temp.region_code = form.value.region_code;
+      temp.report_time = form.value.report_time;
+      temp.response_level = form.value.response_level;
+      editEvent(temp).then(() => {
+        emits("confirm");
+        showSuccessToast("定位修改成功");
+      });
+    }
   } else {
     if (!form.value.address) {
       showFailToast("详细地址不能为空");
@@ -504,4 +541,46 @@ function submit() {
 .van-style-select {
   margin-left: 5px;
 }
+:deep(.van-field__button) {
+  .van-button {
+    background: #fff !important;
+    border-color: #ebedf0;
+    color: #323233;
+
+    &:active {
+      background: #f8f8f8 !important;
+    }
+  }
+}
+.custom-vant-field {
+  // 保持原有样式
+  display: flex;
+  align-items: center;
+  padding: 10px 16px;
+  font-size: 14px;
+  .van-field__label {
+    width: 70px;
+    color: #373738;
+    margin-right: 12px;
+    flex-shrink: 0;
+  }
+  // 新增字段统一样式
+  .van-field {
+    flex: 1;
+    padding: 0;
+    :deep(.van-field__body) {
+      input::placeholder {
+        color: #c8c9cc;
+        font-size: 14px;
+      }
+    }
+  }
+}
+// 调整搜索按钮对齐方式
+.address-field {
+  :deep(.van-field__button) {
+    display: flex;
+    align-items: center;
+  }
+}
 </style>

+ 13 - 6
src/views/mobileControl/index.vue

@@ -76,7 +76,11 @@
     </div>
 
     <div v-if="!!eventId && !temp" v-show="showMenu && !fullscreen">
-      <EventBox :eventId="eventId" :event-details="eventDetails" />
+      <EventBox
+        :eventId="eventId"
+        :event-details="eventDetails"
+        @confirm="getDetail"
+      />
     </div>
     <!--切换事件-->
     <van-popup v-model:show="showSwitch" round position="bottom">
@@ -353,6 +357,13 @@ const handleShowMaterialManage = () => {
 onMounted(() => {
   eventId.value = route.query.event_id as string;
   selectEventId.value = [route.query.event_id as string];
+  getDetail();
+  getListActive({}).then(res => {
+    endEventState.columns = res.data;
+  });
+  getOnlinePlotting();
+});
+const getDetail = () => {
   if (!!eventId.value && !temp.value) {
     getEventDetail({ event_id: eventId.value })
       .then(res => {
@@ -364,11 +375,7 @@ onMounted(() => {
   } else {
     loading.value = false;
   }
-  getListActive({}).then(res => {
-    endEventState.columns = res.data;
-  });
-  getOnlinePlotting();
-});
+};
 // 获取地图元素操作
 const getMap = () => {
   if (["imageMap", "satellite2", "satellite3"].includes(activeMap.value)) {