Kaynağa Gözat

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	src/router/routes.ts
Hwf 7 ay önce
ebeveyn
işleme
1807ed2997

+ 35 - 2
src/api/inspectionWork/inspector.ts

@@ -1,8 +1,41 @@
 import request from '@/utils/request';
 
-export function workSubList(params) {
+export function queryMyTask(params) {
     return request({
-      url: '/api/riskManagement/inspection/task/list',
+      url: '/api/riskManagement/inspection/task/children/task/list',
+      method: 'get',
+      params: params
+    });
+}
+
+export function queryMyTaskRecord(params) {
+    return request({
+      url: '/api/riskManagement/inspection/task/children/task/records',
+      method: 'get',
+      params: params
+    });
+}
+
+
+export function queryMyTaskByCalendar(params) {
+    return request({
+      url: '/api/riskManagement/inspection/task/children/task/calendar/list',
+      method: 'get',
+      params: params
+    });
+}
+
+export function addTaskResult(data) {
+  return request({
+      url: '/api/riskManagement/inspection/task/children/task/result/create',
+      method: 'post',
+      data: data
+    });
+}
+
+export function listTaskResult(children_task_id, params) {
+  return request({
+      url: '/api/riskManagement/inspection/task/children/task/result/'+children_task_id+"/list",
       method: 'get',
       params: params
     });

+ 9 - 0
src/api/riskManagement/index.ts

@@ -0,0 +1,9 @@
+import request from "@/utils/request";
+
+// 获取当前活动事件列表
+export function getTaskList(type:string) {
+  return request({
+    url: "/api/riskManagement/risk/children/task/list",
+    method: "get"
+  });
+}

+ 13 - 21
src/router/routes.ts

@@ -78,15 +78,6 @@ export const constantRoutes: Array<RouteRecordRaw> = [
       noCache: true
     }
   },
-  {
-    path: "/nonCoalMine",
-    name: "NonCoalMine",
-    component: () => import("@/views/disasterRiskMonitor/nonCoalMine.vue"),
-    meta: {
-      title: "非煤矿山应急专题",
-      noCache: true
-    }
-  },
   {
     path: "/cityEmergencyEvent",
     name: "CityEmergencyEvent",
@@ -191,7 +182,7 @@ export const constantRoutes: Array<RouteRecordRaw> = [
     }
   },
   {
-    path: "/riskManagement",
+    path: "/riskManagement/index",
     name: "riskManagement",
     component: () => import("@/views/worker/riskManagement/index.vue"),
     meta: {
@@ -199,19 +190,20 @@ export const constantRoutes: Array<RouteRecordRaw> = [
     }
   },
   {
-    path: "/windAndFloodPrevention",
-    name: "WindAndFloodPrevention",
-    component: () => import("@/views/disasterRiskMonitor/windAndFloodPrevention.vue"),
+    path: "/patorlTaskResultAdd",
+    name: "patorlTaskResultAdd",
+    component: () => import("@/views/worker/inspectionWork/patorlTaskResultAdd.vue"),
     meta: {
-      title: "防风防汛应急专题"
+      title: "巡查上报"
     }
-  },
+  }
+  ,
   {
-    path: "/forestFirePrevention",
-    name: "ForestFirePrevention",
-    component: () => import("@/views/disasterRiskMonitor/forestFirePrevention.vue"),
+    path: "/patorlTaskResultList",
+    name: "patorlTaskResultList",
+    component: () => import("@/views/worker/inspectionWork/patorlTaskResultList.vue"),
     meta: {
-      title: "森林防火应急专题"
+      title: "巡查结果"
     }
   }
 ];
@@ -273,7 +265,7 @@ export const leaderRoute: Array<RouteRecordRaw> = [
         name: "My",
         component: () => import("@/views/about/index.vue"),
         meta: {
-          title: "我",
+          title: "我",
           noCache: true
         }
       }
@@ -347,7 +339,7 @@ export const workerRoute = [
         name: "My",
         component: () => import("@/views/about/index.vue"),
         meta: {
-          title: "我",
+          title: "我",
           noCache: true
         }
       }

+ 248 - 160
src/views/event/detail.vue

@@ -1,17 +1,22 @@
 <template>
   <div class="container">
-    <div v-if="!hideMap" id="aMap" class="event_map"></div>
+    <div v-if="!hideMap" id="aMap" class="event_map" />
     <div class="box">
-      <div class="event_title">{{ eventInfo.event_title || "暂无事件标题" }}</div>
+      <div class="event_title">
+        {{ eventInfo.event_title || "暂无事件标题" }}
+      </div>
       <div class="event_prop">
         <div class="event_type">
-          <dict-tag :options="mm_event_type" :value="eventInfo.event_type"></dict-tag>
+          <dict-tag :options="mm_event_type" :value="eventInfo.event_type" />
         </div>
         <div class="event_level">
-          <dict-tag :options="mm_event_level" :value="eventInfo.event_level||'0'"></dict-tag>
+          <dict-tag
+            :options="mm_event_level"
+            :value="eventInfo.event_level || '0'"
+          />
         </div>
         <div class="event_status">
-          <dict-tag :options="mm_event_state" :value="eventInfo.event_status"></dict-tag>
+          <dict-tag :options="mm_event_state" :value="eventInfo.event_status" />
         </div>
       </div>
       <van-tabs v-model:active="active">
@@ -19,93 +24,117 @@
           <div class="event_tab">
             <div class="event-data-item">
               <div class="item-left">
-                <i class="icon6"/>
+                <i class="icon6" />
                 <div class="event-data-item-title">事件编号:</div>
               </div>
               <div class="event-data-item-value">{{ eventInfo.event_id }}</div>
             </div>
             <div class="event-data-item">
               <div class="item-left">
-                <i class="icon1"/>
+                <i class="icon1" />
                 <div class="event-data-item-title">事件类型:</div>
               </div>
               <div class="event-data-item-value">
-                <dict-tag :options="mm_event_type" :value="eventInfo.event_type"></dict-tag>
+                <dict-tag
+                  :options="mm_event_type"
+                  :value="eventInfo.event_type"
+                />
               </div>
             </div>
             <div class="event-data-item">
               <div class="item-left">
-                <i class="icon2"/>
+                <i class="icon2" />
                 <div class="event-data-item-title">事件等级:</div>
               </div>
               <div class="event-data-item-value">
-                <dict-tag :options="mm_event_level" :value="eventInfo.event_level||'0'"></dict-tag>
+                <dict-tag
+                  :options="mm_event_level"
+                  :value="eventInfo.event_level || '0'"
+                />
               </div>
             </div>
             <div class="event-data-item">
               <div class="item-left">
-                <i class="icon3"/>
+                <i class="icon3" />
                 <div class="event-data-item-title">事件状态:</div>
               </div>
               <div class="event-data-item-value">
-                <dict-tag :options="mm_event_state" :value="eventInfo.event_status"></dict-tag>
+                <dict-tag
+                  :options="mm_event_state"
+                  :value="eventInfo.event_status"
+                />
               </div>
             </div>
             <div class="event-data-item">
               <div class="item-left">
-                <i class="icon5"/>
+                <i class="icon5" />
                 <div class="event-data-item-title">事发地点:</div>
               </div>
               <div class="event-data-item-value">{{ eventInfo.address }}</div>
             </div>
             <div class="event-data-item">
               <div class="item-left">
-                <i class="icon4"/>
+                <i class="icon4" />
                 <div class="event-data-item-title">事发时间:</div>
               </div>
-              <div class="event-data-item-value">{{ eventInfo.event_time }}</div>
+              <div class="event-data-item-value">
+                {{ eventInfo.event_time }}
+              </div>
             </div>
             <div class="event-data-item">
               <div class="item-left">
-                <i class="icon4"/>
+                <i class="icon4" />
                 <div class="event-data-item-title">上报时间:</div>
               </div>
-              <div class="event-data-item-value">{{ eventInfo.report_time }}</div>
+              <div class="event-data-item-value">
+                {{ eventInfo.report_time }}
+              </div>
             </div>
             <div class="event-data-item">
               <div class="item-left">
-                <i class="icon7"/>
+                <i class="icon7" />
                 <div class="event-data-item-title">伤亡情况:</div>
               </div>
-              <div class="event-data-item-value blue" @click="handleUploadCasualties">去上报</div>
+              <div
+                class="event-data-item-value blue"
+                @click="handleUploadCasualties"
+              >
+                去上报
+              </div>
             </div>
             <div class="event-data-item">
               <div class="item-left">
-                <i class="icon8"/>
+                <i class="icon8" />
                 <div class="event-data-item-title">登记人:</div>
               </div>
-              <div class="event-data-item-value">{{ eventInfo.reported_by }}</div>
+              <div class="event-data-item-value">
+                {{ eventInfo.reported_by }}
+              </div>
             </div>
             <div class="event-data-item">
               <div class="item-left">
-                <i class="icon4"/>
+                <i class="icon4" />
                 <div class="event-data-item-title">登记时间:</div>
               </div>
-              <div class="event-data-item-value">{{ eventInfo.reported_time }}</div>
+              <div class="event-data-item-value">
+                {{ eventInfo.reported_time }}
+              </div>
             </div>
             <div class="event-data-item">
               <div class="item-left">
-                <i class="icon9"/>
+                <i class="icon9" />
                 <div class="event-data-item-title">联系方式:</div>
               </div>
               <div class="event-data-item-value">{{ eventInfo.contact }}</div>
             </div>
             <div class="event-data-item">
               <div class="item-left">
-                <i class="icon10"/>
+                <i class="icon10" />
                 <div class="event-data-item-title">事件来源:</div>
               </div>
-              <div class="event-data-item-value">{{ eventInfo.event_source }}</div>
+              <div class="event-data-item-value">
+                {{ eventInfo.event_source }}
+              </div>
             </div>
           </div>
         </van-tab>
@@ -115,7 +144,10 @@
         <van-tab title="事件跟踪">
           <div class="event_tab">
             <van-steps direction="vertical" :active="0">
-              <van-step v-for="(item,index) in eventTrackState.items" :key="item.id">
+              <van-step
+                v-for="(item, index) in eventTrackState.items"
+                :key="item.id"
+              >
                 <h3>{{ item.title }}</h3>
                 <p>{{ item.description }}</p>
               </van-step>
@@ -124,39 +156,70 @@
         </van-tab>
         <van-tab title="匹配预案">
           <div class="event_tab2">
-            <template v-if="!!eventInfo.plan_id && !!eventInfo.plan_files && eventInfo.plan_files.length > 0">
+            <template
+              v-if="
+                !!eventInfo.plan_id &&
+                !!eventInfo.plan_files &&
+                eventInfo.plan_files.length > 0
+              "
+            >
               <div class="plan-content">
                 <div class="content-header">
-                  <div class="plan-content-title">{{ eventInfo.plan_files[0]?.name }}</div>
-                  <i class="download-icon" @click="handleDownload(eventInfo.plan_files[0])"/>
+                  <div class="plan-content-title">
+                    {{ eventInfo.plan_files[0]?.name }}
+                  </div>
+                  <i
+                    class="download-icon"
+                    @click="handleDownload(eventInfo.plan_files[0])"
+                  />
                 </div>
                 <div class="content-text">
                   <div v-for="(item, index) in planFiles" :key="index">
                     <div>{{ item.title }}</div>
                     <div v-for="(item2, index2) in item.items" :key="index2">
                       <div>{{ item2.title }}</div>
-                      <div v-html="item2.value"></div>
+                      <div v-html="item2.value" />
                     </div>
                   </div>
                 </div>
               </div>
             </template>
             <template v-else>
-              <div class="emptyIcon"/>
+              <div class="emptyIcon" />
               <div class="emptyText">未关联到对应预案</div>
-              <van-button type="primary" size="small" @click="associationShow = true">手工关联</van-button>
+              <van-button
+                type="primary"
+                size="small"
+                @click="associationShow = true"
+                >手工关联</van-button
+              >
             </template>
           </div>
         </van-tab>
         <van-tab title="总结报告">
           <div class="event_tab2">
-            <div v-if="eventInfo.summary_file && eventInfo.summary_file.length > 0" class="file-list">
-              <div v-for="(item, index) in eventInfo.summary_file" :key="index" class="item" @click="handleDownload2(item)">{{item.file_name}}</div>
+            <div
+              v-if="eventInfo.summary_file && eventInfo.summary_file.length > 0"
+              class="file-list"
+            >
+              <div
+                v-for="(item, index) in eventInfo.summary_file"
+                :key="index"
+                class="item"
+                @click="handleDownload2(item)"
+              >
+                {{ item.file_name }}
+              </div>
             </div>
             <template v-else>
-              <div class="emptyIcon2"/>
+              <div class="emptyIcon2" />
               <div class="emptyText">暂未上传总结报告</div>
-              <van-button type="primary" size="small" @click="handleUploadCasualties">去上传</van-button>
+              <van-button
+                type="primary"
+                size="small"
+                @click="handleUploadCasualties"
+                >去上传</van-button
+              >
             </template>
           </div>
         </van-tab>
@@ -164,93 +227,119 @@
     </div>
 
     <div class="footer">
-      <div style="display: flex; flex-direction: row; justify-content: space-between;">
-        <van-button v-if="eventInfo.event_status == '0'" type="primary" @click="handleStartEvent">开始指挥</van-button>
-        <van-button v-if="eventInfo.event_status == '1'" type="primary" @click="handleEnterEvent">进入指挥</van-button>
-        <van-button v-if="eventInfo.event_status == '0' || eventInfo.event_status == '2'" type="danger"
-                    @click="handleCloseEvent">关闭事件
+      <div
+        style="
+          display: flex;
+          flex-direction: row;
+          justify-content: space-between;
+        "
+      >
+        <van-button
+          v-if="eventInfo.event_status == '0'"
+          type="primary"
+          @click="handleStartEvent"
+          >开始指挥</van-button
+        >
+        <van-button
+          v-if="eventInfo.event_status == '1'"
+          type="primary"
+          @click="handleEnterEvent"
+          >进入指挥</van-button
+        >
+        <van-button
+          v-if="eventInfo.event_status == '0' || eventInfo.event_status == '2'"
+          type="danger"
+          @click="handleCloseEvent"
+          >关闭事件
         </van-button>
       </div>
     </div>
-    <AssociationPlan v-model="associationShow" :eventId="eventId" @confirm="associationPlanConfirm" />
+    <AssociationPlan
+      v-model="associationShow"
+      :eventId="eventId"
+      @confirm="associationPlanConfirm"
+    />
     <UploadEventCasualtiesDialog
-        v-model="uploadCasualtiesState.show"
-        :data="uploadCasualtiesState.form"
-        @update:model-value="onUploadCasualtiesDialogClose"
-        @confirm="onUploadCasualtiesDialogClose"
+      v-model="uploadCasualtiesState.show"
+      :data="uploadCasualtiesState.form"
+      @update:model-value="onUploadCasualtiesDialogClose"
+      @confirm="onUploadCasualtiesDialogClose"
+    />
+    <StartEventDialog
+      v-model="startEventState.show"
+      :data="startEventState.form"
+      @update:model-value="onStartEventDialogClose"
     />
-    <StartEventDialog v-model="startEventState.show" :data="startEventState.form"
-                      @update:model-value="onStartEventDialogClose"></StartEventDialog>
   </div>
 </template>
 
 <script lang="ts" setup>
-import {getCurrentInstance, reactive, ref, toRefs, onMounted} from 'vue';
-import {useRouter, useRoute} from 'vue-router'
-import {getEventDetail, closeEvent} from "@/api/event";
+import { getCurrentInstance, reactive, ref, toRefs, onMounted } from "vue";
+import { useRouter, useRoute } from "vue-router";
+import { getEventDetail, closeEvent } from "@/api/event";
 import UploadEventCasualtiesDialog from "./UploadEventCasualtiesDialog.vue";
-import {showDialog, showConfirmDialog} from 'vant';
-import {useAMap} from "@/hooks/AMap/useAMap";
+import { showDialog, showConfirmDialog } from "vant";
+import { useAMap } from "@/hooks/AMap/useAMap";
 import StartEventDialog from "@/views/event/StartEventDialog.vue";
-import {download2} from "@/utils/request";
-import {getPlanDoc, listPlan} from "@/api/duty/eventing";
+import { download2 } from "@/utils/request";
+import { getPlanDoc, listPlan } from "@/api/duty/eventing";
 import AssociationPlan from "@/views/event/AssociationPlan.vue";
 
-const router = useRouter()
-const route = useRoute()
+const router = useRouter();
+const route = useRoute();
 const proxy = getCurrentInstance()?.proxy;
-const {
-  mm_event_type,
-  mm_event_level,
-  mm_event_state
-} = toRefs<any>(proxy?.useDict('mm_event_type', 'mm_event_level', 'mm_event_state'));
+const { mm_event_type, mm_event_level, mm_event_state } = toRefs<any>(
+  proxy?.useDict("mm_event_type", "mm_event_level", "mm_event_state")
+);
 
 const active = ref(0);
-const eventId = ref('');
+const eventId = ref("");
 const data = reactive({
   eventInfo: {
-    event_id: '',
-    event_title: '',
-    event_code: '',
-    event_type: '',
-    event_level: '',
-    event_status: '',
-    address: '',
-    event_time: '',
-    report_time: '',
-    contact: '',
-    event_source: '',
-    event_description: '',
-    reported_by: '',
-    reported_time: '',
-    longitude: '',
-    latitude: '',
-    plan_id: '',
-    plan_name: '',
+    event_id: "",
+    event_title: "",
+    event_code: "",
+    event_type: "",
+    event_level: "",
+    event_status: "",
+    address: "",
+    event_time: "",
+    report_time: "",
+    contact: "",
+    event_source: "",
+    event_description: "",
+    reported_by: "",
+    reported_time: "",
+    longitude: "",
+    latitude: "",
+    plan_id: "",
+    plan_name: "",
     summary_file: [],
     plan_files: [],
     // 伤亡情况
-    deaths: '',
-    injuries: '',
-    missing: '',
+    deaths: "",
+    injuries: "",
+    missing: ""
   },
   eventTrackState: {
     active: 0,
-    items: [{
-      id: 0,
-      title: '事件登记',
-      description: ''
-    }]
+    items: [
+      {
+        id: 0,
+        title: "事件登记",
+        description: ""
+      }
+    ]
   }
 });
-const {eventInfo, eventTrackState} = toRefs(data);
+const { eventInfo, eventTrackState } = toRefs(data);
 const startEventState = reactive({
   show: false,
   form: {
-    event_id: '',
-    event_title: '',
-    event_level: '',
-    event_level_text: '',
+    event_id: "",
+    event_title: "",
+    event_level: "",
+    event_level_text: ""
   }
 });
 const handleStartEvent = () => {
@@ -259,10 +348,10 @@ const handleStartEvent = () => {
   startEventState.form.event_level = eventInfo.value.event_level;
   startEventState.show = true;
   return false;
-}
+};
 const handleEnterEvent = () => {
   router.push({
-    path: '/leader/mobile_control',
+    path: "/leader/mobile_control",
     query: {
       event_id: eventId.value
     }
@@ -271,22 +360,22 @@ const handleEnterEvent = () => {
 
 // 关闭事件
 const handleCloseEvent = () => {
-  if (eventInfo.value.plan_id === '') {
-    showDialog({message: '关闭事件前请先匹配预案'});
+  if (eventInfo.value.plan_id === "") {
+    showDialog({ message: "关闭事件前请先匹配预案" });
     return false;
   }
   if (eventInfo.value.summary_file.length === 0) {
-    showDialog({message: '关闭事件前请先上传总结报告'});
+    showDialog({ message: "关闭事件前请先上传总结报告" });
     return false;
   }
   showConfirmDialog({
-    title: '提示',
-    message: '关闭事件所有事项相关数据将不能再修改,是否继续?'
+    title: "提示",
+    message: "关闭事件所有事项相关数据将不能再修改,是否继续?"
   }).then(() => {
-    closeEvent({eventId: eventId.value}).then((res) => {
-      refreshData()
-    })
-  })
+    closeEvent({ eventId: eventId.value }).then(res => {
+      refreshData();
+    });
+  });
 };
 
 let associationShow = ref(false);
@@ -295,16 +384,15 @@ let associationShow = ref(false);
 const uploadCasualtiesState = reactive({
   show: false,
   form: {
-    event_id: '',
-    deaths: '',
-    injuries: '',
-    missing: ''
+    event_id: "",
+    deaths: "",
+    injuries: "",
+    missing: ""
   }
-})
-
+});
 
 const handleUploadCasualties = () => {
-  console.log('handleUploadCasualties');
+  console.log("handleUploadCasualties");
   uploadCasualtiesState.form.event_id = eventId.value;
   uploadCasualtiesState.form.deaths = eventInfo.value.deaths;
   uploadCasualtiesState.form.injuries = eventInfo.value.injuries;
@@ -312,88 +400,88 @@ const handleUploadCasualties = () => {
   uploadCasualtiesState.show = true;
 };
 
-const onUploadCasualtiesDialogClose = (t) => {
-  console.log('onUploadCasualtiesDialogClose', t)
+const onUploadCasualtiesDialogClose = t => {
+  console.log("onUploadCasualtiesDialogClose", t);
   uploadCasualtiesState.show = false;
   if (t) {
     refreshData();
   }
-}
+};
 
-const onStartEventDialogClose = (t) => {
+const onStartEventDialogClose = t => {
   startEventState.show = false;
   console.log(startEventState.form);
   if (t) {
-    getEventDetail({event_id: eventId.value}).then((res) => {
-      eventInfo.value = res.data
+    getEventDetail({ event_id: eventId.value }).then(res => {
+      eventInfo.value = res.data;
       eventTrackState.value = res.data.event_status_tracks;
-    })
+    });
   }
 };
 let planFiles = ref([]);
 const getPlan = () => {
-  getPlanDoc({plan_id: eventInfo.value.plan_id}).then((res)=> {
+  getPlanDoc({ plan_id: eventInfo.value.plan_id }).then(res => {
     planFiles.value = res.data;
   });
-}
-const associationPlanConfirm = (plan_id) => {
+};
+const associationPlanConfirm = plan_id => {
   associationShow.value = false;
   eventInfo.value.plan_id = plan_id;
   getPlan();
-}
+};
 const baseUrl = import.meta.env.VITE_BASE_API;
 // 下载方法
 const handleDownload = (file: any) => {
-  download2(baseUrl + '/file/download/' + file.url, file.name);
+  download2(baseUrl + "/file/download/" + file.url, file.name);
 };
 const handleDownload2 = (file: any) => {
-  download2(baseUrl + '/file/download/' + file.url, file.file_name);
+  download2(baseUrl + "/file/download/" + file.url, file.file_name);
 };
 onMounted(() => {
   refreshData();
-
-})
+});
 let hideMap = ref(false);
 let map;
 const refreshData = () => {
   eventId.value = route.query.event_id as string;
-  getEventDetail({event_id: eventId.value}).then((res) => {
-    eventInfo.value = res.data
+  getEventDetail({ event_id: eventId.value }).then(res => {
+    eventInfo.value = res.data;
     eventTrackState.value = res.data.event_status_tracks;
     if (!!eventInfo.value.plan_id) {
       getPlan(eventInfo.value.plan_id);
     }
     if (!eventInfo.value.longitude || !eventInfo.value.latitude) {
-      hideMap.vlaue = true
+      hideMap.value.vlaue = true;
     } else {
       // 初始化地图
       const lnglat = [eventInfo.value.longitude, eventInfo.value.latitude];
-      const {getMap} = useAMap({
-        key: '30d3d8448efd68cb0b284549fd41adcf',
-        version: '2.0',
+      const { getMap } = useAMap({
+        key: "30d3d8448efd68cb0b284549fd41adcf",
+        version: "2.0",
         zoom: 16,
         center: lnglat,
         dragEnable: true,
         scrollWheel: true,
         // 加载完成事件
-        onLoadCompleted: (AMap) => {
+        onLoadCompleted: AMap => {
           map = getMap();
           let marker = new AMap.Marker({
             position: lnglat,
             icon: new AMap.Icon({
-              size: new AMap.Size(22, 28),  //图标所处区域大小
+              size: new AMap.Size(22, 28), //图标所处区域大小
               imageSize: new AMap.Size(22, 28), //图标大小
-              image: "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
+              image:
+                "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png"
             }),
-            anchor: 'bottom-center',
+            anchor: "bottom-center",
             offset: new AMap.Pixel(0, 0)
           });
           marker.setMap(map);
         }
       });
     }
-  })
-}
+  });
+};
 </script>
 
 <style lang="scss" scoped>
@@ -412,7 +500,7 @@ const refreshData = () => {
 .event_title {
   font-weight: 600;
   min-height: 46px;
-  background-image: linear-gradient(180deg, #F3F7FD 0%, #FFFFFF 100%);
+  background-image: linear-gradient(180deg, #f3f7fd 0%, #ffffff 100%);
   padding: 12px;
 }
 
@@ -427,35 +515,35 @@ const refreshData = () => {
 
   .event_type {
     padding: 3px 10px;
-    border: 0.8px solid #2C81FF;
+    border: 0.8px solid #2c81ff;
     border-radius: 2px;
-    color: #2C81FF;
+    color: #2c81ff;
     margin-right: 7px;
   }
 
   .event_level {
     padding: 3px 10px;
-    border: 0.8px solid #2C81FF;
+    border: 0.8px solid #2c81ff;
     border-radius: 2px;
     margin-right: 7px;
-    color: #2C81FF;
+    color: #2c81ff;
   }
 
   .event_status {
     padding: 3px 10px;
-    border: 0.8px solid #2C81FF;
+    border: 0.8px solid #2c81ff;
     border-radius: 2px;
-    color: #2C81FF;
+    color: #2c81ff;
   }
 }
 
 .event_tab {
   padding: 16px;
-  color: #A6000000;
+  color: #a6000000;
 
   .event-data-item {
     font-size: 14px;
-    line-height: 8.0vmin;
+    line-height: 8vmin;
     display: flex;
     flex-direction: row;
     align-items: flex-start;
@@ -470,7 +558,7 @@ const refreshData = () => {
       .icon1 {
         width: 17px;
         height: 16px;
-        background: url('@/assets/images/event/icon1.png') no-repeat;
+        background: url("@/assets/images/event/icon1.png") no-repeat;
         background-size: 100% 100%;
         margin-right: 7px;
       }
@@ -478,7 +566,7 @@ const refreshData = () => {
       .icon2 {
         width: 17px;
         height: 16px;
-        background: url('@/assets/images/event/icon2.png') no-repeat;
+        background: url("@/assets/images/event/icon2.png") no-repeat;
         background-size: 100% 100%;
         margin-right: 7px;
       }
@@ -486,7 +574,7 @@ const refreshData = () => {
       .icon3 {
         width: 17px;
         height: 16px;
-        background: url('@/assets/images/event/icon3.png') no-repeat;
+        background: url("@/assets/images/event/icon3.png") no-repeat;
         background-size: 100% 100%;
         margin-right: 7px;
       }
@@ -494,7 +582,7 @@ const refreshData = () => {
       .icon4 {
         width: 17px;
         height: 16px;
-        background: url('@/assets/images/event/icon4.png') no-repeat;
+        background: url("@/assets/images/event/icon4.png") no-repeat;
         background-size: 100% 100%;
         margin-right: 7px;
       }
@@ -502,7 +590,7 @@ const refreshData = () => {
       .icon5 {
         width: 16px;
         height: 16px;
-        background: url('@/assets/images/event/icon5.png') no-repeat;
+        background: url("@/assets/images/event/icon5.png") no-repeat;
         background-size: 100% 100%;
         margin-right: 7px;
       }
@@ -564,7 +652,7 @@ const refreshData = () => {
 
   h3 {
     font-size: 4.2vmin;
-    line-height: 8.0vmin;
+    line-height: 8vmin;
   }
 }
 
@@ -598,14 +686,14 @@ const refreshData = () => {
 .emptyIcon {
   width: 110px;
   height: 108px;
-  background: url('@/assets/images/unrelatedPlan.png') no-repeat;
+  background: url("@/assets/images/unrelatedPlan.png") no-repeat;
   background-size: 100% 100%;
 }
 
 .emptyIcon2 {
   width: 111px;
   height: 110px;
-  background: url('@/assets/images/noReport.png') no-repeat;
+  background: url("@/assets/images/noReport.png") no-repeat;
   background-size: 100% 100%;
 }
 
@@ -621,7 +709,7 @@ const refreshData = () => {
     justify-content: center;
     align-items: center;
     font-size: 14px;
-    color: #2C81FF;
+    color: #2c81ff;
     font-weight: bold;
     padding: 5px 0;
     .plan-content-title {
@@ -632,7 +720,7 @@ const refreshData = () => {
       display: inline-block;
       width: 15px;
       height: 14px;
-      background: url('@/assets/images/download.png') no-repeat;
+      background: url("@/assets/images/download.png") no-repeat;
       background-size: 100% 100%;
       margin-left: 20px;
     }
@@ -646,7 +734,7 @@ const refreshData = () => {
   }
 }
 :deep(.van-tabs__wrap) {
-  border-bottom: 1px solid #F6F6F6;
+  border-bottom: 1px solid #f6f6f6;
 }
 .file-list {
   width: 100%;

+ 59 - 45
src/views/onlineRollCall/index.vue

@@ -1,6 +1,11 @@
 <template>
   <div class="container">
-    <div v-for="(item, index) in menuData" :key="index" class="box" @click="handleClick(item.key)">
+    <div
+      v-for="(item, index) in menuData"
+      :key="index"
+      class="box"
+      @click="handleClick(item.key)"
+    >
       <div class="box-left">
         <i :class="item.img" />
       </div>
@@ -10,52 +15,61 @@
 </template>
 
 <script lang="ts" setup name="onlineRollCall">
-import {reactive} from "vue";
-import {useRouter} from "vue-router";
-import {showConfirmDialog, showToast} from 'vant';
-import {create_by_city_to_area, create_by_city_to_district} from "@/api/onlineRollCall";
+import { reactive } from "vue";
+import { useRouter } from "vue-router";
+import { showConfirmDialog, showToast } from "vant";
+import {
+  create_by_city_to_area,
+  create_by_city_to_district
+} from "@/api/onlineRollCall";
 
 const router = useRouter();
 const menuData = reactive([
-  { name: '一键点名全市至区县', key: '1', img: 'icon1' },
-  { name: '一键点名全市至镇街', key: '2', img: 'icon1' },
-  { name: '分区/县点名', key: '3', img: 'icon1' },
-  { name: '在线点名记录', key: '4', img: 'icon2' },
-  { name: '点名应答记录', key: '5', img: 'icon3' }
-])
+  { name: "一键点名全市至区县", key: "1", img: "icon1" },
+  { name: "一键点名全市至镇街", key: "2", img: "icon1" },
+  { name: "分区/县点名", key: "3", img: "icon1" },
+  { name: "在线点名记录", key: "4", img: "icon2" },
+  { name: "点名应答记录", key: "5", img: "icon3" }
+]);
 const handleClick = (key: string) => {
-  if (key === '1') {
+  if (key === "1") {
     showConfirmDialog({
-      title: '提示',
-      message: '确认一键点名全市至区县?'
-    })
-    .then(() => {
-      create_by_city_to_area({}).then((res) => {
-        showToast({type: 'success', message: res.msg, onClose:()=>{
-          router.push({ name : 'RollCallDetails', query: { id: res.data }})
-        }});
-      })
-    })
-  } else if (key === '2') {
+      title: "提示",
+      message: "确认一键点名全市至区县?"
+    }).then(() => {
+      create_by_city_to_area({}).then(res => {
+        showToast({
+          type: "success",
+          message: res.msg,
+          onClose: () => {
+            router.push({ name: "RollCallDetails", query: { id: res.data } });
+          }
+        });
+      });
+    });
+  } else if (key === "2") {
     showConfirmDialog({
-      title: '提示',
-      message: '确认一键点名全市至镇街?'
-    })
-    .then(() => {
-      create_by_city_to_district({}).then((res) => {
-        showToast({type: 'success', message: res.msg, onClose:()=>{
-          router.push({ name : 'RollCallDetails', query: { id: res.data }})
-        }});
-      })
-    })
-  } else if (key === '3') {
-    router.push({ name : 'DistrictCountyRollCall'});
-  } else if (key === '4') {
-    router.push({ name : 'RollCallRecord'});
-  } else if (key === '5') {
-    router.push({ name : 'rollCallRecord2'});
+      title: "提示",
+      message: "确认一键点名全市至镇街?"
+    }).then(() => {
+      create_by_city_to_district({}).then(res => {
+        showToast({
+          type: "success",
+          message: res.msg,
+          onClose: () => {
+            router.push({ name: "RollCallDetails", query: { id: res.data } });
+          }
+        });
+      });
+    });
+  } else if (key === "3") {
+    router.push({ name: "DistrictCountyRollCall" });
+  } else if (key === "4") {
+    router.push({ name: "RollCallRecord" });
+  } else if (key === "5") {
+    router.push({ name: "rollCallRecord2" });
   }
-}
+};
 </script>
 
 <style lang="scss" scoped>
@@ -69,7 +83,7 @@ const handleClick = (key: string) => {
   .box {
     width: 358px;
     height: 89px;
-    background: url('@/assets/images/onlineRollCall/box.png') no-repeat;
+    background: url("@/assets/images/onlineRollCall/box.png") no-repeat;
     background-size: 100% 100%;
     display: flex;
     //justify-content: center;
@@ -86,25 +100,25 @@ const handleClick = (key: string) => {
       display: inline-block;
       width: 92px;
       height: 93px;
-      background: url('@/assets/images/onlineRollCall/icon1.png') no-repeat;
+      background: url("@/assets/images/onlineRollCall/icon1.png") no-repeat;
       background-size: 100% 100%;
     }
     .icon2 {
       display: inline-block;
       width: 97px;
       height: 94px;
-      background: url('@/assets/images/onlineRollCall/icon2.png') no-repeat;
+      background: url("@/assets/images/onlineRollCall/icon2.png") no-repeat;
       background-size: 100% 100%;
     }
     .icon3 {
       display: inline-block;
       width: 96px;
       height: 89px;
-      background: url('@/assets/images/onlineRollCall/icon3.png') no-repeat;
+      background: url("@/assets/images/onlineRollCall/icon3.png") no-repeat;
       background-size: 100% 100%;
     }
     .label {
-      color: #414F64;
+      color: #414f64;
       font-size: 16px;
       width: 144px;
       text-align: center;

+ 3 - 3
src/views/worker/inspectionWork/index.vue

@@ -15,8 +15,8 @@
     </div>
     <div class="content">
       <PatrolTask v-if="activeIndex === 'PatrolTask'" @changIndex="handleClickTab" />
-      <InspectionRecord v-else-if="activeIndex === 'PatrolTask'" />
-      <PatrolCalendar v-else-if="activeIndex === 'PatrolTask'" />
+      <InspectionRecord v-else-if="activeIndex === 'InspectionRecord'" />
+      <PatrolCalendar v-else-if="activeIndex === 'PatrolCalendar'" />
     </div>
   </div>
 </template>
@@ -87,7 +87,7 @@ const handleClickTab = (id) => {
   }
   .content {
     margin-top: 10px;
-    height: calc(100vh - 230px);
+    height: calc(100vh - 180px);
     overflow-y: auto;
   }
 }

+ 328 - 9
src/views/worker/inspectionWork/inspectionRecord.vue

@@ -1,11 +1,330 @@
-<script setup lang="ts">
-
-</script>
-
 <template>
+    <div class="container">
+      <van-search
+        placeholder="请输入任务名称"
+        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-dropdown-menu>
+        <van-dropdown-item
+          v-model="queryParams.type"
+          :title="!!queryParams.type ? '' : '业务'"
+          :options="businessOptions"
+          @change="change_busi_type"
+        />
+      </van-dropdown-menu>
+      <van-list
+        v-model:loading="loading"
+        v-model:error="error"
+        error-text="请求失败,点击重新加载"
+        :finished="finished"
+        finished-text="没有更多任务了"
+        @load="getList"
+      >
+        <div
+          v-for="(item, index) in taskData"
+          :key="item.id"
+          class="event-list-item"
+        >
+          <div class="item-title">
+            <div class="item-title-text">
+              {{ get_task_title(item.business) }}
+            </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">{{ get_task_cycle(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">{{ get_task_range(item.task_range) }}</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.create_time }}</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.task_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";
+  import { queryMyTaskRecord } from "@/api/inspectionWork/inspector";
+  
+  const proxy = getCurrentInstance()?.proxy;
+  const router = useRouter();
+  const taskData = ref([]);
+  const total = ref(0);
+  const loading = ref(false);
+  const error = ref(false);
+  const finished = ref(false);
+  const initFormData = reactive({
+    range: "",
+    cycle: "",
+    time: "",
+    title: "",
+    create_time: "",
+    id: 0
+  });
+  // 巡查业务选项
+  const businessOptions = [
+    { text: "全部", value: "" },
+    { text: "城市隐患巡查", value: "0" },
+    { text: "森林防火巡查", value: "1" },
+    { text: "重点危化企业巡查", value: "2" },
+    { text: "重点水库水位巡查", value: "3" }
+  ];
+  // 巡查周期选项
+  const cycleOptions = [
+    { value: '', label: '全部' },
+    { value: '0', label: '每年' },
+    { value: '1', label: '每月' },
+    { value: '2', label: '每周' },
+    { value: '3', label: '每日' },
+    { value: '4', label: '一次' }
+  ];
+  const rangeOptions = {
+        '0': '市级',
+        '1': '区县级',
+        '2': '镇街级',
+        '3': '村居级'
+  };
+  const get_task_title = (business: String) => {
+    return businessOptions.find(item => item.value == business).text
+  }
+  const get_task_cycle = (cycle: String) => {
+    return cycleOptions.find(item => item.value == cycle).label
+  }
+  const get_task_range = (range) => {
+    return rangeOptions[range]
+  }
+  const data = reactive({
+    form: { ...initFormData },
+    queryParams: {
+      search_keyword: '',
+      type: '',
+      page: 0,
+      pageSize: 10
+    }
+  });
+  const { queryParams, form } = toRefs(data);
+  // 获取列表数据的方法
+  async function getList() {
+    loading.value = true;
+    queryParams.value.page++;
+    queryMyTaskRecord(queryParams.value)
+      .then(res => {
+        var items = res.data || [];
+        total.value = res.total;
+        if (queryParams.value.page == 1) {
+          taskData.value = [];
+        }
+        items.forEach(val => {
+          taskData.value.push(val);
+        });
+        if (queryParams.value.pageSize * queryParams.value.page >= total.value) {
+          finished.value = true;
+        } else {
+          finished.value = false;
+        }
+      })
+      .catch(() => {
+        error.value = true;
+        finished.value = false;
+      })
+      .finally(() => {
+        loading.value = false;
+      });
+    /*
+    taskData.value = [
+      {id: 1, title: '巡查子任务1', cycle: '每天', range: '范围', time: '2024-10-27'},
+    ];
+    total.value = 5;
+    */
+  }
+  // 搜索关键字变化时触发的方法
+  function on_search_keyword(keyword) {
+    // 根据搜索关键字更新查询参数
+    queryParams.value.search_keyword = keyword;
+    queryParams.value.page = 0;
+    // 刷新列表数据
+    getList();
+  }
+  
+  // 右侧关闭按钮点击时触发的方法
+  const on_search_cancel = () => {
+    // 清空搜索关键字
+    queryParams.value.search_keyword = "";
+    queryParams.value.page = 0;
+    // 刷新列表数据
+    getList();
+  }
+  
+  const change_busi_type = () => {
+    queryParams.value.page = 0;
+    getList();
+  }
+  const handleView = (item) => {
+    router.push("/patorlTaskResultList?id="+item.id+"&type="+item.business+"&area_code="+item.area_code);
+  }
 
-</template>
-
-<style scoped lang="scss">
-
-</style>
+  onMounted(()=>{
+    console.log("onMounted");
+  })
+  </script>
+  
+  <style lang="scss" scoped>
+  .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: 0px;
+    }
+    .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;
+    }
+    :deep(.van-dropdown-menu__item) {
+      justify-content: right;
+      margin-right: 20px;
+    }
+  }
+  .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>
+  

+ 152 - 0
src/views/worker/inspectionWork/patorlTaskResultAdd.vue

@@ -0,0 +1,152 @@
+<template>
+    <van-form @submit="on_submit">
+        
+        <div style="padding: 16px 0 ;display:flex;flex-direction: row;justify-content: space-between;">
+            <div class="van-doc-block__title">{{get_task_title(type)}}</div>
+            <div class="van-doc-block__sub_title" @click="add" v-if="points.length < 3">新增巡查点</div>
+        </div>
+
+        <div style="padding: 8px 8px 0 8px;background: #f6f6f6" v-for="(point, index) in points" :key="index">
+            <van-field
+            v-model="point.inspection_point_name"
+                label="巡查点"
+                placeholder="填写巡查点"
+                :rules="[{ required: true, message: '请填写巡查点'  }]"
+            />
+
+            <van-field
+                v-model="point.inspection_result"
+                label="巡查结果"
+                placeholder="选择巡查结果"
+                :rules="[{ required: true, message: '请选择巡查结果'  }]"
+                readonly
+                @click="openPicker(point)"
+            />
+
+            <van-field
+            v-model="point.remark"
+                label="备注信息"
+                placeholder="填写备注信息"
+                :rules="[{ required: false, message: '请填写备注信息'  }]"
+            />
+
+            <van-field name="fileList" label="现场照片" label-align="top">
+                <template #input>
+                <FileUpload v-model="point.fileList" :fileType="['png', 'jpeg', 'jpg']"/>
+                </template>
+            </van-field>
+        </div>
+
+        <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>
+        </div>
+    </van-form>
+    <van-popup v-model:show="showPicker" round position="bottom">
+        <van-picker
+            :columns="resultOptions"
+            @cancel="showPicker = false"
+            @confirm="onConfirm"
+        />
+    </van-popup>
+</template>
+<script lang="ts" setup>
+import {reactive, ref, toRefs, onMounted} from 'vue';
+import {useRoute, useRouter} from "vue-router";
+import {addTaskResult } from "@/api/inspectionWork/inspector";
+import { showToast } from 'vant';
+
+const route = useRoute();
+const router = useRouter();
+const id = ref('');
+const type = ref('');
+const area_code = ref('');
+const showPicker = ref(false);
+
+// 巡查业务选项
+const businessOptions = [
+  { text: "全部", value: "" },
+  { text: "城市隐患巡查", value: "0" },
+  { text: "森林防火巡查", value: "1" },
+  { text: "重点危化企业巡查", value: "2" },
+  { text: "重点水库水位巡查", value: "3" }
+];
+
+const resultOptions = [
+    { value: '0', text: '正常' },
+    { value: '1', text: '异常' }
+];
+
+const onConfirm = ({selectedOptions}) => {
+  showPicker.value = false;
+  point.value.inspection_result = selectedOptions[0].text;
+}
+
+const get_task_title = (business: String) => {
+  return businessOptions.find(item => item.value == business).text
+}
+const point = ref();
+const points = ref([{
+    inspection_point_name: '',
+    inspection_result: '',
+    remark: '',
+    fileList: []
+}]);
+
+const on_submit = () => {
+    console.log('on_submit');
+    addTaskResult({
+        children_task_id: id.value,
+        result: points.value,
+        area_code: area_code.value
+    }).then((res)=>{
+        console.log(res)
+        showToast(res.msg);
+        // router.back();
+    });
+};
+
+const openPicker = (p) => {
+    point.value = p;
+    showPicker.value = true;
+};
+
+const add = () => {
+    points.value.push({
+        inspection_point_name: '',
+        inspection_result: '',
+        remark: '',
+        fileList: []
+    })
+};
+
+const handleCancel = () => {
+    router.back();
+}
+
+onMounted(() => {
+  id.value = route.query.id as string;
+  type.value = route.query.type as string;
+  area_code.value = route.query.area_code as string;
+})
+
+</script>
+
+<style lang="scss" scoped>
+.van-doc-block__title {
+  color: var(--van-doc-text-color-4);
+  margin: 0px;
+  padding: 0 6vmin;
+  font-size: 4.6vmin;
+  font-weight: 600;
+  line-height: 6.0vmin;
+}
+
+.van-doc-block__sub_title {
+    margin: 0px;
+    padding: 0 6vmin;
+    font-size: 3.6vmin;
+    font-weight: 400;
+    line-height: 6.0vmin;
+}
+</style>

+ 192 - 0
src/views/worker/inspectionWork/patorlTaskResultList.vue

@@ -0,0 +1,192 @@
+<template>
+    <div class="container">
+        <div style="padding: 16px 0 ;display:flex;flex-direction: row;justify-content: space-between;">
+            <div class="van-doc-block__title">{{get_task_title(type)}}</div>
+        </div>
+
+        <div
+          v-for="(item, index) in resultData"
+          :key="item.id"
+          class="event-list-item"
+        >
+          <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.inspection_point_name }}</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.inspection_result == 10) ? '正常' : '异常' }}</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.remark }}</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.fileList }}</div>
+            </div>
+          </div>
+        </div>
+    </div>
+</template>
+
+
+<script lang="ts" setup>
+import {reactive, ref, toRefs, onMounted} from 'vue';
+import {useRoute, useRouter} from "vue-router";
+import {listTaskResult } from "@/api/inspectionWork/inspector";
+import { showToast } from 'vant';
+
+const route = useRoute();
+const router = useRouter();
+const id = ref('');
+const type = ref('');
+const resultData = ref([]);
+
+// 巡查业务选项
+const businessOptions = [
+  { text: "全部", value: "" },
+  { text: "城市隐患巡查", value: "0" },
+  { text: "森林防火巡查", value: "1" },
+  { text: "重点危化企业巡查", value: "2" },
+  { text: "重点水库水位巡查", value: "3" }
+];
+
+const data = reactive({
+    queryParams: {
+      page: 1,
+      pageSize: 100
+    }
+});
+const { queryParams } = toRefs(data);
+
+const get_task_title = (business: String) => {
+    return businessOptions.find(item => item.value == business).text
+}
+
+const getList = () => {
+    listTaskResult(id.value, queryParams.value)
+      .then(res => {
+        resultData.value = res.data || [];
+    });
+};
+
+onMounted(() => {
+  id.value = route.query.id as string;
+  type.value = route.query.type as string;
+  getList();
+})
+</script>
+
+
+<style lang="scss" scoped>
+.van-doc-block__title {
+  color: var(--van-doc-text-color-4);
+  margin: 0px;
+  padding: 0 6vmin;
+  font-size: 4.6vmin;
+  font-weight: 600;
+  line-height: 6.0vmin;
+}
+
+.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: 0px;
+    }
+    .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;
+      }
+    }
+  }
+  .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;
+  }
+</style>

+ 279 - 3
src/views/worker/inspectionWork/patrolCalendar.vue

@@ -1,11 +1,287 @@
+
+<template>
+    <Calendar ref="calendarRef" :current="current" :dotDays="taskData.days" @change="handleChange"/>
+    <div>
+    <div
+        v-for="(item, index) in taskData.tasks"
+        :key="item.id"
+        class="event-list-item"
+      >
+        <div class="item-title">
+          <div class="item-title-text">
+            {{ get_task_title(item.business) }}
+          </div>
+          <div class="item-title-control">
+            <van-button v-if="!item.task_status" type="primary" @click="handleUploadView(item)">
+              巡查上报
+            </van-button>
+            <van-button v-if="item.task_status" type="primary" @click="handleResultView(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">{{ get_task_cycle(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">{{ get_task_range(item.task_range) }}</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.task_time }}</div>
+          </div>
+        </div>
+      </div>
+    </div>
+</template>
+
 <script setup lang="ts">
+import {onMounted, ref} from "vue";
+import { queryMyTaskByCalendar } from "@/api/inspectionWork/inspector";
+import {parseTime} from "@/utils/ruoyi";
+import { useRouter } from "vue-router";
 
-</script>
+const router = useRouter();
 
-<template>
+let calendarRef = ref();
+const current = ref('');
+const year_1 = ref('');
+const month_1 = ref('');
+const day_1 = ref('');
+const taskData  = ref({
+    days: [
+    //{ date: '2024-10-19', color: '#a2d7f1' },
+    //{ date: '2024-10-18', color: '#ffd5d8' },
+    //{ date: '2024-10-17', color: '#ffefcc' },
+    //{ date: '2024-10-16', color: '#dfdfdf' }
+    ],
+    tasks: []
+});
+
+const handleUploadView = (item) => {
+  router.push("/patorlTaskResultAdd?id="+item.id+"&type="+item.business+"&area_code="+item.area_code);
+}
+
+const handleResultView = (item) => {
+  router.push("/patorlTaskResultList?id="+item.id+"&type="+item.business+"&area_code="+item.area_code);
+}
+
+// 巡查业务选项
+const businessOptions = [
+  { text: "全部", value: "" },
+  { text: "城市隐患巡查", value: "0" },
+  { text: "森林防火巡查", value: "1" },
+  { text: "重点危化企业巡查", value: "2" },
+  { text: "重点水库水位巡查", value: "3" }
+];
+// 巡查周期选项
+const cycleOptions = [
+  { value: '', label: '全部' },
+  { value: '0', label: '每年' },
+  { value: '1', label: '每月' },
+  { value: '2', label: '每周' },
+  { value: '3', label: '每日' },
+  { value: '4', label: '一次' }
+];
+const rangeOptions = {
+      '0': '市级',
+      '1': '区县级',
+      '2': '镇街级',
+      '3': '村居级'
+};
+const get_task_title = (business: String) => {
+  return businessOptions.find(item => item.value == business).text
+}
+const get_task_cycle = (cycle: String) => {
+  return cycleOptions.find(item => item.value == cycle).label
+}
+const get_task_range = (range) => {
+  return rangeOptions[range]
+}
+
+const handleChange = (date) => {
+    year_1.value = parseTime(date.value, '{y}');
+    month_1.value = parseTime(date.value, '{m}');
+    day_1.value = parseTime(date.value, '{d}');
+    current.value = date.value;
+    console.log('handleChange:', year_1.value, month_1.value, day_1.value);
+    getList();
+}
+
+// 获取数据
+const getList = () => {
+    queryMyTaskByCalendar({year_1: year_1.value, month_1: month_1.value}).then((res)=>{
+        // console.log('res', res.data);
+        let days = [];
+        res.data.map((item, index)=>{
+            // 有事已完成
+            if(item.status == 1) {
+                days.push({"date": item.date, "color": "#a2d7f1"});
+            }
+            // 有事未完成
+            else if(item.status == 2) {
+                days.push({"date": item.date, "color": "#ffd5d8"});
+            }
+            // 未来有事
+            else if(item.status == 3) {
+                days.push({"date": item.date, "color": "#ffefcc"});
+            }
+
+            if(item.date == current.value) {
+                taskData.value.tasks = item.task_list;
+            }
+        });
+        taskData.value.days = days;
+        console.log('tasks:', taskData.value.tasks);            
+    });
+};
+
+const initData = () => {
+    year_1.value = parseTime(new Date(), '{y}');
+    month_1.value = parseTime(new Date(), '{m}');
+    day_1.value = parseTime(new Date(), '{d}');
+    current.value = parseTime(new Date(), '{y}-{m}-{d}');
+};
+
+onMounted(() => {
+    initData();
+    getList();
+})
+</script>
 
-</template>
 
 <style scoped lang="scss">
+.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: 16px;
+  }
+  .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;
+  }
+  :deep(.van-dropdown-menu__item) {
+    justify-content: right;
+    margin-right: 20px;
+  }
+}
+.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>

+ 89 - 33
src/views/worker/inspectionWork/patrolTask.vue

@@ -1,6 +1,7 @@
 <template>
   <div class="container">
     <van-search
+      placeholder="请输入任务名称"
       v-model="queryParams.search_keyword"
       class="common-search"
       :left-icon="searchImg"
@@ -8,12 +9,20 @@
       @search="on_search_keyword"
       @click-right-icon.stop="on_search_cancel"
     />
+    <van-dropdown-menu>
+      <van-dropdown-item
+        v-model="queryParams.type"
+        :title="!!queryParams.type ? '' : '业务'"
+        :options="businessOptions"
+        @change="change_busi_type"
+      />
+    </van-dropdown-menu>
     <van-list
       v-model:loading="loading"
       v-model:error="error"
       error-text="请求失败,点击重新加载"
       :finished="finished"
-      finished-text="没有更多事件了"
+      finished-text="没有更多任务了"
       @load="getList"
     >
       <div
@@ -23,7 +32,7 @@
       >
         <div class="item-title">
           <div class="item-title-text">
-            {{ item.title }}
+            {{ get_task_title(item.business) }}
           </div>
           <div class="item-title-control">
             <van-button type="primary" @click="handleView(item)">
@@ -37,21 +46,21 @@
               <i class="icon4" />
               <div class="item-data-label">巡查周期:</div>
             </div>
-            <div class="item-data-value">{{ item.cycle }}</div>
+            <div class="item-data-value">{{ get_task_cycle(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 class="item-data-value">{{ get_task_range(item.task_range) }}</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 class="item-data-value">{{ item.task_time }}</div>
           </div>
         </div>
       </div>
@@ -64,7 +73,7 @@ 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";
-import { workSubList } from "@/api/inspectionWork/inspector";
+import { queryMyTask } from "@/api/inspectionWork/inspector";
 
 const proxy = getCurrentInstance()?.proxy;
 const router = useRouter();
@@ -74,54 +83,93 @@ const loading = ref(false);
 const error = ref(false);
 const finished = ref(false);
 const initFormData = reactive({
-  scope: "",
+  range: "",
   cycle: "",
   time: "",
   title: "",
   id: 0
 });
+// 巡查业务选项
+const businessOptions = [
+  { text: "全部", value: "" },
+  { text: "城市隐患巡查", value: "0" },
+  { text: "森林防火巡查", value: "1" },
+  { text: "重点危化企业巡查", value: "2" },
+  { text: "重点水库水位巡查", value: "3" }
+];
+// 巡查周期选项
+const cycleOptions = [
+  { value: '', label: '全部' },
+  { value: '0', label: '每年' },
+  { value: '1', label: '每月' },
+  { value: '2', label: '每周' },
+  { value: '3', label: '每日' },
+  { value: '4', label: '一次' }
+];
+const rangeOptions = {
+      '0': '市级',
+      '1': '区县级',
+      '2': '镇街级',
+      '3': '村居级'
+};
+const get_task_title = (business: String) => {
+  return businessOptions.find(item => item.value == business).text
+}
+const get_task_cycle = (cycle: String) => {
+  return cycleOptions.find(item => item.value == cycle).label
+}
+const get_task_range = (range) => {
+  return rangeOptions[range]
+}
 const data = reactive({
   form: { ...initFormData },
   queryParams: {
     search_keyword: '',
-    page: 1,
+    type: '',
+    page: 0,
     pageSize: 10
   }
 });
 const { queryParams, form } = toRefs(data);
 // 获取列表数据的方法
 async function getList() {
-  /*
   loading.value = true;
-  try {
-    // 这里是获取列表数据的逻辑,可以根据实际需求进行修改
-    const res = await workSubList(
-      queryParams.value
-    );
-    taskData.value = res.data;
-    total.value = res.total;
-  } catch (err) {
-    console.error("获取列表数据出错", err);
-    error.value = true;
-  } finally {
-    loading.value = false;
-  }
-  */
-  loading.value = false;
+  queryParams.value.page++;
+  queryMyTask(queryParams.value)
+    .then(res => {
+      var items = res.data || [];
+      total.value = res.total;
+      if (queryParams.value.page == 1) {
+        taskData.value = [];
+      }
+      items.forEach(val => {
+        taskData.value.push(val);
+      });
+      if (queryParams.value.pageSize * queryParams.value.page >= total.value) {
+        finished.value = true;
+      } else {
+        finished.value = false;
+      }
+    })
+    .catch(() => {
+      error.value = true;
+      finished.value = false;
+    })
+    .finally(() => {
+      loading.value = false;
+    });
+  /*
   taskData.value = [
-    {id: 1, title: '巡查子任务1', cycle: '每天', scope: '范围', time: '2024-10-27'},
-    {id: 2, title: '巡查子任务2', cycle: '每天', scope: '范围', time: '2024-10-27'},
-    {id: 3, title: '巡查子任务3', cycle: '每天', scope: '范围', time: '2024-10-27'},
-    {id: 4, title: '巡查子任务4', cycle: '每天', scope: '范围', time: '2024-10-27'},
-    {id: 5, title: '巡查子任务5', cycle: '每天', scope: '范围', time: '2024-10-27'},
+    {id: 1, title: '巡查子任务1', cycle: '每天', range: '范围', time: '2024-10-27'},
   ];
   total.value = 5;
+  */
 }
 // 搜索关键字变化时触发的方法
 function on_search_keyword(keyword) {
   // 根据搜索关键字更新查询参数
   queryParams.value.search_keyword = keyword;
-  queryParams.value.page = 1;
+  queryParams.value.page = 0;
   // 刷新列表数据
   getList();
 }
@@ -130,13 +178,17 @@ function on_search_keyword(keyword) {
 const on_search_cancel = () => {
   // 清空搜索关键字
   queryParams.value.search_keyword = "";
-  queryParams.value.page = 1;
+  queryParams.value.page = 0;
   // 刷新列表数据
   getList();
 }
 
+const change_busi_type = () => {
+  queryParams.value.page = 0;
+  getList();
+}
 const handleView = (item) => {
-
+  router.push("/patorlTaskResultAdd?id="+item.id+"&type="+item.business+"&area_code="+item.area_code);
 }
 </script>
 
@@ -149,7 +201,7 @@ const handleView = (item) => {
   border: 0.5px solid #eaedf7;
   box-shadow: 0 0 4px 0 #4554661a;
   &:first-child {
-    margin-top: 16px;
+    margin-top: 0px;
   }
   .item-title {
     display: flex;
@@ -205,6 +257,10 @@ const handleView = (item) => {
     background: transparent;
     box-shadow: none;
   }
+  :deep(.van-dropdown-menu__item) {
+    justify-content: right;
+    margin-right: 20px;
+  }
 }
 .common-search {
   :deep(.van-field__left-icon) {

+ 217 - 0
src/views/worker/riskManagement/HiddenSource.vue

@@ -0,0 +1,217 @@
+<!--隐患源排查-->
+
+<template>
+  <van-tabs v-model:active="activeName">
+    <van-tab title="隐患源排查" name="1">
+      <van-list
+        v-model:loading="loading"
+        v-model:error="error"
+        error-text="请求失败,点击重新加载"
+        :finished="finished"
+        finished-text="没有更多事件了"
+        class="list"
+        @load="getlist"
+      >
+        <div
+          v-for="(item, index) in taskData"
+          :key="item.id"
+          class="event-list-item"
+        >
+          <div class="item-title">
+            <div class="item-title-text">隐患源排查</div>
+            <div class="item-title-control">
+              <van-button type="primary" @click="handleStartEvent(index)">
+                上报
+              </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.area }}</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.task_time }}</div>
+            </div>
+          </div>
+        </div>
+      </van-list>
+    </van-tab>
+  </van-tabs>
+</template>
+<script setup lang="ts">
+import { ref, onMounted, toRefs } from "vue";
+import { getTaskList } from "@/api/riskManagement";
+
+const total = ref(0);
+const loading = ref(false);
+const error = ref(false);
+const finished = ref(false);
+const name = ref("");
+
+const activeName = ref(0);
+const taskData = ref([]);
+
+const getlist = async () => {
+  try {
+    loading.value = true;
+    const res = await getTaskList("1");
+    loading.value = false;
+    taskData.value = res.data;
+    total.value = res.total;
+    // console.log(taskData);
+  } catch (error) {
+    console.error("请求失败", error);
+  }
+};
+onMounted(() => {
+  getlist();
+});
+</script>
+
+<style lang="scss" scoped>
+.list {
+  height: calc(100vh - 102px);
+  overflow-y: auto;
+}
+.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>

+ 5 - 0
src/views/worker/riskManagement/InvestigationRecords.vue

@@ -0,0 +1,5 @@
+<!--排查记录-->
+<template></template>
+
+<script lang="ts"></script>
+

+ 4 - 0
src/views/worker/riskManagement/dangerousSource.vue

@@ -0,0 +1,4 @@
+<!--危险源排查-->
+<template></template>
+
+<script lang="ts" setup></script>

+ 10 - 67
src/views/worker/riskManagement/index.vue

@@ -1,73 +1,16 @@
 <template>
-  <van-tabs v-model:active="active" type="card">
-    <van-tab title="风险源排查">
-      <div v-for="(item, index) in menuData" :key="index" class="task-item">
-        <div class="header">
-          <h>风险源排查任务</h>
-          <van-button type="primary" class="report-button">上报</van-button>
-        </div>
-        <p>巡检周期: {{ item.name }}</p>
-        <p>巡检范围: {{ item.range }}</p>
-        <p>要求巡检时间: {{ item.time }}</p>
-        <hr />
-      </div>
-    </van-tab>
-    <van-tab title="隐患源排查">
-      <div v-for="(item, index) in menuData" :key="index" class="task-item">
-        <div class="header">
-          <h>隐患源排查任务</h>
-          <van-button type="primary" class="report-button">上报</van-button>
-        </div>
-        <p>巡检周期: {{ item.name }}</p>
-        <p>巡检范围: {{ item.range }}</p>
-        <p>要求巡检时间: {{ item.time }}</p>
-        <hr />
-      </div>
-    </van-tab>
-    <van-tab title="危险源排查">
-      <div v-for="(item, index) in menuData" :key="index" class="task-item">
-        <div class="header">
-          <h>危险源排查任务</h>
-          <van-button type="primary" class="report-button">上报</van-button>
-        </div>
-        <p>巡检周期: {{ item.name }}</p>
-        <p>巡检范围: {{ item.range }}</p>
-        <p>要求巡检时间: {{ item.time }}</p>
-        <hr />
-      </div>
-    </van-tab>
-    <van-tab title="排查记录"></van-tab>
+  <van-tabs v-model:active="active">
+    <van-tab label="风险源排查" name="0"><riskSource /></van-tab>
+    <van-tab label="隐患源排查" name="1"><HiddenSource /></van-tab>
+    <van-tab label="危险源排查" name="2"><dangerousSource /></van-tab>
+    <van-tab label="排查记录"><investigationRecords /></van-tab>
   </van-tabs>
 </template>
 <script setup lang="ts">
-import { reactive, ref } from "vue";
+import riskSource from "./riskSource.vue";
+import HiddenSource from "./HiddenSource.vue";
+import dangerousSource from "./dangerousSource.vue";
+import investigationRecords from "./investigationRecords.vue";
+import { ref } from "vue";
 const active = ref(0);
-// 接口
-const getlist = index => {
-  console.log(index);
-};
-const menuData = reactive([
-  { name: "每周", range: "辖区内", time: "2024-10-10" },
-  { name: "每年", range: "辖区内", time: "2024-10-11" },
-  { name: "每月", range: "辖区内", time: "2024-10-12" },
-  { name: "每日", range: "辖区内", time: "2024-10-13" },
-  { name: "每周", range: "辖区内", time: "2024-10-14" }
-]);
 </script>
-
-<style scoped>
-.task-item .header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.task-item .header h {
-  margin: 0;
-  flex: 1; /* 使标题占据尽可能多的空间 */
-}
-
-.task-item .header .report-button {
-  margin-left: auto; /* 将按钮推到最右边 */
-}
-</style>

+ 216 - 0
src/views/worker/riskManagement/riskSource.vue

@@ -0,0 +1,216 @@
+<!--风险源排查-->
+<template>
+  <van-tabs v-model:active="activeName">
+    <van-tab title="风险源排查" name="0">
+      <van-list
+        v-model:loading="loading"
+        v-model:error="error"
+        error-text="请求失败,点击重新加载"
+        :finished="finished"
+        finished-text="没有更多事件了"
+        class="list"
+        @load="getlist"
+      >
+        <div
+          v-for="(item, index) in taskData"
+          :key="item.id"
+          class="event-list-item"
+        >
+          <div class="item-title">
+            <div class="item-title-text">风险源排查</div>
+            <div class="item-title-control">
+              <van-button type="primary" @click="handleStartEvent(index)">
+                上报
+              </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.area }}</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.task_time }}</div>
+            </div>
+          </div>
+        </div>
+      </van-list>
+    </van-tab>
+  </van-tabs>
+</template>
+<script setup lang="ts">
+import { ref, onMounted, toRefs } from "vue";
+import { getTaskList } from "@/api/riskManagement";
+
+const total = ref(0);
+const loading = ref(false);
+const error = ref(false);
+const finished = ref(false);
+const name = ref("");
+
+const activeName = ref(0);
+const taskData = ref([]);
+
+const getlist = async () => {
+  try {
+    loading.value = true;
+    const res = await getTaskList("0");
+    loading.value = false;
+    taskData.value = res.data;
+    total.value = res.total;
+    // console.log(taskData);
+  } catch (error) {
+    console.error("请求失败", error);
+  }
+};
+onMounted(() => {
+  getlist();
+});
+</script>
+
+<style lang="scss" scoped>
+.list {
+  height: calc(100vh - 102px);
+  overflow-y: auto;
+}
+.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>