瀏覽代碼

Merge remote-tracking branch 'origin/dev' into dev

hmm 6 月之前
父節點
當前提交
2817d9b36e

+ 20 - 0
src/api/inspectionWork/inspector.ts

@@ -147,3 +147,23 @@ export function fileDownload(url) {
     params: url
   });
 }
+// 查询巡查已完成果列表
+export function patrolNum(children_task_id, queryParams) {
+  return request({
+    url: '/api/riskManagement/inspection/task/children/task/log/' + children_task_id + '/' + 'completed' + '/list',
+    method: 'get',
+    params: {
+      area_code: queryParams.area_code
+    }
+  });
+}
+// 查询巡查未完成果列表
+export function patrolNum_1(children_task_id, queryParams) {
+  return request({
+    url: '/api/riskManagement/inspection/task/children/task/log/' + children_task_id + '/' + 'incomplete' + '/list',
+    method: 'get',
+    params: {
+      area_code: queryParams.area_code
+    }
+  });
+}

+ 2 - 0
src/types/components.d.ts

@@ -54,6 +54,8 @@ declare module 'vue' {
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSelect: typeof import('element-plus/es')['ElSelect']
+    ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
+    ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
     ElSlider: typeof import('element-plus/es')['ElSlider']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']

+ 124 - 0
src/views/dataFilling/formDetail.vue

@@ -0,0 +1,124 @@
+<template>
+  <div class="app-container p-2">
+    <el-row :gutter="20">
+      <el-col :lg="30" :xs="24" style="">
+        <el-row :span="24" :gutter="10">
+          <el-col :span="18" label="任务名称">
+            <h2 v-if="detailData.title" key="business" style="font-weight: bolder">{{ detailData.title }}</h2>
+            <p class="report-period">【填报周期】:{{ detailData.start }} 至 {{ detailData.end }}</p>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" @click="exportToExcel()"> 导出表格 </el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="danger" @click="handleReturn()"> 返回 </el-button>
+          </el-col>
+        </el-row>
+      </el-col>
+      <el-col :lg="30" :xs="24">
+        <el-table :data="tableData" border>
+          <el-table-column v-for="header in editableHeaders" :key="header" :label="header" :prop="header">
+            <template #header="{ column }">
+              <span class="editable-header" v-text="column.label"></span>
+            </template>
+            <template #default="{ row, $index }">
+              <span class="editable-span" v-text="row[header]"></span>
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted } from 'vue';
+import { ElTable, ElButton, ElCol, ElRow, ElTableColumn } from 'element-plus';
+import * as XLSX from 'xlsx';
+
+const emits = defineEmits(['close']);
+const detailData = ref({
+  title: '测试表单',
+  start: '2024-10-15 17:02:22',
+  end: '2024-10-15 18:00:00'
+});
+
+const editableHeaders = ref(['时间', '地点', '损坏程度', '救援人员', '物资']);
+const tableData = ref([]);
+
+onMounted(() => {
+  loadFromLocalStorage();
+  addDefaultRow();
+});
+
+function loadFromLocalStorage() {
+  const storedData = localStorage.getItem('tableData');
+  if (storedData) {
+    tableData.value = JSON.parse(storedData);
+  } else {
+    tableData.value = [
+      {
+        时间: '2024-01-01',
+        地点: '某地',
+        损坏程度: '轻度',
+        救援人员: '张三, 李四',
+        物资: '食品, 水'
+      },
+      {
+        时间: '2024-01-02',
+        地点: '某地',
+        损坏程度: '中度',
+        救援人员: '王五, 赵六',
+        物资: '帐篷, 医疗用品'
+      }
+    ];
+  }
+}
+
+function addDefaultRow() {
+  tableData.value.push({
+    时间: '',
+    地点: '',
+    损坏程度: '',
+    救援人员: '',
+    物资: ''
+  });
+}
+
+const exportToExcel = () => {
+  const worksheet = XLSX.utils.json_to_sheet(tableData.value);
+  const workbook = { Sheets: { data: worksheet }, SheetNames: ['data'] };
+  const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
+
+  const blob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
+  const link = document.createElement('a');
+  const url = window.URL.createObjectURL(blob);
+  link.href = url;
+  link.download = 'SheetJS.xlsx';
+  link.click();
+  window.URL.revokeObjectURL(url); // 清理
+};
+const handleReturn = () => {
+  emits('close');
+};
+</script>
+
+<style scoped>
+.app-container {
+  font-family: Avenir, Helvetica, Arial, sans-serif;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  color: #2c3e50;
+}
+.report-period {
+  margin-top: 10px;
+  font-size: 14px;
+  color: #606266;
+}
+.editable-span {
+  cursor: default;
+}
+.editable-header {
+  cursor: default;
+}
+</style>

+ 14 - 1
src/views/dataFilling/myFilling.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <div v-show="!writeFormState.show" class="app-container">
+    <div v-show="!writeFormState.show && !formDetailState.show" class="app-container">
       <div>
         <transition name="fade">
           <div v-show="showSearch">
@@ -46,10 +46,12 @@
     </div>
   </div>
   <WriteForm v-if="writeFormState.show" :event-id="writeFormState.eventId" @close="handleCancel" />
+  <FormDetail v-if="formDetailState.show" :event-id="formDetailState.eventId" @close="handleCancel" />
 </template>
 <script setup lang="ts">
 import { onMounted, reactive, ref } from 'vue';
 import WriteForm from './writeForm.vue';
+import FormDetail from './formDetail.vue';
 const loading = ref(true);
 const showSearch = ref(true);
 const multiple = ref(true);
@@ -104,8 +106,13 @@ let writeFormState = reactive({
   show: false,
   eventId: ''
 });
+let formDetailState = reactive({
+  show: false,
+  eventId: ''
+});
 const handleCancel = () => {
   writeFormState.show = false;
+  formDetailState.show = false;
 };
 const handleWrite = (row) => {
   if (row) {
@@ -113,6 +120,12 @@ const handleWrite = (row) => {
     writeFormState.show = true;
   }
 };
+const handleView = (row) => {
+  if (row) {
+    formDetailState.eventId = row.id;
+    formDetailState.show = true;
+  }
+};
 // 初始化数据
 onMounted(() => {
   tableData.value = staticData;

+ 41 - 22
src/views/dataFilling/writeForm.vue

@@ -62,7 +62,7 @@
 import { ref, onMounted } from 'vue';
 import { ElTable, ElButton, ElCol, ElRow, ElTableColumn } from 'element-plus';
 import * as XLSX from 'xlsx';
-
+const emits = defineEmits(['close']);
 const detailData = ref({
   title: '测试表单',
   start: '2024-10-15 17:02:22',
@@ -70,22 +70,38 @@ const detailData = ref({
 });
 
 const editableHeaders = ref(['时间', '地点', '损坏程度', '救援人员', '物资']);
-const tableData = ref([
-  {
-    时间: '2024-01-01',
-    地点: '某地',
-    损坏程度: '轻度',
-    救援人员: '张三, 李四',
-    物资: '食品, 水'
-  },
-  {
-    时间: '2024-01-02',
-    地点: '某地',
-    损坏程度: '中度',
-    救援人员: '王五, 赵六',
-    物资: '帐篷, 医疗用品'
+const tableData = ref([]);
+
+// 初始化表格数据
+onMounted(() => {
+  loadFromLocalStorage();
+  addDefaultRow();
+});
+
+// 加载数据
+function loadFromLocalStorage() {
+  const storedData = localStorage.getItem('tableData');
+  if (storedData) {
+    tableData.value = JSON.parse(storedData);
+  } else {
+    tableData.value = [
+      {
+        时间: '2024-01-01',
+        地点: '某地',
+        损坏程度: '轻度',
+        救援人员: '张三, 李四',
+        物资: '食品, 水'
+      },
+      {
+        时间: '2024-01-02',
+        地点: '某地',
+        损坏程度: '中度',
+        救援人员: '王五, 赵六',
+        物资: '帐篷, 医疗用品'
+      }
+    ];
   }
-]);
+}
 
 function saveEdit(rowIndex, header, value) {
   tableData.value[rowIndex][header] = value;
@@ -108,10 +124,6 @@ function addDefaultRow() {
   });
 }
 
-onMounted(() => {
-  addDefaultRow();
-});
-
 const exportToExcel = () => {
   const worksheet = XLSX.utils.json_to_sheet(tableData.value);
   const workbook = { Sheets: { data: worksheet }, SheetNames: ['data'] };
@@ -130,8 +142,15 @@ const handleAdd = () => console.log('批量导入');
 const handleDownloadEmptyTable = () => console.log('下载空表格');
 const handleAddRow = () => addDefaultRow();
 const handleReport = () => console.log('上报');
-const handleSave = () => console.log('保存');
-const handleReturn = () => console.log('返回');
+
+const handleSave = () => {
+  // 保存本地状态
+  localStorage.setItem('tableData', JSON.stringify(tableData.value));
+  alert('数据已保存');
+};
+const handleReturn = () => {
+  emits('close');
+};
 </script>
 
 <style scoped>

+ 48 - 0
src/views/globalMap/RightMenu/GridPointRainfall.vue

@@ -0,0 +1,48 @@
+<template>
+  <Dialog custom-show title="格点雨量" :height="'450px'" hide-footer @close="handleClose">
+    <div class="gradient-text title">雨量统计:{{ address }}({{ location[0] }}, {{ location[1] }})</div>
+    <Chart :option="chartOption" style="height: 360px" />
+  </Dialog>
+</template>
+
+<script lang="ts" setup name="GridPointRainfall">
+import { option9 } from '@/views/globalMap/RightMenu/echartOptions';
+import AMapLoader from '@amap/amap-jsapi-loader';
+
+interface Props {
+  modelValue: boolean;
+  location?: string | number[];
+}
+const props = withDefaults(defineProps<Props>(), {});
+const emits = defineEmits(['update:modelValue']);
+let address = ref('');
+let chartOption = ref(option9);
+const handleClose = () => {
+  emits('update:modelValue', false);
+};
+let AMap, geocoder;
+onMounted(() => {
+  AMapLoader.load({
+    key: '30d3d8448efd68cb0b284549fd41adcf', // 申请好的Web端开发者Key,首次调用 load 时必填
+    version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
+    plugins: ['AMap.PlaceSearch', 'AMap.ContextMenu', 'AMap.PolygonEditor', 'AMap.Geocoder'] // 插件列表
+  }).then((res) => {
+    AMap = res;
+    geocoder = new AMap.Geocoder({
+      // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
+      city: '010'
+    });
+    geocoder.getAddress(props.location, (status, result) => {
+      if (status === 'complete' && result.info === 'OK') {
+        address.value = result.regeocode.formattedAddress;
+      }
+    });
+  });
+  chartOption.value.series[0].data = [820, 932, 901, 934, 1290, 1330];
+  chartOption.value.series[1].data = ['', '', '', '', '', 1330, 901, 934, 1290, 1330, 1320];
+});
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 98 - 6
src/views/globalMap/RightMenu/echartOptions.ts

@@ -9,7 +9,7 @@ export const option1 = {
     type: 'category',
     axisLabel: {
       color: '#A8CCDE',
-      fontSize: 32
+      fontSize: 16
     },
     axisTick: false,
     data: []
@@ -22,7 +22,7 @@ export const option1 = {
     },
     axisLabel: {
       color: '#A8CCDE',
-      fontSize: 32
+      fontSize: 16
     }
   },
   series: [
@@ -88,7 +88,7 @@ export const option2 = {
     type: 'plain',
     show: true,
     textStyle: {
-      fontSize: '32',
+      fontSize: '16',
       color: '#A8CCDE'
     },
     data: ['警戒线', '河流水位']
@@ -111,7 +111,7 @@ export const option2 = {
         //坐标轴刻度标签的相关设置
         textStyle: {
           color: '#A8CCDE',
-          fontSize: 32
+          fontSize: 16
         }
       },
       splitLine: {
@@ -131,7 +131,7 @@ export const option2 = {
       name: '水位:m',
       nameTextStyle: {
         color: '#A8CCDE',
-        fontSize: 32,
+        fontSize: 16,
         padding: [10, 0]
       },
       min: 0,
@@ -148,7 +148,7 @@ export const option2 = {
         show: true,
         textStyle: {
           color: '#A8CCDE',
-          fontSize: 32
+          fontSize: 16
         }
       },
       axisTick: {
@@ -707,3 +707,95 @@ export const option8 = {
     }
   ]
 };
+
+// 格点雨量
+export const option9 = {
+  legend: {
+    show: true,
+    icon: 'rect',
+    textStyle: {
+      fontSize: '16',
+      color: '#A8CCDE'
+    },
+    data: ['过去累计雨量', '未来累计雨量']
+  },
+  color: ['#467cd1', '#bcbcbc'],
+  xAxis: {
+    type: 'category',
+    axisLabel: {
+      textStyle: {
+        color: '#a7ccdf',
+        fontFamily: '微软雅黑',
+        fontSize: 16
+      }
+    },
+    data: ['-24h', '-12h', '-6h', '-3h', '-1h', '现在', '1h', '3h', '24h', '40h', '70h']
+  },
+  yAxis: {
+    type: 'value',
+    axisLabel: {
+      textStyle: {
+        color: '#a7ccdf',
+        fontFamily: '微软雅黑',
+        fontSize: 16
+      }
+    },
+    splitLine: {
+      lineStyle: {
+        color: '#0c2c5a'
+      }
+    },
+    axisLine: {
+      show: false
+    }
+  },
+  series: [
+    {
+      name: '过去累计雨量',
+      data: [820, 932, 901, 934, 1290, 1330],
+      label: {
+        show: true, // 显示标签
+        color: '#a7ccdf',
+        fontFamily: '微软雅黑',
+        fontSize: 16,
+        position: 'top' // 标签位置,可以是 'top'、'bottom'、'left'、'right' 等
+      },
+      markLine: {
+        symbol: 'none',
+        data: [
+          {
+            xAxis: 5, // "现在"的索引为1(从0开始计数)
+            yAxis: null, // yAxis为null表示竖线贯穿整个y轴
+            label: { show: false },
+            lineStyle: {
+              width: 2,
+              color: 'red',
+              type: 'solid'
+            }
+          }
+        ]
+      },
+      lineStyle: {
+        width: 2
+      },
+      type: 'line',
+      smooth: true
+    },
+    {
+      name: '未来累计雨量',
+      label: {
+        show: true, // 显示标签
+        color: '#a7ccdf',
+        fontFamily: '微软雅黑',
+        fontSize: 16,
+        position: 'top' // 标签位置,可以是 'top'、'bottom'、'left'、'right' 等
+      },
+      data: ['', '', '', '', '', 1330, 901, 934, 1290, 1330, 1320],
+      lineStyle: {
+        width: 2
+      },
+      type: 'line',
+      smooth: true
+    }
+  ]
+};

+ 23 - 6
src/views/globalMap/index.vue

@@ -26,6 +26,7 @@
       <TimeAxis />
       <DrawTools v-if="showDrawTools" @handle-analysis-data="handleAnalysisData" />
       <NearbyVideos v-if="showNearbyVideos" v-model="showNearbyVideos" :location="location" />
+      <GridPointRainfall v-if="showRainfall" v-model="showRainfall" :location="location" />
       <MaterialDetail v-if="showWarehouse" v-model="showWarehouse" :warehouse-data="warehouseData" />
       <CommunicationSupport v-if="communicationSupport.show" @close="handleHideCommunicationSupport" />
     </div>
@@ -46,6 +47,7 @@ import RightMenu from './RightMenu/index.vue';
 import { PointType } from '@/api/globalMap/type';
 import DrawTools from '@/views/globalMap/RightMenu/DrawTools.vue';
 import CommunicationSupport from '@/views/globalMap/RightMenu/CommunicationSupport.vue';
+import GridPointRainfall from '@/views/globalMap/RightMenu/GridPointRainfall.vue';
 import NearbyVideos from '@/components/NearbyVideos/index.vue';
 
 const rightMenuRef = ref(null);
@@ -57,7 +59,7 @@ let leftMenuRef = ref(null);
 //  vectorgraph satellite imageMap 废弃:logical satellite2 satellite3
 let activeMap = ref('satellite');
 // 附近视频菜单数据
-let videoMenu = ref({});
+let tempMenu = ref({});
 const communicationSupport = reactive({
   show: false,
   data: {}
@@ -152,7 +154,7 @@ const clickMenu = (item, dataList) => {
     communicationSupport.show = !communicationSupport.show;
     communicationSupport.data = item;
   } else if (item.path === '4') {
-    videoMenu.value = item;
+    tempMenu.value = item;
     // 附近视频
     map = getMap();
     //为地图注册click事件获取鼠标点击出的经纬度坐标
@@ -240,13 +242,24 @@ const trackPlayback = (data) => {
   return {};
 };
 let showNearbyVideos = ref(false);
+let showRainfall = ref(false);
 let location = ref([]);
 watch(showNearbyVideos, () => {
   if (!showNearbyVideos.value) {
     location.value = [];
-    if (!!videoMenu.value) {
-      leftMenuRef.value.setMenuChange(videoMenu.value, false);
-      videoMenu.value = {};
+    if (!!tempMenu.value) {
+      leftMenuRef.value.setMenuChange(tempMenu.value, false);
+      tempMenu.value = {};
+      map.off('click', handleClickMap);
+    }
+  }
+});
+watch(showRainfall, () => {
+  if (!showRainfall.value) {
+    location.value = [];
+    if (!!tempMenu.value) {
+      leftMenuRef.value.setMenuChange(tempMenu.value, false);
+      tempMenu.value = {};
       map.off('click', handleClickMap);
     }
   }
@@ -258,7 +271,11 @@ const handleShowVideo = (data) => {
 };
 const handleClickMap = (e) => {
   location.value = [e.lnglat.getLng(), e.lnglat.getLat()];
-  showNearbyVideos.value = true;
+  if (!!tempMenu.value && tempMenu.value.name === '附近视频') {
+    showNearbyVideos.value = true;
+  } else if (!!tempMenu.value && tempMenu.value.name === '格点雨量') {
+    showRainfall.value = true;
+  }
 };
 let showWarehouse = ref(false);
 let warehouseData = ref('');

+ 149 - 0
src/views/inspectionWork/completed.vue

@@ -0,0 +1,149 @@
+<template>
+  <el-dialog v-model="showSearch" title="已完成" width="80%" @close="$emit('close')">
+    <el-row :gutter="20">
+      <el-col :lg="4" :xs="24">
+        <el-tree
+          ref="deptTreeRef"
+          class="mt-2"
+          node-key="id"
+          :data="deptOptions"
+          :props="{ label: 'label', children: 'children' }"
+          :expand-on-click-node="false"
+          :filter-node-method="filterNode"
+          highlight-current
+          default-expand-all
+          @node-click="handleNodeClick"
+        />
+      </el-col>
+      <el-col :lg="20" :xs="24">
+        <transition name="fade">
+          <div v-show="showSearch">
+            <el-form ref="queryFormRef" :model="queryParams">
+              <el-button type="primary" @click="handleExport">导出</el-button>
+            </el-form>
+          </div>
+        </transition>
+        <el-table ref="multipleTable" v-loading="loading" :data="tableData" @selection-change="handleSelectionChange">
+          <el-table-column label="排查范围" align="center" prop="area" />
+          <el-table-column label="任务进度" align="center" prop="task_status">
+            <!-- 使用自定义槽来渲染转换后的文本 -->
+            <template #default="scope">
+              {{ formatStatus(scope.row.task_status) }}
+            </template>
+          </el-table-column>
+          <el-table-column label="巡查人员" align="center" prop="nick_name" />
+          <el-table-column label="上报时间" align="center" prop="create_time" />
+        </el-table>
+      </el-col>
+    </el-row>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { onMounted, reactive, ref, watch } from 'vue';
+import { useRouter } from 'vue-router';
+import { inspectorDivision, patrolNum } from '@/api/inspectionWork/inspector';
+
+const router = useRouter();
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref<Array<number | string>>([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const deptOptions = ref([]);
+const deptTreeRef = ref(null);
+const tableData = ref([]);
+const props = defineProps<{ eventId: string }>();
+
+const initFormData = reactive({
+  area: '',
+  task_status: '',
+  yzy_organization: '',
+  nick_name: '',
+  create_time: ''
+});
+
+const data = reactive({
+  form: { ...initFormData },
+  queryParams: {
+    area_code: '',
+    deptId: ''
+  }
+});
+
+const { queryParams, form } = toRefs(data);
+const formatStatus = (status) => {
+  return Number(status) === 1 ? '已完成' : '未完成';
+};
+
+const filterNode = (value: string, data: any) => {
+  if (!value) return true;
+  return data.label.indexOf(value) !== -1;
+};
+
+const getTreeSelect = async () => {
+  const res = await inspectorDivision();
+  if (res.code === 200) {
+    deptOptions.value = res.data; // 将部门树数据赋值给deptOptions
+  } else {
+    console.error(res.msg);
+  }
+  loading.value = false; // 加载完成后关闭加载提示
+};
+
+const fetchUserData = async () => {
+  loading.value = true; // 开始加载
+
+  // 构造请求参数
+  const params = {
+    ...queryParams.value,
+    // 只在area_code有值时添加到请求参数中
+    ...(queryParams.value.area_code ? { area_code: queryParams.value.area_code } : {})
+  };
+
+  return patrolNum(props.eventId, params)
+    .then((res) => {
+      if (res.code === 200) {
+        tableData.value = res.data; // 确保tableData是一个数组
+        total.value = res.total;
+      } else {
+        console.error(res.msg);
+      }
+      loading.value = false; // 结束加载
+    })
+    .catch((error) => {
+      console.error('Error fetching sub tasks:', error);
+      loading.value = false; // 结束加载
+    });
+};
+
+watch(queryParams, () => {
+  fetchUserData();
+});
+
+const handleNodeClick = (data: any) => {
+  queryParams.value.deptId = data.id;
+  queryParams.value.area_code = data.code; // 设置area_code为点击节点的code值
+  fetchUserData();
+};
+
+const handleSelectionChange = (selection) => {
+  ids.value = selection.map((item) => item.id);
+};
+
+onMounted(async () => {
+  await getTreeSelect();
+  fetchUserData();
+});
+</script>
+
+<style scoped>
+.mt-2 {
+  max-width: 300px; /* 设置最大宽度 */
+  max-height: 800px; /* 设置最大高度 */
+  overflow-y: auto; /* 如果内容超出高度则显示滚动条 */
+}
+</style>

+ 149 - 0
src/views/inspectionWork/incompleted.vue

@@ -0,0 +1,149 @@
+<template>
+  <el-dialog v-model="showSearch" title="未完成" width="80%" @close="$emit('close')">
+    <el-row :gutter="20">
+      <el-col :lg="4" :xs="24">
+        <el-tree
+          ref="deptTreeRef"
+          class="mt-2"
+          node-key="id"
+          :data="deptOptions"
+          :props="{ label: 'label', children: 'children' }"
+          :expand-on-click-node="false"
+          :filter-node-method="filterNode"
+          highlight-current
+          default-expand-all
+          @node-click="handleNodeClick"
+        />
+      </el-col>
+      <el-col :lg="20" :xs="24">
+        <transition name="fade">
+          <div v-show="showSearch">
+            <el-form ref="queryFormRef" :model="queryParams">
+              <el-button type="primary" @click="handleExport">导出</el-button>
+            </el-form>
+          </div>
+        </transition>
+        <el-table ref="multipleTable" v-loading="loading" :data="tableData" @selection-change="handleSelectionChange">
+          <el-table-column label="排查范围" align="center" prop="area" />
+          <el-table-column label="任务进度" align="center" prop="task_status">
+            <!-- 使用自定义槽来渲染转换后的文本 -->
+            <template #default="scope">
+              {{ formatStatus(scope.row.task_status) }}
+            </template>
+          </el-table-column>
+          <el-table-column label="巡查人员" align="center" prop="nick_name" />
+          <el-table-column label="上报时间" align="center" prop="create_time" />
+        </el-table>
+      </el-col>
+    </el-row>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { onMounted, reactive, ref, watch } from 'vue';
+import { useRouter } from 'vue-router';
+import { inspectorDivision, patrolNum_1 } from '@/api/inspectionWork/inspector';
+
+const router = useRouter();
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref<Array<number | string>>([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const deptOptions = ref([]);
+const deptTreeRef = ref(null);
+const tableData = ref([]);
+const props = defineProps<{ eventId: string }>();
+
+const initFormData = reactive({
+  area: '',
+  task_status: '',
+  yzy_organization: '',
+  nick_name: '',
+  create_time: ''
+});
+
+const data = reactive({
+  form: { ...initFormData },
+  queryParams: {
+    area_code: '',
+    deptId: ''
+  }
+});
+
+const { queryParams, form } = toRefs(data);
+
+const formatStatus = (status) => {
+  return Number(status) === 1 ? '已完成' : '未完成';
+};
+
+const filterNode = (value: string, data: any) => {
+  if (!value) return true;
+  return data.label.indexOf(value) !== -1;
+};
+
+const getTreeSelect = async () => {
+  const res = await inspectorDivision();
+  if (res.code === 200) {
+    deptOptions.value = res.data; // 将部门树数据赋值给deptOptions
+  } else {
+    console.error(res.msg);
+  }
+  loading.value = false; // 加载完成后关闭加载提示
+};
+
+const fetchUserData = async () => {
+  loading.value = true; // 开始加载
+
+  // 构造请求参数
+  const params = {
+    ...queryParams.value,
+    // 只在area_code有值时添加到请求参数中
+    ...(queryParams.value.area_code ? { area_code: queryParams.value.area_code } : {})
+  };
+
+  return patrolNum_1(props.eventId, params)
+    .then((res) => {
+      if (res.code === 200) {
+        tableData.value = res.data; // 确保tableData是一个数组
+        total.value = res.total;
+      } else {
+        console.error(res.msg);
+      }
+      loading.value = false; // 结束加载
+    })
+    .catch((error) => {
+      console.error('Error fetching sub tasks:', error);
+      loading.value = false; // 结束加载
+    });
+};
+watch(queryParams, () => {
+  fetchUserData();
+});
+
+const handleNodeClick = (data: any) => {
+  queryParams.value.deptId = data.id;
+  queryParams.value.area_code = data.code; // 设置 area_code
+  fetchUserData(); // 调用 fetchUserData 函数更新表格数据
+};
+
+const handleSelectionChange = (selection) => {
+  ids.value = selection.map((item) => item.id);
+};
+
+onMounted(async () => {
+  await getTreeSelect();
+  fetchUserData();
+});
+</script>
+
+<style scoped>
+.mt-2 {
+  max-width: 300px; /* 设置最大宽度 */
+  max-height: 800px; /* 设置最大高度 */
+  overflow-y: auto; /* 如果内容超出高度则显示滚动条 */
+}
+</style>

+ 2 - 2
src/views/inspectionWork/inspector.vue

@@ -60,9 +60,9 @@
         <pagination v-show="total > 0" v-model:page="queryParams.page" v-model:limit="queryParams.pageSize" :total="total" @pagination="tableData" />
       </el-col>
     </el-row>
+    <InspectorEdit v-if="inspectorEditState.show" :event-id="inspectorEditState.eventId" @close="handleCancel" />
+    <InspectorAdd v-if="inspectorAddState.show" @close="handleCancel" @refresh="fetchUserData" />
   </div>
-  <InspectorEdit v-if="inspectorEditState.show" :event-id="inspectorEditState.eventId" @close="handleCancel" />
-  <InspectorAdd v-if="inspectorAddState.show" @close="handleCancel" @refresh="fetchUserData" />
 </template>
 
 <script setup lang="ts">

+ 4 - 2
src/views/inspectionWork/inspectorAdd.vue

@@ -50,7 +50,7 @@ import { useRouter } from 'vue-router';
 
 const emits = defineEmits(['close']);
 const props = defineProps<{
-  eventId: string | number;
+  // eventId: string | number;
 }>();
 
 const formData = ref({
@@ -59,7 +59,9 @@ const formData = ref({
   phonenumber: '',
   uuid: ''
 });
-
+const rules = ref({
+  // id: [{ required: true, message: '主键不能为空', trigger: 'blur' }],
+});
 const treeData = ref([]);
 const rawDivisionData = ref([]);
 const formattedDivisionData = ref([]);

+ 3 - 0
src/views/inspectionWork/inspectorEdit.vue

@@ -41,6 +41,9 @@ const formData = ref({
   yzy_account: '',
   area: ''
 });
+const rules = ref({
+  // id: [{ required: true, message: '主键不能为空', trigger: 'blur' }],
+});
 const fetchDetail = async () => {
   const response = await inspectorDetail(props.eventId);
   if (response.code === 200) {

+ 5 - 2
src/views/inspectionWork/patrolSubResult.vue

@@ -102,8 +102,8 @@ const initFormData = reactive({
 const data = reactive({
   form: { ...initFormData },
   queryParams: {
-    page: '',
-    pageSize: '',
+    page: 1,
+    pageSize: 10,
     inspection_result: '',
     area_code: '',
     nick_name: ''
@@ -172,6 +172,9 @@ const handleQuery = () => {
   queryParams.value.page = 1;
   fetchResulData();
 };
+const handleExport = () => {
+  ElMessage.info("导出成功");
+};
 // 重置查询条件
 const resetQuery = () => {
   queryParams.value = { page: 1, pageSize: 10, nick_name: '', area_code: '', inspection_result: '' };

+ 36 - 2
src/views/inspectionWork/patrolSubTasks.vue

@@ -47,8 +47,16 @@
             <el-table-column label="巡查周期" align="center" :formatter="(row) => cycleMap[row.cycle]" />
             <el-table-column label="巡查范围" align="center" :formatter="(row) => inspectionRangeMap[row.inspection_range]" />
             <el-table-column label="执行日期" align="center" prop="create_time" />
-            <el-table-column label="已完成" align="center" prop="completed_num" />
-            <el-table-column label="未完成" align="center" prop="incomplete_num" />
+            <el-table-column label="已完成" align="center" prop="completed_num">
+              <template #default="scope">
+                <el-text class="common-btn-text-primary" @click="handleCompletedClick(scope.row)">{{ scope.row.completed_num }}</el-text>
+              </template>
+            </el-table-column>
+            <el-table-column label="未完成" align="center" prop="incomplete_num">
+            <template #default="scope">
+              <el-text class="common-btn-text-primary" @click="handleIncompletedClick(scope.row)">{{ scope.row.incomplete_num }}</el-text>
+            </template>
+            </el-table-column>
             <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
               <template #default="scope">
                 <el-text class="common-btn-text-primary" @click="handleResult(scope.row)">巡查结果</el-text>
@@ -68,6 +76,8 @@
   </div>
   <PatrolSubResult v-if="patrolSubResultState.show" :event-id="patrolSubResultState.eventId" @close="handleCancel" />
   <PatrolTaskEdit v-if="patrolTaskEditState.show" :event-id="patrolTaskEditState.eventId" @close="handleCancel" @refresh-parent="refreshBoth" />
+  <Completed v-if="completedState.show" :event-id="completedState.eventId" @close="handleCancel" />
+  <Incompleted v-if="incompletedState.show" :event-id="incompletedState.eventId" @close="handleCancel" />
 </template>
 <script setup lang="ts">
 import { workDetail, workSubList, updatetask, deleteRisk } from '@/api/inspectionWork/inspector';
@@ -75,6 +85,8 @@ import { reactive, ref } from 'vue';
 import { ElMessageBox } from 'element-plus';
 import PatrolSubResult from './patrolSubResult.vue';
 import PatrolTaskEdit from './patrolTaskEdit.vue';
+import Completed from './completed.vue';
+import Incompleted from './incompleted.vue';
 import { to } from 'await-to-js';
 const props = defineProps<{ eventId: string }>();
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -150,9 +162,19 @@ let patrolSubResultState = reactive({
   show: false,
   eventId: ''
 });
+let completedState = reactive({
+  show: false,
+  eventId: ''
+});
+let incompletedState = reactive({
+  show: false,
+  eventId: ''
+});
 const handleCancel = () => {
   patrolTaskEditState.show = false;
   patrolSubResultState.show = false;
+  completedState.show = false;
+  incompletedState.show = false;
 };
 const handleUpdate = () => {
   patrolTaskEditState.eventId = props.eventId; // 假设eventId是id字段
@@ -164,6 +186,18 @@ const handleResult = (row) => {
     patrolSubResultState.show = true;
   }
 };
+const handleCompletedClick = (row) => {
+  if (row) {
+    completedState.eventId = row.id; // 假设eventId是id字段
+    completedState.show = true;
+  }
+};
+const handleIncompletedClick = (row) => {
+  if (row) {
+    incompletedState.eventId = row.id; // 假设eventId是id字段
+    incompletedState.show = true;
+  }
+};
 const loading = ref(false);
 const fetchWorkDetail = () => {
   loading.value = true;

+ 5 - 5
src/views/inspectionWork/patrolTask.vue

@@ -75,10 +75,10 @@
         <pagination v-show="total > 0" v-model:page="queryParams.page" v-model:limit="queryParams.pageSize" :total="total" @pagination="tableData" />
       </div>
     </div>
+    <PatrolSubTasks v-if="patrolSubTasksState.show" :event-id="patrolSubTasksState.eventId" @close="handleCancel" @refreshsub="fetchWorkrData" />
+    <PatrolTaskEdit v-if="patrolTaskEditState.show" :event-id="patrolTaskEditState.eventId" @close="handleCancel" @refresh="fetchWorkrData" />
+    <PatrolTaskAdd v-if="patrolTaskAddState.show" @close="handleCancel" @refresh="fetchWorkrData" />
   </div>
-  <PatrolSubTasks v-if="patrolSubTasksState.show" :event-id="patrolSubTasksState.eventId" @close="handleCancel" @refreshsub="fetchWorkrData" />
-  <PatrolTaskEdit v-if="patrolTaskEditState.show" :event-id="patrolTaskEditState.eventId" @close="handleCancel" @refresh="fetchWorkrData" />
-  <PatrolTaskAdd v-if="patrolTaskAddState.show" @close="handleCancel" @refresh="fetchWorkrData" />
 </template>
 <script setup lang="ts">
 import { onMounted, reactive, ref } from 'vue';
@@ -197,7 +197,7 @@ const handleCancel = () => {
 };
 const openPatrolSubTasks = (row) => {
   if (row) {
-    patrolSubTasksState.eventId = row.id; // 假设eventId是id字段
+    patrolSubTasksState.eventId = row.id + ""; // 假设eventId是id字段
     patrolSubTasksState.show = true;
   }
 };
@@ -206,7 +206,7 @@ const handleAdd = () => {
 };
 const handleUpdate = (row) => {
   if (row) {
-    patrolTaskEditState.eventId = row.id; // 假设eventId是id字段
+    patrolTaskEditState.eventId = row.id + ""; // 假设eventId是id字段
     patrolTaskEditState.show = true;
   }
 };

+ 3 - 0
src/views/inspectionWork/patrolTaskEdit.vue

@@ -97,6 +97,9 @@ const fetchDetail = async () => {
     ElMessage.error(response.msg);
   }
 };
+const rules = ref({
+  // id: [{ required: true, message: '主键不能为空', trigger: 'blur' }],
+});
 watch(
   () => props.eventId,
   (newVal) => {