Browse Source

地质灾害 对接接口

Hwf 2 tháng trước cách đây
mục cha
commit
b5b7ef09be

+ 2 - 1
package.json

@@ -44,7 +44,8 @@
     "uuid": "^10.0.0",
     "vant": "^4.9.0",
     "vue": "^3.4.27",
-    "vue-router": "^4.3.2"
+    "vue-router": "^4.3.2",
+    "vue-types": "^6.0.0"
   },
   "devDependencies": {
     "@commitlint/config-conventional": "^19.2.2",

+ 16 - 0
pnpm-lock.yaml

@@ -89,6 +89,9 @@ importers:
       vue-router:
         specifier: ^4.3.2
         version: 4.4.5(vue@3.5.11(typescript@5.4.5))
+      vue-types:
+        specifier: ^6.0.0
+        version: 6.0.0(vue@3.5.11(typescript@5.4.5))
     devDependencies:
       '@commitlint/config-conventional':
         specifier: ^19.2.2
@@ -5276,6 +5279,15 @@ packages:
     peerDependencies:
       typescript: '>=5.0.0'
 
+  vue-types@6.0.0:
+    resolution: {integrity: sha512-fBgCA4nrBrB8SCU/AN40tFq8HUxLGBvU2ds7a5+SEDse6dYc+TJyvy8mWiwwL8oWIC/aGS/8nTqmhwxApgU5eA==}
+    engines: {node: '>=14.0.0'}
+    peerDependencies:
+      vue: ^3.0.0
+    peerDependenciesMeta:
+      vue:
+        optional: true
+
   vue@3.5.11:
     resolution: {integrity: sha512-/8Wurrd9J3lb72FTQS7gRMNQD4nztTtKPmuDuPuhqXmmpD6+skVjAeahNpVzsuky6Sy9gy7wn8UadqPtt9SQIg==}
     peerDependencies:
@@ -11673,6 +11685,10 @@ snapshots:
       semver: 7.6.3
       typescript: 5.4.5
 
+  vue-types@6.0.0(vue@3.5.11(typescript@5.4.5)):
+    optionalDependencies:
+      vue: 3.5.11(typescript@5.4.5)
+
   vue@3.5.11(typescript@5.4.5):
     dependencies:
       '@vue/compiler-dom': 3.5.11

+ 10 - 0
src/api/disasterRiskMonitor/geologicalDisaster.ts

@@ -0,0 +1,10 @@
+import request from "@/utils/request";
+
+// 地质灾害列表
+export const getRainfallDzzhList = (params) => {
+    return request({
+        url: "/api/rainfall/dzzh/list",
+        method: "get",
+        params: params
+    });
+};

+ 91 - 0
src/components/Pagination/index.vue

@@ -0,0 +1,91 @@
+<template>
+  <div :class="{ hidden: hidden }" class="pagination-container">
+    <el-pagination
+      v-model:current-page="currentPage"
+      v-model:page-size="pageSize"
+      :background="background"
+      :layout="layout"
+      :page-sizes="pageSizes"
+      :pager-count="pagerCount"
+      :total="total"
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+    />
+  </div>
+</template>
+
+<script lang="ts">
+import { ElPagination } from "element-plus";
+export default {
+  name: 'Pagination'
+};
+</script>
+
+<script setup lang="ts">
+import { scrollTo } from '@/utils/scroll-to';
+import { propTypes } from '@/utils/propTypes';
+
+const props = defineProps({
+  total: propTypes.number,
+  page: propTypes.number.def(1),
+  limit: propTypes.number.def(20),
+  pageSizes: {
+    type: Array,
+    default: () => [10, 20, 30, 50]
+  },
+  // 移动端页码按钮的数量端默认值5
+  pagerCount: propTypes.number.def(document.body.clientWidth < 992 ? 5 : 7),
+  layout: propTypes.string.def('total, sizes, prev, pager, next, jumper'),
+  background: propTypes.bool.def(true),
+  autoScroll: propTypes.bool.def(true),
+  hidden: propTypes.bool.def(false),
+  // float: propTypes.string.def('right')
+});
+
+const emit = defineEmits(['update:page', 'update:limit', 'pagination']);
+const currentPage = computed({
+  get() {
+    return props.page;
+  },
+  set(val) {
+    emit('update:page', val);
+  }
+});
+const pageSize = computed({
+  get() {
+    return props.limit;
+  },
+  set(val) {
+    emit('update:limit', val);
+  }
+});
+function handleSizeChange(val: number) {
+  if (currentPage.value * val > props.total) {
+    currentPage.value = 1;
+  }
+  emit('pagination', { page: currentPage.value, limit: val });
+  if (props.autoScroll) {
+    scrollTo(0, 800);
+  }
+}
+function handleCurrentChange(val: number) {
+  emit('pagination', { page: val, limit: pageSize.value });
+  if (props.autoScroll) {
+    scrollTo(0, 800);
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.pagination-container {
+  padding: 15px 8px;
+  display: flex;
+  justify-content: flex-end;
+  //.el-pagination {
+  //  float: v-bind(float);
+  //}
+}
+.pagination-container.hidden {
+  display: none;
+}
+</style>

+ 26 - 0
src/utils/propTypes.ts

@@ -0,0 +1,26 @@
+import { CSSProperties } from 'vue';
+import VueTypes, { createTypes, toValidableType, VueTypeValidableDef, VueTypesInterface } from 'vue-types';
+
+type PropTypes = VueTypesInterface & {
+  readonly style: VueTypeValidableDef<CSSProperties>;
+  readonly fieldOption: VueTypeValidableDef<Array<FieldOption>>;
+};
+
+const propTypes = createTypes({
+  func: undefined,
+  bool: undefined,
+  string: undefined,
+  number: undefined,
+  object: undefined,
+  integer: undefined
+}) as PropTypes;
+
+export default class ProjectTypes extends VueTypes {
+  static get style() {
+    return toValidableType('style', {
+      type: [String, Object],
+      default: undefined
+    });
+  }
+}
+export { propTypes };

+ 65 - 0
src/utils/scroll-to.ts

@@ -0,0 +1,65 @@
+const easeInOutQuad = (t: number, b: number, c: number, d: number) => {
+  t /= d / 2;
+  if (t < 1) {
+    return (c / 2) * t * t + b;
+  }
+  t--;
+  return (-c / 2) * (t * (t - 2) - 1) + b;
+};
+
+// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
+const requestAnimFrame = (function () {
+  return (
+    window.requestAnimationFrame ||
+    (window as any).webkitRequestAnimationFrame ||
+    (window as any).mozRequestAnimationFrame ||
+    function (callback) {
+      window.setTimeout(callback, 1000 / 60);
+    }
+  );
+})();
+
+/**
+ * Because it's so fucking difficult to detect the scrolling element, just move them all
+ * @param {number} amount
+ */
+const move = (amount: number) => {
+  document.documentElement.scrollTop = amount;
+  (document.body.parentNode as HTMLElement).scrollTop = amount;
+  document.body.scrollTop = amount;
+};
+
+const position = () => {
+  return document.documentElement.scrollTop || (document.body.parentNode as HTMLElement).scrollTop || document.body.scrollTop;
+};
+
+/**
+ * @param {number} to
+ * @param {number} duration
+ * @param {Function} callback
+ */
+export const scrollTo = (to: number, duration: number, callback?: any) => {
+  const start = position();
+  const change = to - start;
+  const increment = 20;
+  let currentTime = 0;
+  duration = typeof duration === 'undefined' ? 500 : duration;
+  const animateScroll = function () {
+    // increment the time
+    currentTime += increment;
+    // find the value with the quadratic in-out easing function
+    const val = easeInOutQuad(currentTime, start, change, duration);
+    // move the document.body
+    move(val);
+    // do the animation unless its over
+    if (currentTime < duration) {
+      requestAnimFrame(animateScroll);
+    } else {
+      if (callback && typeof callback === 'function') {
+        // the animation is done so lets callback
+        callback();
+      }
+    }
+  };
+  animateScroll();
+};

+ 63 - 150
src/views/disasterRiskMonitor/geologicalDisaster.vue

@@ -9,7 +9,7 @@
         <div class="card1">
           <div class="text1">隐患点总数</div>
           <div class="text-box">
-            <div class="text2">34,221</div>
+            <div class="text2">{{ total }}</div>
           </div>
         </div>
@@ -21,7 +21,7 @@
           </div>
         </div>
       </div>
-      <div class="card-header" style="justify-content: space-between">
+      <div class="card-header mg10" style="justify-content: space-between">
         <div class="flex">
           <i class="icon-line" />
           <div class="text">威胁人员规模</div>
@@ -143,22 +143,32 @@
               </div>
             </template>
           </el-table-column>
-          <el-table-column label="镇街" prop="area" align="center">
-            <template #header>
-              <div class="table-line" @click="showPicker2 = true">
-                <div>{{ labelData.country ? labelData.country : "镇街" }}</div>
-                <i class="icon-down" />
-              </div>
-            </template>
-          </el-table-column>
+<!--          <el-table-column label="镇街" prop="area" align="center">-->
+<!--            <template #header>-->
+<!--              <div class="table-line" @click="showPicker2 = true">-->
+<!--                <div>{{ labelData.country ? labelData.country : "镇街" }}</div>-->
+<!--                <i class="icon-down" />-->
+<!--              </div>-->
+<!--            </template>-->
+<!--          </el-table-column>-->
           <el-table-column
             label="隐患点名称"
             prop="address"
             align="center"
             width="160px"
           />
-          <el-table-column label="隐患类型" prop="speed" align="center" />
+          <el-table-column label="隐患类型" prop="type" align="center" />
         </el-table>
+        <pagination
+            v-show="total > 0"
+            v-model:page="queryParams.page"
+            v-model:limit="queryParams.pageSize"
+            :total="total"
+            :pager-count="3"
+            size="small"
+            layout="prev, pager, next"
+            @pagination="getList"
+        />
         <van-popup v-model:show="showPicker" round position="bottom">
           <van-picker
             :columns="columns"
@@ -166,13 +176,13 @@
             @confirm="onSelectLevelConfirm"
           />
         </van-popup>
-        <van-popup v-model:show="showPicker2" round position="bottom">
-          <van-picker
-            :columns="columns2"
-            @cancel="showPicker2 = false"
-            @confirm="onSelectLevelConfirm2"
-          />
-        </van-popup>
+<!--        <van-popup v-model:show="showPicker2" round position="bottom">-->
+<!--          <van-picker-->
+<!--            :columns="columns2"-->
+<!--            @cancel="showPicker2 = false"-->
+<!--            @confirm="onSelectLevelConfirm2"-->
+<!--          />-->
+<!--        </van-popup>-->
       </div>
     </div>
   </div>
@@ -181,8 +191,9 @@
 <script lang="ts" setup name="geologicalDisaster">
 import Map from '@/components/Map/index2.vue';
 import searchImg from "@/assets/images/search.png";
-import { onMounted, reactive, ref } from "vue";
 import { ElTable, ElTableColumn } from "element-plus";
+import {getRainfallDzzhList} from "@/api/disasterRiskMonitor/geologicalDisaster";
+import {getDicts} from "@/api/system/dict/data";
 const getImageUrl = name => {
   return new URL(
     `../../assets/images/disasterRiskMonitor/geologicalDisaster/${name}`,
@@ -191,9 +202,11 @@ const getImageUrl = name => {
 };
 const queryParams = reactive({
   keyword: "",
-  page: 0,
+  area_name: "",
+  page: 1,
   pageSize: 10
 });
+let total = ref(0);
 let mapRef = ref();
 let menu1 = ref([
   { name: "特大型", icon: getImageUrl("icon1.png"), num: 0, checked: true },
@@ -211,44 +224,34 @@ let menu2 = ref([
   { name: "崩塌", icon: getImageUrl("icon11.png"), num: 3, checked: true },
   { name: "滑坡", icon: getImageUrl("icon12.png"), num: 3, checked: true }
 ]);
-let pointData = ref([]);
 let eventDetails = ref({});
 const labelData = reactive({
   area: "",
   country: ""
 });
-const columns = ref([
-  { text: "全部", value: "" },
-  { text: "滨海新区", value: "0" },
-  { text: "信宜", value: "1" },
-  { text: "电白", value: "2" },
-  { text: "高州", value: "3" }
-]);
-const columns2 = ref([
-  { text: "全部", value: "" },
-  { text: "滨海新区2", value: "0" },
-  { text: "信宜2", value: "1" },
-  { text: "电白2", value: "2" },
-  { text: "高州2", value: "3" }
-]);
+const columns = ref([]);
+// const columns2 = ref([
+//   { text: "全部", value: "" },
+// ]);
 let showPicker = ref(false);
 let showPicker2 = ref(false);
-const queryParams2 = reactive({
-  area: "",
-  country: ""
-});
 let detailsData = ref({
   dataList: []
 });
 const handleClick = item => {
   item.checked = !item.checked;
 };
-const getList = () => {};
+const getList = () => {
+  getRainfallDzzhList(queryParams).then((res) => {
+    detailsData.value.dataList = res.data;
+    total.value = res.total;
+  })
+};
 // 搜索关键字变化时触发的方法
 function onSearchKeyword(keyword) {
   // 根据搜索关键字更新查询参数
   queryParams.keyword = keyword;
-  queryParams.page = 0;
+  queryParams.page = 1;
   // 刷新列表数据
   getList();
 }
@@ -263,17 +266,15 @@ const onSearchCancel = () => {
 };
 const onSelectLevelConfirm = ({ selectedOptions }) => {
   showPicker.value = false;
-  labelData.area =
-    selectedOptions[0].text === "全部" ? "县区" : selectedOptions[0].text;
-  queryParams2.area = selectedOptions[0].value;
-  initData();
+  labelData.area = selectedOptions[0].text === "全部" ? "县区" : selectedOptions[0].text;
+  queryParams.page = 1;
+  queryParams.area_name = selectedOptions[0].value;
+  getList()
 };
 const onSelectLevelConfirm2 = ({ selectedOptions }) => {
   showPicker2.value = false;
   labelData.country =
     selectedOptions[0].text === "全部" ? "镇街" : selectedOptions[0].text;
-  queryParams2.country = selectedOptions[0].value;
-  initData();
 };
 let iconList = reactive({
   "1": {
@@ -457,113 +458,20 @@ const initData = () => {
   });
   dom.addMarker(data);
 };
-const getTableData = () => {
-  detailsData.value.dataList = [
-    {
-      area: "电白",
-      type: "滨海新区",
-      address: "海滨街道办",
-      speed: "滑坡"
-    },
-    {
-      area: "电白",
-      type: "林头镇",
-      address: "林头村",
-      speed: "崩塌"
-    },
-    {
-      area: "电白",
-      type: "观珠镇",
-      address: "观珠市场",
-      speed: "地面沉降"
-    },
-    {
-      area: "高州",
-      type: "石鼓镇",
-      address: "石鼓村",
-      speed: "不稳定斜坡"
-    },
-    {
-      area: "高州",
-      type: "沙田镇",
-      address: "沙田中学",
-      speed: "地裂缝"
-    },
-    {
-      area: "化州",
-      type: "鉴江街道",
-      address: "鉴江社区",
-      speed: "地面塌陷"
-    },
-    {
-      area: "化州",
-      type: "平定镇",
-      address: "平定村",
-      speed: "泥石流"
-    },
-    {
-      area: "茂南",
-      type: "袂花镇",
-      address: "袂花新村",
-      speed: "滑坡"
-    },
-    {
-      area: "茂南",
-      type: "公馆镇",
-      address: "公馆市场",
-      speed: "崩塌"
-    },
-    {
-      area: "信宜",
-      type: "镇隆镇",
-      address: "镇隆村",
-      speed: "地面沉降"
-    },
-    {
-      area: "信宜",
-      type: "池洞镇",
-      address: "池洞小学",
-      speed: "不稳定斜坡"
-    },
-    {
-      area: "电白",
-      type: "树仔镇",
-      address: "树仔村",
-      speed: "地裂缝"
-    },
-    {
-      area: "高州",
-      type: "荷塘镇",
-      address: "荷塘市场",
-      speed: "地面塌陷"
-    },
-    {
-      area: "化州",
-      type: "官桥镇",
-      address: "官桥村",
-      speed: "泥石流"
-    },
-    {
-      area: "茂南",
-      type: "金塘镇",
-      address: "金塘社区",
-      speed: "滑坡"
-    },
-    {
-      area: "信宜",
-      type: "丁堡镇",
-      address: "丁堡村",
-      speed: "崩塌"
-    }
-  ];
-};
 // table样式
 const getTableRowClass = ({ rowIndex }) => {
   return rowIndex % 2 === 0 ? "" : "common-table-tr";
 };
 onMounted(() => {
-  getTableData();
-});
+  getList();
+  getDicts("district_type").then(res => {
+    const data = [{ text: "全部", value: "" }]
+    res.data.forEach(item => {
+      data.push({ text: item.dictLabel, value: item.dictLabel });
+    });
+    columns.value = data;
+  });
+})
 </script>
 
 <style scoped lang="scss">
@@ -780,7 +688,7 @@ onMounted(() => {
           align-items: center;
           font-size: 12px;
           color: #7f8b9f;
-          margin-right: 14px;
+          margin-right: 12px;
           &:nth-child(1n) {
             width: 48px;
           }
@@ -830,6 +738,7 @@ onMounted(() => {
   }
   .table-line {
     display: flex;
+    justify-content: center;
     align-items: center;
     font-size: 14px;
     .icon-down {
@@ -854,6 +763,7 @@ onMounted(() => {
   }
   :deep(.van-search__content) {
     background-color: #ffffff;
+    border: none !important;
   }
   :deep(.van-field__left-icon) {
     .van-icon__image {
@@ -875,4 +785,7 @@ onMounted(() => {
     color: #2c81ff;
   }
 }
+.mg10 {
+  margin-top: 10px;
+}
 </style>

+ 23 - 34
src/views/disasterRiskMonitor/rainfall.vue

@@ -8,7 +8,7 @@
             v-for="(item, index) in option1"
             :key="index"
             :class="
-            queryParams.value1 === '1' && queryParams.value2 === item.value
+            queryParams.query.value1 === '1' && queryParams.query.timeOption === item.value
               ? 'box-tag tag-active'
               : 'box-tag'
           "
@@ -23,7 +23,7 @@
             v-for="(item, index) in option1"
             :key="index"
             :class="
-            queryParams.value1 === '2' && queryParams.value2 === item.value
+            queryParams.value1 === '2' && queryParams.timeOption === item.value
               ? 'box-tag tag-active'
               : 'box-tag'
           "
@@ -53,11 +53,10 @@
           :row-class-name="getTableRowClass"
           table-layout="auto"
       >
-<!--        <el-table-column label="地区" prop="area" align="center" />-->
-        <el-table-column prop="level" align="center">
+        <el-table-column prop="area" align="center">
           <template #header>
             <div class="table-line" @click="showLevelPicker = true">
-              <div>{{ labelData.level ? labelData.level : "县区" }}</div>
+              <div>{{ labelData.area ? labelData.area : "县区" }}</div>
               <i class="icon-down" />
             </div>
           </template>
@@ -70,7 +69,7 @@
         />
         <el-table-column
             label="雨量(mm)"
-            prop="speed"
+            prop="rainfall"
             align="center"
             sortable
         />
@@ -89,6 +88,7 @@
 <script lang="ts" setup>
 import { ElTable, ElTableColumn } from "element-plus";
 import icon1 from '@/assets/images/disasterRiskMonitor/rainfall/icon1.png'
+import {getRainfallRange2} from "@/api/globalMap/rainMonitor";
 
 const option1 = reactive([
   { text: "1h", value: "1" },
@@ -99,15 +99,17 @@ const option1 = reactive([
 ]);
 const labelData = reactive({
   type: "",
-  level: "",
   area: ""
 });
 const queryParams = reactive({
-  value1: "1",
-  value2: "24",
-  type: "",
-  level: "",
-  area: ""
+  current: 1,
+  size: 10,
+  query: {
+    township: "",
+    timeOption: "24",
+    area: "",
+    sort: "desc"
+  }
 });
 const detailsData = ref({
   img: "",
@@ -115,24 +117,11 @@ const detailsData = ref({
   dataList: []
 });
 const initData = () => {
-  detailsData.value = {
-    img: icon1,
-    text: "据气象水文监测,24日至25日16时,茂名无降水。",
-    dataList: [
-      {
-        area: "茂名",
-        level: "化州",
-        address: "林尘镇政府",
-        speed: "0.0"
-      },
-      {
-        area: "茂名",
-        level: "化州",
-        address: "那务镇宝树水库",
-        speed: "0.0"
-      }
-    ]
-  };
+  getRainfallRange2(queryParams).then((res) => {
+    detailsData.value.dataList = res.rows;
+  });
+  detailsData.value.img = icon1;
+  detailsData.value.text = "据气象水文监测,24日至25日16时,茂名无降水。";
 };
 
 const levelColumns = ref([
@@ -145,14 +134,14 @@ const levelColumns = ref([
 let showLevelPicker = ref(false);
 const onSelectLevelConfirm = ({ selectedOptions }) => {
   showLevelPicker.value = false;
-  labelData.level =
+  labelData.area =
       selectedOptions[0].text === "全部" ? "县区" : selectedOptions[0].text;
-  queryParams.level = selectedOptions[0].value;
+  queryParams.area = selectedOptions[0].value;
   initData();
 };
-const handleClickMenu = (value1, value2) => {
+const handleClickMenu = (value1, timeOption) => {
   queryParams.value1 = value1;
-  queryParams.value2 = value2;
+  queryParams.timeOption = timeOption;
   initData();
 };
 // table样式