Kaynağa Gözat

减灾能力+自然灾害承载体界面优化

zhangyihao 7 ay önce
ebeveyn
işleme
6f50be8b2f

+ 307 - 0
src/views/censusDataAnalysis/DisasterReduction/BaseService.vue

@@ -0,0 +1,307 @@
+<template>
+  <div class="box-content">
+    <div class="tag-box">
+      <div
+        v-for="(item, index) in baseService.menu"
+        :key="index"
+        :class="activeIndex === index ? 'tag-item tag-active2' : 'tag-item'"
+        @click="handleClick3(item, index)"
+      >
+        {{ item.name }}
+      </div>
+    </div>
+    <template v-if="activeIndex === 0">
+      <div v-for="(item, index) in baseService.dataList" :key="index" class="checked-box">
+        <div class="checked-header">
+          <div class="title-box2">
+            <div class="text1">{{ item.name }}</div>
+            <el-checkbox v-model="item.checked" label="全选" @change="() => handleCheckedAllChange(item)" />
+          </div>
+          <div class="expand-box" @click="item.show = !item.show">
+            <div>{{ item.show ? '收起' : '展开' }}</div>
+            <el-icon class="icon">
+              <ArrowUpBold v-show="item.show" />
+              <ArrowDownBold v-show="!item.show" />
+            </el-icon>
+          </div>
+        </div>
+        <div v-if="!!item.children && !!item.show" class="checked-box2">
+          <div
+            v-for="(item2, index2) in item.children"
+            :key="index2"
+            :class="!!item2.checked ? 'checked-item checked-item-active' : 'checked-item'"
+            :title="item2.name"
+            @click="handleClickChecked(item2)"
+          >
+            <div
+              class="icon"
+              :style="{ backgroundImage: `url(${iconList[item2.value] && iconList[item2.value].image ? iconList[item2.value].image : ''})` }"
+            />
+            <div class="text">{{ item2.name }}</div>
+          </div>
+        </div>
+      </div>
+    </template>
+    <template v-else-if="activeIndex === 1"></template>
+    <template v-else-if="activeIndex === 2"></template>
+  </div>
+</template>
+
+<script lang="ts" setup name="BaseService">
+import { iconList } from '@/views/censusDataAnalysis/DisasterReduction/data';
+import { ArrowDownBold } from '@element-plus/icons-vue';
+
+const emits = defineEmits(['change']);
+// 基础服务
+const activeIndex = ref(0);
+const baseService = reactive({
+  menu: [],
+  dataList: []
+});
+const getBaseServiceDataList = () => {
+  // 模拟数据
+  const data = [
+    {
+      name: '公共服务承灾体',
+      children: [
+        { name: '学校', value: '1' },
+        { name: '旅游景区', value: '2' },
+        { name: '星级饭店', value: '3' },
+        { name: '体育场馆', value: '4' },
+        { name: '卫生医疗机构', value: '5' },
+        { name: '公共文化场所', value: '6' },
+        { name: '宗教活动场所', value: '7' },
+        { name: '提供住宿的社会服务机构', value: '8' },
+        { name: '大型超市、百货店和亿元以上商品交易市场', value: '9' }
+      ]
+    },
+    {
+      name: '危化品承载体',
+      children: [
+        { name: '化工园区', value: '10' },
+        { name: '危化品企业', value: '11' },
+        { name: '加油加气站', value: '12' }
+      ]
+    }
+  ];
+  data.forEach((item) => {
+    item.checked = false;
+    item.show = true;
+    if (item.children && item.children.length > 0) {
+      item.children.forEach((item) => {
+        item.checked = false;
+      });
+    }
+  });
+  baseService.dataList = data;
+};
+
+// 点击基础服务菜单
+const handleClick3 = (item, index) => {
+  if (activeIndex.value === index) return;
+  activeIndex.value = index;
+  getBaseServiceDataList();
+  console.log('点击', item);
+};
+
+// 点击全选
+const handleCheckedAllChange = (item) => {
+  let checked = item.checked;
+  item.children.forEach((child) => {
+    child.checked = checked;
+  });
+  // getCheckedData();
+};
+// 单选
+const handleClickChecked = (item) => {
+  item.checked = !item.checked;
+};
+
+//获取选中的二级点的打点数据
+const getCheckedData = () => {
+  const data = [
+    {
+      'name': '多数据点位',
+      'id': '43',
+      'dataType': 1,
+      'longitude': '110.420681',
+      'latitude': '22.023646',
+      'type': '1'
+    },
+    {
+      'name': '多数据点位',
+      'id': '50',
+      'dataType': 1,
+      'longitude': '110.74013',
+      'latitude': '22.024823',
+      'type': '1'
+    },
+    {
+      'name': '多数据点位',
+      'id': '47',
+      'dataType': 1,
+      'longitude': '110.824124',
+      'latitude': '21.62655',
+      'type': '1'
+    },
+    {
+      'name': '陈洋',
+      'id': '48',
+      'dataType': 1,
+      'longitude': '110.862318',
+      'latitude': '21.828685',
+      'type': '2'
+    },
+    {
+      'name': '钟国艺',
+      'id': '49',
+      'dataType': 1,
+      'longitude': '110.925456',
+      'latitude': '21.662999',
+      'type': '2'
+    }
+  ];
+  data.forEach((item) => {
+    item.icon = iconList[item.dataType].image;
+    item.image = iconList[item.dataType].image;
+    item.imageHover = iconList[item.dataType].imageHover;
+    item.size = iconList[item.dataType].size;
+    item.lnglat = [item.longitude, item.latitude];
+  });
+  emits('change', data);
+};
+const initData = () => {
+  baseService.menu = [
+    { name: '承灾体', value: '1' },
+    { name: '致灾因子', value: '2' },
+    { name: '减灾能力', value: '3' }
+  ];
+  getBaseServiceDataList();
+};
+onMounted(() => {
+  initData();
+});
+</script>
+
+<style lang="scss" scoped>
+.box-content {
+  width: 100%;
+  height: 415px;
+  background: url('@/assets/images/censusDataAnalysis/box.png') no-repeat;
+  background-size: 100% 100%;
+  overflow-y: auto;
+  .tag-box {
+    display: flex;
+    flex-wrap: wrap;
+    align-items: center;
+    cursor: pointer;
+    padding: 0 10px;
+    .tag-item {
+      width: 121px;
+      height: 29px;
+      text-align: center;
+      background: url('@/assets/images/censusDataAnalysis/tab.png') no-repeat;
+      background-size: 100% 100%;
+      font-size: 14px;
+      color: #ffffff;
+      &:hover {
+        background: url('@/assets/images/censusDataAnalysis/tabActive.png') no-repeat;
+        background-size: 100% 37px;
+      }
+    }
+    .tag-active2 {
+      background: url('@/assets/images/censusDataAnalysis/tabActive.png') no-repeat;
+      background-size: 100% 37px;
+    }
+  }
+  .checked-box {
+    padding-right: 27px;
+    box-sizing: border-box;
+    .checked-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 5px 0 0;
+      .title-box2 {
+        display: flex;
+        align-items: center;
+        height: 25px;
+        background: url('@/assets/images/censusDataAnalysis/titleBox2.png') no-repeat bottom left;
+        background-size: 136px 20px;
+        padding-left: 23px;
+        font-size: 16px;
+        color: #ffffff;
+        .text1 {
+          margin-right: 20px;
+        }
+        :deep(.el-checkbox) {
+          .el-checkbox__input.is-checked .el-checkbox__inner {
+            background-color: #0167f5 !important;
+            border-color: #0167f5 !important;
+          }
+        }
+        :deep(.el-checkbox__label) {
+          color: #ffffff;
+        }
+      }
+      .expand-box {
+        display: flex;
+        align-items: center;
+        cursor: pointer;
+        color: #ffffff;
+        .icon {
+          margin-left: 3px;
+        }
+      }
+    }
+    .checked-box2 {
+      display: flex;
+      flex-wrap: wrap;
+      justify-content: space-between;
+      align-items: center;
+      cursor: pointer;
+      .checked-item {
+        text-align: center;
+        padding: 8px 15px 8px 10px;
+        width: 218px;
+        height: 41px;
+        background: url('@/assets/images/censusDataAnalysis/tag.png') no-repeat;
+        background-size: 100% 100%;
+        margin-top: 6px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        &:nth-child(1),
+        &:nth-child(2) {
+          margin-top: 0;
+        }
+        &:hover {
+          background: url('@/assets/images/censusDataAnalysis/tagActive.png') no-repeat;
+          background-size: 100% 100%;
+        }
+        .icon {
+          width: 42px;
+          height: 44px;
+          background-repeat: no-repeat;
+          background-size: 100% 100%;
+          margin-right: 15px;
+          flex-shrink: 0;
+        }
+        .text {
+          color: #ffffff;
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          font-size: 14px;
+          width: 107px;
+          text-align: left;
+        }
+      }
+      .checked-item-active {
+        background: url('@/assets/images/censusDataAnalysis/tagActive.png') no-repeat;
+        background-size: 100% 100%;
+      }
+    }
+  }
+}
+</style>

+ 480 - 0
src/views/censusDataAnalysis/DisasterReduction/RightSection.vue

@@ -0,0 +1,480 @@
+<template>
+  <div class="right-section">
+    <div class="data-box1" style="margin-top: 9px">
+      <div class="title-box">
+        <div class="gradient-text">区县级减灾能力评估排行</div>
+      </div>
+      <div class="box-content">
+        <div class="btn" @click="showExportReport = true">综合分析报告</div>
+      </div>
+    </div>
+    <div class="data-box1" style="margin-top: 9px">
+      <div class="title-box">
+        <div class="gradient-text">区县减灾能力统计表</div>
+      </div>
+      <div class="box-content" style="padding: 5px 0 5px 5px; height: 255px">
+        <div class="box4">
+          <div class="common-table">
+            <div class="table-header">
+              <div class="td" style="width: 90px">区县名称</div>
+              <div class="td" style="width: 90px">政府减灾能力</div>
+              <div class="td" style="width: 90px">社会组织减灾能力</div>
+              <div class="td" style="width: 90px">乡镇减灾能力</div>
+              <div class="td" style="width: 90px">社区减灾能力</div>
+              <div class="td" style="width: 90px">家庭减灾能力</div>
+            </div>
+            <div v-for="(item, index) in tableData" :key="index" class="tr">
+              <div class="td">{{ item.area }}</div>
+              <div class="td">{{ item.data1 }}</div>
+              <div class="td">{{ item.data2 }}</div>
+              <div class="td">{{ item.data3 }}</div>
+              <div class="td">{{ item.data4 }}</div>
+              <div class="td">{{ item.data5 }}</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <Dialog v-model="showExportReport" type="xs" title="导出综合分析报告" hide-footer>
+      <div class="flex-box">
+        <div class="icon-chart"></div>
+        <div>暂无数据导出</div>
+      </div>
+    </Dialog>
+  </div>
+</template>
+
+<script lang="ts" setup name="RightSection">
+import { setHighText } from '@/utils';
+const props = defineProps({
+  time: String
+});
+let showExportReport = ref(false);
+let riskOverviewData = ref({
+  time1: '',
+  time2: '',
+  text: ''
+});
+let colorText = ref([
+  { text: '低风险', color: '#40c75f' },
+  { text: '中低风险', color: '#3180f6' },
+  { text: '中风险', color: '#efec93' },
+  { text: '中高风险', color: '#f07d00' },
+  { text: '极高风险', color: '#aa0d1c' }
+]);
+// 风险分布
+let riskDistributionState = reactive({
+  showLevel: '1',
+  countyLevel: [
+    { name: '极高风险区县', value: '0', icon: 'icon5', text: 'red-text' },
+    { name: '中高风险区县', value: '0', icon: 'icon4', text: 'orange-text' },
+    { name: '中风险区县', value: '0', icon: 'icon3', text: 'yellow-text' },
+    { name: '中低风险区县', value: '0', icon: 'icon2', text: 'blue-text' },
+    { name: '低风险区县', value: '0', icon: 'icon1', text: 'green-text' }
+  ],
+  townShipLevel: [
+    { name: '极高风险镇街', value: '0', icon: 'icon5', text: 'red-text' },
+    { name: '中高风险镇街', value: '0', icon: 'icon4', text: 'orange-text' },
+    { name: '中风险镇街', value: '0', icon: 'icon3', text: 'yellow-text' },
+    { name: '中低风险镇街', value: '0', icon: 'icon2', text: 'blue-text' },
+    { name: '低风险镇街', value: '0', icon: 'icon1', text: 'green-text' }
+  ]
+});
+//
+const tableData = ref([]);
+const getData = () => {
+  const data = {
+    time1: '2024-10-31 09:00:00',
+    time2: '2024-10-31 09:00:00',
+    text: '经系统研判,当前茂名市海洋风险为低风险当前全市林火中高风险区县共有1个,为信宜市。林火中风险区县共有1个,为化州市,林火中低危险区县共有1个,为高州市,电白区、茂南区为低风险。'
+  };
+  data.text = setHighText(data.text, colorText.value);
+  riskOverviewData.value = data;
+
+  const data2 = {
+    data1: '0',
+    data2: '0',
+    data3: '21',
+    data4: '258',
+    data5: '34'
+  };
+  const data3 = {
+    data1: '0',
+    data2: '0',
+    data3: '6',
+    data4: '156',
+    data5: '6'
+  };
+  riskDistributionState.countyLevel[0].value = data2.data1;
+  riskDistributionState.countyLevel[1].value = data2.data2;
+  riskDistributionState.countyLevel[2].value = data2.data3;
+  riskDistributionState.countyLevel[3].value = data2.data4;
+  riskDistributionState.countyLevel[4].value = data2.data5;
+  riskDistributionState.townShipLevel[0].value = data3.data1;
+  riskDistributionState.townShipLevel[1].value = data3.data2;
+  riskDistributionState.townShipLevel[2].value = data3.data3;
+  riskDistributionState.townShipLevel[3].value = data3.data4;
+  riskDistributionState.townShipLevel[4].value = data3.data5;
+
+  tableData.value = [
+    { area: '茂南区', data1: '强', data2: '强', data3: '强', data4: '强', data5: '强' },
+    { area: '电白区', data1: '中等', data2: '中等', data3: '中等', data4: '中等', data5: '中等' },
+    { area: '高州区', data1: '强', data2: '强', data3: '强', data4: '强', data5: '强' },
+    { area: '化州区', data1: '较强', data2: '较强', data3: '较强', data4: '较强', data5: '较强' },
+    { area: '信宜区', data1: '中等', data2: '中等', data3: '中等', data4: '中等', data5: '中等' }
+  ];
+};
+const parseTime2 = (dateStr) => {
+  if (!dateStr) return '';
+  let time = dateStr.replace(/年/g, '-').replace(/月/g, '-').replace(/日/g, '');
+  // 将字符串转换为 Date 对象
+  const date = new Date(time);
+
+  // 设置时间为 00:00:00
+  date.setHours(0, 0, 0, 0);
+
+  // 格式化输出为所需的字符串格式
+  const year = date.getFullYear();
+  const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,所以需要+1
+  const day = String(date.getDate()).padStart(2, '0');
+  const formattedDate = `${year}年${month}月${day}日 00:00:00`;
+
+  return formattedDate;
+};
+onMounted(() => {
+  getData();
+});
+</script>
+
+<style lang="scss" scoped>
+.right-section {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  color: #ffffff;
+  padding-right: 20px;
+  .data-box1 {
+    &::after {
+      content: '';
+      display: block;
+      width: 517px;
+      height: 19px;
+      background: url('@/assets/images/censusDataAnalysis/line.png') no-repeat;
+      background-size: 100% 100%;
+      margin-top: -8px;
+    }
+    .title-box {
+      width: 516px;
+      height: 40px;
+      background: url('@/assets/images/censusDataAnalysis/titleBox.png') no-repeat;
+      background-size: 100% 100%;
+      padding-left: 50px;
+      .gradient-text {
+        font-size: 24px;
+      }
+    }
+    .box-content {
+      min-height: 123px;
+      background: url('@/assets/images/censusDataAnalysis/box.png') no-repeat;
+      background-size: 100% 100%;
+      padding: 5px 28px;
+      .btn {
+        width: 106px;
+        height: 40px;
+        background: url('@/assets/images/censusDataAnalysis/btn.png') no-repeat;
+        background-size: 100% 100%;
+        font-size: 12px;
+        color: #edfaff;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        padding-left: 15px;
+        cursor: pointer;
+      }
+      .box1 {
+        display: flex;
+        align-items: center;
+        width: 235px;
+        height: 20px;
+        background: url('@/assets/images/censusDataAnalysis/forestFire/box1.png') no-repeat bottom left;
+        background-size: 100% 13px;
+        .icon-address {
+          width: 11px;
+          height: 10px;
+          background: url('@/assets/images/censusDataAnalysis/forestFire/address.png') no-repeat;
+          background-size: 100% 100%;
+          margin-right: 5px;
+        }
+        .text1 {
+          font-size: 12px;
+          color: #edfaff;
+          display: flex;
+          align-items: center;
+        }
+      }
+      .box2 {
+        display: flex;
+        flex-wrap: wrap;
+        margin-top: 8px;
+        .box-item {
+          display: flex;
+          margin-left: 42px;
+          &:nth-child(1),
+          &:nth-child(4) {
+            margin-left: 0;
+          }
+          .icon1 {
+            background: url('@/assets/images/censusDataAnalysis/forestFire/iconRisk1.png') no-repeat;
+          }
+          .icon2 {
+            background: url('@/assets/images/censusDataAnalysis/forestFire/iconRisk2.png') no-repeat;
+          }
+          .icon3 {
+            background: url('@/assets/images/censusDataAnalysis/forestFire/iconRisk3.png') no-repeat;
+          }
+          .icon4 {
+            background: url('@/assets/images/censusDataAnalysis/forestFire/iconRisk4.png') no-repeat;
+          }
+          .icon5 {
+            background: url('@/assets/images/censusDataAnalysis/forestFire/iconRisk5.png') no-repeat;
+          }
+          .icon1,
+          .icon2,
+          .icon3,
+          .icon4,
+          .icon5 {
+            width: 48px;
+            height: 49px;
+            background-size: 100% 100%;
+          }
+          .text-box {
+            margin-left: 8px;
+            .text-box2 {
+              display: flex;
+              align-items: baseline;
+              margin-bottom: 6px;
+              .red-text,
+              .orange-text,
+              .yellow-text,
+              .blue-text,
+              .green-text {
+                min-width: 25px;
+                font-size: 16px;
+                color: transparent;
+                -webkit-background-clip: text;
+                background-clip: text;
+                display: inline-block;
+                font-family: BEBAS-1;
+              }
+              .red-text {
+                background-image: linear-gradient(to bottom, #ffffff 30%, #ffc4be 50%, #ff2f3c 100%);
+              }
+              .orange-text {
+                background-image: linear-gradient(to bottom, #ffffff 30%, #ffddc7 50%, #f88726 100%);
+              }
+              .yellow-text {
+                background-image: linear-gradient(to bottom, #ffffff 30%, #fcfed0 50%, #f7f71e 100%);
+              }
+              .blue-text {
+                background-image: linear-gradient(to bottom, #ffffff 30%, #c1dbff 50%, #2c81ff 100%);
+              }
+              .green-text {
+                background-image: linear-gradient(to bottom, #ffffff 30%, #d1ffdb 50%, #22fb81 100%);
+              }
+            }
+            .text1 {
+              font-size: 12px;
+              color: #a8ccde;
+            }
+            .text2 {
+              font-size: 12px;
+              color: #ffffff;
+            }
+          }
+        }
+      }
+      .box3 {
+        width: 100%;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .item {
+          width: 116px;
+          height: 58px;
+          background: url('@/assets/images/censusDataAnalysis/forestFire/box2.png') no-repeat;
+          background-size: 100% 100%;
+          display: flex;
+          align-items: center;
+          position: relative;
+          padding-left: 40px;
+          box-sizing: border-box;
+          .icon1 {
+            background: url('@/assets/images/censusDataAnalysis/forestFire/town.png') no-repeat;
+          }
+          .icon2 {
+            background: url('@/assets/images/censusDataAnalysis/forestFire/population.png') no-repeat;
+          }
+          .icon3 {
+            background: url('@/assets/images/censusDataAnalysis/forestFire/area.png') no-repeat;
+          }
+          .icon4 {
+            background: url('@/assets/images/censusDataAnalysis/forestFire/gdp.png') no-repeat;
+          }
+          .icon1,
+          .icon2,
+          .icon3,
+          .icon4 {
+            position: absolute;
+            left: -32px;
+            top: -24px;
+            flex-shrink: 0;
+            display: inline-block;
+            width: 106px;
+            height: 106px;
+            margin-right: 10px;
+            background-size: 100% 100%;
+          }
+          .text-box {
+            .text1 {
+              font-size: 14px;
+              color: #ffffff;
+            }
+            .text-box2 {
+              display: flex;
+              align-items: baseline;
+              .text2 {
+                font-size: 16px;
+                min-width: 40px;
+                color: transparent;
+                -webkit-background-clip: text;
+                background-clip: text;
+                display: inline-block;
+                font-family: BEBAS-1;
+                background-image: linear-gradient(to bottom, #ffffff 30%, #c1dbff 50%, #2c81ff 100%);
+              }
+              .text3 {
+                font-size: 12px;
+                color: #a8ccde;
+              }
+            }
+          }
+        }
+      }
+      .box4 {
+        display: flex;
+        flex-wrap: wrap;
+        align-items: center;
+        .item {
+          box-sizing: border-box;
+          padding-top: 5px;
+          padding-left: 70px;
+          width: 163px;
+          height: 57px;
+          background-repeat: no-repeat;
+          background-size: 100% 100%;
+          margin-left: 10px;
+          margin-top: 7px;
+          //&:nth-child(1),
+          //&:nth-child(2),
+          //&:nth-child(3) {
+          //  margin-top: 0;
+          //}
+          &:nth-child(3n + 1) {
+            margin-left: 0;
+          }
+          .text1 {
+            font-size: 14px;
+          }
+          .text2 {
+            font-size: 18px;
+            color: transparent;
+            -webkit-background-clip: text;
+            background-clip: text;
+            display: inline-block;
+            font-family: BEBAS-1;
+            background-image: linear-gradient(to bottom, #ffffff 30%, #c1dbff 50%, #2c81ff 100%);
+            margin-top: 5px;
+          }
+        }
+      }
+    }
+  }
+  .data-box2 {
+    width: 506px;
+    height: 135px;
+    background: url('@/assets/images/censusDataAnalysis/box2.png') no-repeat;
+    background-size: 100% 100%;
+    padding: 8px 10px;
+    .box-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      .header-left {
+        display: flex;
+        align-items: center;
+        .header-title {
+          font-size: 16px;
+          color: transparent;
+          background-image: linear-gradient(to bottom, #fff 40%, #65a3ff 70%, #3385ff 100%);
+          -webkit-background-clip: text;
+          background-clip: text;
+          display: inline-block;
+        }
+        .time {
+          color: #edfaff;
+          font-size: 12px;
+          margin-left: 15px;
+        }
+      }
+    }
+    .box-content {
+      display: flex;
+      align-items: center;
+      .icon {
+        display: inline-block;
+        flex-shrink: 0;
+        width: 64px;
+        height: 65px;
+        background: url('@/assets/images/censusDataAnalysis/riskOverview.png') no-repeat;
+        background-size: 100% 100%;
+      }
+      .line {
+        width: 1.5px;
+        height: 39px;
+        margin: 0 10px;
+        background-color: #535353;
+      }
+      .text {
+        overflow: hidden;
+        text-overflow: ellipsis;
+        display: -webkit-box;
+        -webkit-box-orient: vertical;
+        -webkit-line-clamp: 4;
+        font-size: 14px;
+      }
+    }
+  }
+}
+.flex-box {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  font-size: 16px;
+  color: #c9daf0;
+  .icon-chart {
+    width: 79px;
+    height: 62px;
+    background: url('@/assets/images/censusDataAnalysis/forestFire/chart.png') no-repeat;
+    background-size: 100% 100%;
+  }
+}
+.common-table {
+  .table-header {
+    padding: 0;
+  }
+  .tr {
+    padding: 2px 0;
+  }
+}
+</style>

+ 66 - 0
src/views/censusDataAnalysis/DisasterReduction/data.ts

@@ -0,0 +1,66 @@
+export const getImageUrl = (name) => {
+  return new URL(`../../../assets/images/censusDataAnalysis/forestFire/${name}.png`, import.meta.url).href;
+};
+
+export const iconList = {
+  '1': {
+    image: getImageUrl('school'),
+    imageHover: getImageUrl('school'),
+    size: [42, 44]
+  },
+  '2': {
+    image: getImageUrl('scenicSpot'),
+    imageHover: getImageUrl('scenicSpot'),
+    size: [43, 44]
+  },
+  '3': {
+    image: getImageUrl('restaurant'),
+    imageHover: getImageUrl('restaurant'),
+    size: [43, 44]
+  },
+  '4': {
+    image: getImageUrl('gymnasium'),
+    imageHover: getImageUrl('gymnasium'),
+    size: [43, 44]
+  },
+  '5': {
+    image: getImageUrl('hospital'),
+    imageHover: getImageUrl('hospital'),
+    size: [43, 44]
+  },
+  '6': {
+    image: getImageUrl('publicPlace'),
+    imageHover: getImageUrl('publicPlace'),
+    size: [43, 44]
+  },
+  '7': {
+    image: getImageUrl('religiousPlace'),
+    imageHover: getImageUrl('religiousPlace'),
+    size: [43, 44]
+  },
+  '8': {
+    image: getImageUrl('socialInstitution'),
+    imageHover: getImageUrl('socialInstitution'),
+    size: [43, 44]
+  },
+  '9': {
+    image: getImageUrl('supermarket'),
+    imageHover: getImageUrl('supermarket'),
+    size: [43, 44]
+  },
+  '10': {
+    image: getImageUrl('park'),
+    imageHover: getImageUrl('park'),
+    size: [42, 44]
+  },
+  '11': {
+    image: getImageUrl('hazardousChemicalEnterprises'),
+    imageHover: getImageUrl('hazardousChemicalEnterprises'),
+    size: [41, 44]
+  },
+  '12': {
+    image: getImageUrl('gasStation'),
+    imageHover: getImageUrl('gasStation'),
+    size: [43, 44]
+  }
+};

+ 441 - 0
src/views/censusDataAnalysis/DisasterReduction/index.vue

@@ -0,0 +1,441 @@
+<template>
+  <div class="disaster-container">
+    <div class="left-box">
+      <div class="data-box1">
+        <div class="title-box">
+          <div class="gradient-text">分析服务</div>
+        </div>
+        <div class="box-content">
+          <div class="btn-box">
+            <div :class="activeIndex === '1' ? 'text-active text' : 'text'" @click="handleClick('1')">风险分析</div>
+            <div class="line">|</div>
+            <div :class="activeIndex === '2' ? 'text-active text' : 'text'" @click="handleClick('2')">历史分析</div>
+          </div>
+          <div class="tag-box1">
+            <div
+              v-for="(item, index) in analysisServices"
+              :key="index"
+              :class="activeIndex1 === index ? 'tag-item tag-active' : 'tag-item'"
+              @click="handleClick1(item.value)"
+            >
+              <i :class="item.icon" />
+              {{ item.name }}
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="data-box1">
+        <div class="title-box">
+          <div class="gradient-text">图层分析</div>
+        </div>
+        <div class="box-content2">
+          <div class="tag-box2">
+            <div
+              v-for="(item, index) in layerService"
+              :key="index"
+              :class="activeIndex2 === index ? 'tag-item tag-active' : 'tag-item'"
+              @click="handleClick2(item, index)"
+            >
+              <i :class="item.icon" />
+              {{ item.name }}
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="data-box1">
+        <div class="title-box">
+          <div class="gradient-text">基础服务</div>
+        </div>
+        <BaseService @change="handleChange" />
+      </div>
+    </div>
+    <div class="middle-box">
+      <DistributionMap :active-map="activeMap" :distribution-data="distributionData" :points="points" />
+      <div class="map-title">{{ mapTitle }}</div>
+      <div class="map-time">{{ mapTime }}</div>
+      <div class="right-tabs">
+        <div v-for="(item, index) in rightTabs" :key="index" class="tab" @click="handleClick(item.value)">{{ item.name }}</div>
+      </div>
+    </div>
+    <div class="right-box">
+      <RightSection v-show="activeIndex === '1'" id="mapId" :time="mapTime" />
+      <HistoricalAnalysis v-show="activeIndex === '2'" />
+    </div>
+    <!--风险趋势分析-->
+    <RiskTrendAnalysis v-if="showRiskTrendAnalysis" v-model="showRiskTrendAnalysis" @confirm="handleRiskConfirm" />
+  </div>
+</template>
+
+<script lang="ts" setup name="forestFire">
+// 分析服务
+import RightSection from './RightSection.vue';
+import BaseService from './BaseService.vue';
+import RiskTrendAnalysis from '@/views/censusDataAnalysis/RiskTrendAnalysis.vue';
+import { parseTime } from '@/utils/ruoyi';
+import HistoricalAnalysis from '@/views/censusDataAnalysis/HistoricalAnalysis.vue';
+import { area_map } from '@/api/censusDataAnalysis/map';
+
+let activeIndex = ref('1');
+let activeIndex1 = ref(0);
+const analysisServices = ref([{ name: '减灾能力评估', value: '1', icon: 'icon1' }]);
+let showRiskTrendAnalysis = ref(false);
+const handleClick = (value) => {
+  activeIndex.value = value;
+};
+// 点击分析服务
+const handleClick1 = (index) => {
+  if (index === '2') {
+    showRiskTrendAnalysis.value = true;
+  }
+};
+
+// 图层服务
+const activeIndex2 = ref(0);
+const layerService = ref([]);
+// 中部
+// 使用地图地图
+let activeMap = ref('imageMap');
+let mapTitle = ref('减灾能力分析图');
+let mapTime = ref('');
+let distributionData = ref([]);
+let points = ref([]);
+let rightTabs = ref([
+  { name: '风险实时分析', value: '1', icon: '' },
+  { name: '历史分析', value: '2', icon: '' }
+]);
+// 点击图层分析
+const handleClick2 = (item, index) => {
+  if (activeIndex2.value === index) return;
+  activeIndex2.value = index;
+  getDistributionData();
+  console.log('点击', item);
+};
+// 分布图数据
+const getDistributionData = () => {
+  const tempData2 = [
+    {
+      name: '高',
+      color: '#ff2f3c',
+      points: []
+    },
+    {
+      name: '较高',
+      color: '#ffaf00',
+      points: [
+        [
+          // [110.718235, 21.96198],
+          // [110.796045, 22.020253],
+          // [110.915004, 21.964755],
+          // [110.727213, 21.818969],
+          // [110.597389, 22.030205],
+          // [110.677, 22.072317],
+          // [110.718235, 21.96198],
+          // [110.718235, 21.96198]
+        ],
+        [
+          // [110.891302, 22.335445],
+          // [111.02116, 22.266791],
+          // [110.893363, 22.224818],
+          // [110.823281, 22.310657],
+          // [110.891302, 22.335445]
+        ]
+      ]
+    },
+    {
+      name: '较低',
+      color: '#ffd800',
+      points: []
+    },
+    {
+      name: '低',
+      color: '#40c75f',
+      points: [
+        [
+          // [110.491302, 22.035445],
+          // [110.52116, 22.166791],
+          // [110.593363, 22.024818],
+          // [110.491302, 22.035445]
+        ]
+      ]
+    }
+  ];
+  distributionData.value = tempData2;
+};
+// 分布图打点
+const handleChange = (data) => {
+  points.value = data;
+};
+const handleRiskConfirm = (data) => {
+  mapTime.value = data.title;
+  showRiskTrendAnalysis.value = false;
+};
+// 加载数据
+const initData = () => {
+  layerService.value = [
+    { name: '减灾能力分析图', value: '1', icon: 'icon1' },
+    { name: '综合减灾能力评估结果', value: '2', icon: 'icon2' },
+    { name: '政府减灾能力评估结果', value: '3', icon: 'icon3' },
+    { name: '社会组织减灾能力评估结果', value: '4', icon: 'icon4' },
+    { name: '乡镇减灾能力评估结果', value: '5', icon: 'icon5' },
+    { name: '社区减灾能力评估结果', value: '6', icon: 'icon6' },
+    { name: '家庭减灾能力评估结果', value: '7', icon: 'icon7' }
+  ];
+  getDistributionData();
+  const now = new Date();
+  const currentHour = now.getHours();
+  now.setHours(currentHour, 0, 0, 0);
+  mapTime.value = parseTime(now, '{y}年{m}月{d}日 {h}:{i}:{s}');
+};
+onMounted(() => {
+  initData();
+});
+</script>
+
+<style lang="scss" scoped>
+.disaster-container {
+  overflow: hidden;
+  display: flex;
+  .left-box {
+    width: 536px !important;
+    height: 100%;
+    padding-left: 20px;
+    overflow: hidden;
+  }
+  .middle-box {
+    flex: 1;
+    position: relative;
+    .map-title {
+      position: absolute;
+      top: 20px;
+      left: 50%;
+      transform: translateX(-50%);
+      font-size: 24px;
+      font-weight: bold;
+      color: #ffffff;
+    }
+    .map-time {
+      position: absolute;
+      top: 60px;
+      left: 50%;
+      transform: translateX(-50%);
+      font-size: 18px;
+      color: #ffffff;
+    }
+    .right-tabs {
+      display: flex;
+      flex-direction: column;
+      position: absolute;
+      right: 20px;
+      top: 20px;
+      .tab {
+        box-sizing: border-box;
+        width: 46px;
+        height: 144px;
+        background: url('@/assets/images/censusDataAnalysis/tab2.png') no-repeat;
+        background-size: 100% 100%;
+        color: #fefefe;
+        font-size: 14px;
+        padding: 15px 10px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        text-align: center;
+        cursor: pointer;
+      }
+    }
+  }
+  .right-box {
+    width: 535px !important;
+    height: 100%;
+    overflow: hidden;
+  }
+  .data-box1 {
+    &::after {
+      content: '';
+      display: block;
+      width: 517px;
+      height: 19px;
+      background: url('@/assets/images/censusDataAnalysis/line.png') no-repeat;
+      background-size: 100% 100%;
+      margin-top: -8px;
+    }
+    .title-box {
+      width: 516px;
+      height: 40px;
+      background: url('@/assets/images/censusDataAnalysis/titleBox.png') no-repeat;
+      background-size: 100% 100%;
+      padding-left: 50px;
+      .gradient-text {
+        font-size: 24px;
+      }
+    }
+    .box-content {
+      width: 100%;
+      min-height: 54px;
+      background: url('@/assets/images/censusDataAnalysis/box.png') no-repeat;
+      background-size: 100% 100%;
+      .btn-box {
+        display: flex;
+        justify-content: flex-end;
+        align-items: center;
+        margin-top: -20px;
+        padding-right: 45px;
+        .line {
+          margin: 0 5px;
+        }
+        .text {
+          font-size: 14px;
+          color: #ffffff;
+          cursor: pointer;
+        }
+        .text-active {
+          color: #00fce7;
+        }
+      }
+    }
+    .box-content2 {
+      width: 100%;
+      height: 355px;
+      background: url('@/assets/images/censusDataAnalysis/box.png') no-repeat;
+      background-size: 100% 100%;
+      padding: 5px 0;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      overflow-y: auto;
+    }
+  }
+  .tag-box1 {
+    height: 55px;
+    display: flex;
+    flex-wrap: wrap;
+    align-items: center;
+    cursor: pointer;
+    padding: 0 5px;
+    margin-top: 3px;
+    .tag-item {
+      box-sizing: border-box;
+      text-align: center;
+      padding: 8px 0;
+      width: 218px;
+      height: 41px;
+      background: url('@/assets/images/censusDataAnalysis/tag.png') no-repeat;
+      background-size: 100% 100%;
+      font-size: 14px;
+      color: #ffffff;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      &:first-child {
+        margin-right: 30px;
+      }
+      .icon1 {
+        display: inline-block;
+        width: 37px;
+        height: 40px;
+        background: url('@/assets/images/censusDataAnalysis/icon1.png') no-repeat;
+        background-size: 100% 100%;
+        margin-right: 15px;
+      }
+      .icon2 {
+        display: inline-block;
+        width: 38px;
+        height: 40px;
+        background: url('@/assets/images/censusDataAnalysis/icon2.png') no-repeat;
+        background-size: 100% 100%;
+        margin-right: 15px;
+      }
+      &:hover {
+        background: url('@/assets/images/censusDataAnalysis/tagActive.png') no-repeat;
+        background-size: 100% 100%;
+      }
+    }
+  }
+  .tag-box2 {
+    display: flex;
+    flex-direction: column;
+    cursor: pointer;
+    .tag-item {
+      box-sizing: border-box;
+      width: 470px;
+      height: 41px;
+      padding: 8px 0;
+      margin-top: 7px;
+      background: url('@/assets/images/censusDataAnalysis/tag2.png') no-repeat;
+      background-size: 100% 100%;
+      font-size: 14px;
+      color: #ffffff;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      &:first-child {
+        margin-top: 0;
+      }
+      .icon1 {
+        display: inline-block;
+        width: 38px;
+        height: 40px;
+        background: url('@/assets/images/censusDataAnalysis/forestFire/icon1.png') no-repeat;
+        background-size: 100% 100%;
+        margin-right: 15px;
+      }
+      .icon2 {
+        display: inline-block;
+        width: 38px;
+        height: 40px;
+        background: url('@/assets/images/censusDataAnalysis/forestFire/icon2.png') no-repeat;
+        background-size: 100% 100%;
+        margin-right: 15px;
+      }
+      .icon3 {
+        display: inline-block;
+        width: 38px;
+        height: 40px;
+        background: url('@/assets/images/censusDataAnalysis/forestFire/icon3.png') no-repeat;
+        background-size: 100% 100%;
+        margin-right: 15px;
+      }
+      .icon4 {
+        display: inline-block;
+        width: 38px;
+        height: 40px;
+        background: url('@/assets/images/censusDataAnalysis/forestFire/icon4.png') no-repeat;
+        background-size: 100% 100%;
+        margin-right: 15px;
+      }
+      .icon5 {
+        display: inline-block;
+        width: 38px;
+        height: 40px;
+        background: url('@/assets/images/censusDataAnalysis/forestFire/icon4.png') no-repeat;
+        background-size: 100% 100%;
+        margin-right: 15px;
+      }
+      .icon6 {
+        display: inline-block;
+        width: 38px;
+        height: 40px;
+        background: url('@/assets/images/censusDataAnalysis/forestFire/icon4.png') no-repeat;
+        background-size: 100% 100%;
+        margin-right: 15px;
+      }
+      .icon7 {
+        display: inline-block;
+        width: 38px;
+        height: 40px;
+        background: url('@/assets/images/censusDataAnalysis/forestFire/icon4.png') no-repeat;
+        background-size: 100% 100%;
+        margin-right: 15px;
+      }
+      &:hover {
+        background: url('@/assets/images/censusDataAnalysis/tagActive2.png') no-repeat;
+        background-size: 100% 100%;
+      }
+    }
+  }
+  .tag-active {
+    background: url('@/assets/images/censusDataAnalysis/tagActive2.png') no-repeat !important;
+    background-size: 100% 100% !important;
+  }
+}
+</style>

+ 27 - 98
src/views/censusDataAnalysis/NaturalDisaster/RightSection.vue

@@ -14,55 +14,21 @@
       <div class="title-box">
         <div class="gradient-text">茂名市公共服务承灾体数量统计表</div>
       </div>
-      <div class="box-content" style="padding: 5px 0 5px 5px; height: 585px">
-        <div class="box3">
-          <div class="item">
-            <i class="icon1" />
-            <div class="text-box">
-              <div class="text1">镇街数量</div>
-              <div class="text-box2">
-                <div class="text2">6</div>
-                <div class="text3">个</div>
-              </div>
-            </div>
-          </div>
-          <div class="item">
-            <i class="icon2" />
-            <div class="text-box">
-              <div class="text1">人口</div>
-              <div class="text-box2">
-                <div class="text2">23.38</div>
-                <div class="text3">万</div>
-              </div>
-            </div>
-          </div>
-          <div class="item">
-            <i class="icon3" />
-            <div class="text-box">
-              <div class="text1">面积</div>
-              <div class="text-box2">
-                <div class="text2">996.02</div>
-                <div class="text3">km2</div>
-              </div>
+      <div class="box-content" style="padding: 5px 0 5px 5px; height: 255px">
+        <div class="box4">
+          <div class="common-table">
+            <div class="table-header">
+              <div class="td" style="width: 152px">区县</div>
+              <div class="td" style="width: 152px">星级饭店</div>
+              <div class="td" style="width: 152px">旅游景区</div>
             </div>
-          </div>
-          <div class="item">
-            <i class="icon4" />
-            <div class="text-box">
-              <div class="text1">GDP</div>
-              <div class="text-box2">
-                <div class="text2">123</div>
-                <div class="text3">亿</div>
-              </div>
+            <div v-for="(item, index) in tableData" :key="index" class="tr">
+              <div class="td">{{ item.area }}</div>
+              <div class="td">{{ item.data1 }}</div>
+              <div class="td">{{ item.data2 }}</div>
             </div>
           </div>
         </div>
-        <div class="box4">
-          <div v-for="(item, index) in riskData" :key="index" class="item" :style="{ backgroundImage: `url(${item.icon})` }">
-            <div class="text1">{{ item.name }}</div>
-            <div class="text2">{{ item.value }}</div>
-          </div>
-        </div>
       </div>
     </div>
     <Dialog v-model="showExportReport" type="xs" title="导出综合分析报告" hide-footer>
@@ -76,7 +42,6 @@
 
 <script lang="ts" setup name="RightSection">
 import { setHighText } from '@/utils';
-import { getImageUrl } from './data';
 const props = defineProps({
   time: String
 });
@@ -112,42 +77,7 @@ let riskDistributionState = reactive({
   ]
 });
 //
-let riskData = reactive([
-  { name: '公路高边坡', value: '1', icon: getImageUrl('highwaySlope') },
-  { name: '公路水路风险', value: '1', icon: getImageUrl('waterwayRisk') },
-  { name: '公路风险点', value: '1', icon: getImageUrl('highwayRisk') },
-  { name: '公共文化场所', value: '1', icon: getImageUrl('publicPlace2') },
-  { name: '医疗卫生机构', value: '1', icon: getImageUrl('hospital2') },
-  { name: '旅游景区', value: '1', icon: getImageUrl('scenicSpot2') },
-  { name: '宗教活动场所', value: '1', icon: getImageUrl('religiousPlace2') },
-  { name: '学校', value: '1', icon: getImageUrl('school2') },
-  { name: '体育场馆', value: '1', icon: getImageUrl('gymnasium2') },
-  { name: '星级饭店', value: '1', icon: getImageUrl('restaurant2') },
-  { name: '大型超市', value: '1', icon: getImageUrl('supermarket2') },
-  { name: '提供住宿的社会服务机构', value: '1', icon: getImageUrl('socialInstitution2') },
-  { name: '森林消防队伍', value: '1', icon: getImageUrl('firefightTeam') },
-  { name: '防火道路', value: '1', icon: getImageUrl('fireproofRoad') },
-  { name: '防火物资储备点', value: '1', icon: getImageUrl('materialReservePoint') },
-  { name: '尾矿库', value: '1', icon: getImageUrl('tailingPond2') },
-  { name: '金属非金属露天矿山', value: '1', icon: getImageUrl('opencastMine2') },
-  { name: '废石场', value: '1', icon: getImageUrl('wasteRockYard2') },
-  { name: '金属非金属地下矿山', value: '1', icon: getImageUrl('undergroundMine2') },
-  { name: '排土场', value: '1', icon: getImageUrl('dischargePlace2') },
-  { name: '化工园区', value: '1', icon: getImageUrl('park2') },
-  { name: '危化油气企业', value: '1', icon: getImageUrl('oilAndGasCompany') },
-  { name: '加油加气站', value: '1', icon: getImageUrl('gasStation2') }
-]);
-const getColor = (text) => {
-  for (let i = 0; i < colorText.value.length; i++) {
-    if (colorText.value[i].text === text) {
-      return colorText.value[i].color;
-    }
-  }
-  return '#fff';
-};
-const handleSelectLevel = (value) => {
-  riskDistributionState.showLevel = value;
-};
+const tableData = ref([]);
 const getData = () => {
   const data = {
     time1: '2024-10-31 09:00:00',
@@ -181,23 +111,14 @@ const getData = () => {
   riskDistributionState.townShipLevel[2].value = data3.data3;
   riskDistributionState.townShipLevel[3].value = data3.data4;
   riskDistributionState.townShipLevel[4].value = data3.data5;
-};
-const parseTime2 = (dateStr) => {
-  if (!dateStr) return '';
-  let time = dateStr.replace(/年/g, '-').replace(/月/g, '-').replace(/日/g, '');
-  // 将字符串转换为 Date 对象
-  const date = new Date(time);
 
-  // 设置时间为 00:00:00
-  date.setHours(0, 0, 0, 0);
-
-  // 格式化输出为所需的字符串格式
-  const year = date.getFullYear();
-  const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,所以需要+1
-  const day = String(date.getDate()).padStart(2, '0');
-  const formattedDate = `${year}年${month}月${day}日 00:00:00`;
-
-  return formattedDate;
+  tableData.value = [
+    { area: '茂南区', data1: '123', data2: '74' },
+    { area: '电白区', data1: '23', data2: '12' },
+    { area: '高州区', data1: '14', data2: '23' },
+    { area: '化州区', data1: '25', data2: '14' },
+    { area: '信宜区', data1: '21', data2: '24' }
+  ];
 };
 onMounted(() => {
   getData();
@@ -545,4 +466,12 @@ onMounted(() => {
     background-size: 100% 100%;
   }
 }
+.common-table {
+  .table-header {
+    padding: 0;
+  }
+  .tr {
+    padding: 2px 0;
+  }
+}
 </style>

+ 3 - 1
src/views/censusDataAnalysis/index.vue

@@ -34,6 +34,7 @@
     <FloodingDisaster v-else-if="specialSubjectState.activeIndex === 'FloodingDisaster'" class="content" />
     <SeismicHazard v-else-if="specialSubjectState.activeIndex === 'SeismicHazard'" class="content" />
     <NaturalDisaster v-else-if="specialSubjectState.activeIndex === 'NaturalDisaster'" class="content" />
+    <DisasterReduction v-else-if="specialSubjectState.activeIndex === 'DisasterReduction'" class="content" />
     <FooterSection style="position: absolute; bottom: 0; left: 0" />
   </div>
 </template>
@@ -48,6 +49,7 @@ import OceanDisaster from './OceanDisaster/index.vue';
 import SeismicHazard from './SeismicHazard/index.vue';
 import NaturalAnalysis from './NaturalAnalysis/index.vue';
 import NaturalDisaster from './NaturalDisaster/index.vue';
+import DisasterReduction from './DisasterReduction/index.vue';
 import useUserStore from '@/store/modules/user';
 import autofit from 'autofit.js';
 import { getTransformScale } from '@/utils';
@@ -77,7 +79,7 @@ let specialSubjectState = reactive({
   showMenu: false,
   menu: [
     { name: '自然灾害综合分析', value: 'NaturalAnalysis' },
-    { name: '减灾能力综合展示', value: '2' },
+    { name: '减灾能力综合展示', value: 'DisasterReduction' },
     { name: '自然灾害承灾体综合', value: 'NaturalDisaster' },
     { name: '森林火灾风险综合', value: 'ForestFire' },
     { name: '海洋灾害风险综合', value: 'OceanDisaster' },