ZhangXianQiang
2024-03-12 05e80f0a0531e3b3d10836599f63189af0ee0524
feat:首页添加地图
2个文件已修改
5个文件已添加
33742 ■■■■■ 已修改文件
package.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/map/dujiangyan.json 33093 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/data-view/components/data-hola.vue 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/data-view/components/data-icon.vue 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/data-view/components/data-map.vue 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/data-view/components/data-plane.vue 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/data-view/index.vue 265 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -41,6 +41,7 @@
    "clipboard": "2.0.8",
    "core-js": "3.25.3",
    "echarts": "5.4.0",
    "echarts-gl": "^2.0.9",
    "element-ui": "2.15.14",
    "file-saver": "2.0.5",
    "fuse.js": "6.4.3",
src/assets/map/dujiangyan.json
New file
Diff too large
src/views/home/data-view/components/data-hola.vue
New file
@@ -0,0 +1,110 @@
<template>
  <div class="hola-container">
    <div class="hola-content" ref="hola"></div>
  </div>
</template>
<script>
import * as echarts from 'echarts';
let holaChart = null;
const config = {
  tooltip: {
    trigger: 'item'
  },
  legend: {
    top: '5%',
    left: 'center'
  },
  series: [
    {
      type: 'pie',
      radius: ['40%', '70%'],
      avoidLabelOverlap: false,
      itemStyle: {
        borderRadius: 10,
        borderColor: '#fff',
        borderWidth: 2
      },
      label: {
        show: false,
        position: 'center'
      },
      emphasis: {
        label: {
          show: false,
          fontSize: 40,
          fontWeight: 'bold'
        }
      },
      labelLine: {
        show: false
      },
      data: []
    }
  ]
}
const nameList = {
  data1: '工单数',
  data2: '恢复数',
  data3: '待恢复数',
  data4: '产生违约事项数',
  data5: '产生违约责任数',
}
export default {
  props: {
    activeData: {
      type: Object,
      default: () => { },
    }
  },
  data() {
    return {
    }
  },
  methods: {
    changeConfig(data) {
      if (data) {
        let temp = [];
        Object.keys(data).filter(key => key !== 'name').forEach(key => {
          temp.push({
            name: nameList[key],
            value: data[key]
          });
        });
        config.series[0].data = temp;
        holaChart.setOption(config, true);
      }
    }
  },
  watch: {
    activeData: {
      handler(newVal, oldVal) {
        this.$nextTick(() => {
          this.changeConfig(newVal);
        })
      },
      immediate: true,
    }
  },
  mounted() {
    holaChart = echarts.init(this.$refs.hola);
    holaChart.setOption(config, true);
  }
}
</script>
<style lang="scss" scoped>
.hola-container {
  width: 100%;
  height: 100%;
  .hola-content {
    width: 100%;
    height: 100%;
  }
}
</style>
src/views/home/data-view/components/data-icon.vue
New file
@@ -0,0 +1,127 @@
<template>
  <div class="data-container">
    <div class="data-content">
      <div class="icon-item" v-for="item, index in dataList" :style="{ backgroundColor: iconList[index].color }"
        :key="item.id">
        <div class="icon-container">
          <i :class="iconList[index].icon" class="icon-font"></i>
        </div>
        <div class="data-info">
          <div class="data-num">{{ item.value }}</div>
          <div class="data-lable">{{ item.name }}</div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
const nameList = {
  data1: '工单数',
  data2: '恢复数',
  data3: '待恢复数',
  data4: '产生违约事项数',
  data5: '产生违约责任数',
}
export default {
  props: {
    activeData: {
      type: Object,
      default: () => { return { name: '自贡市', data1: 0, data2: 0, data3: 0, data4: 0, data5: 0 } },
    }
  },
  data() {
    return {
      dataList: [],
      iconList: [
        { icon: 'el-icon-tickets', color: '#7868d9' },
        { icon: 'el-icon-s-claim', color: '#3eba45' },
        { icon: 'el-icon-edit', color: '#3da7f8' },
        { icon: 'el-icon-warning', color: '#ffbe40' },
        { icon: 'el-icon-error', color: '#fe640d' },
      ]
    }
  },
  methods: {
    formatData(data) {
      if (data) {
        let temp = [];
        Object.keys(data).filter(key => key !== 'name').forEach((key, index) => {
          temp.push({
            id: index + 1,
            name: nameList[key],
            value: data[key]
          });
        });
        this.dataList = temp;
      }
    }
  },
  watch: {
    activeData: {
      handler(newVal, oldVal) {
        this.$nextTick(() => {
          this.formatData(newVal);
        })
      },
      immediate: true,
    }
  },
}
</script>
<style lang="scss" scoped>
.data-container {
  height: 100%;
}
.data-content {
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
}
.icon-item {
  display: flex;
  border-radius: 10px;
  align-items: center;
  padding: 10px 10px;
}
.icon-container {
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 8px;
  margin-right: 10px;
  .icon-font {
    font-size: 34px;
    color: #fff;
  }
}
.data-info {
  display: flex;
  height: 100%;
  flex-direction: column;
  justify-content: center;
  text-align: left;
  color: #fff;
  .data-num {
    font-size: 30px;
  }
  .data-lable {
    font-size: 16px;
    text-indent: 3px;
  }
}
</style>
src/views/home/data-view/components/data-map.vue
New file
@@ -0,0 +1,116 @@
<template>
  <div class="map-container">
    <div ref="map" class="map-style"></div>
  </div>
</template>
<script>
import * as echarts from 'echarts';
import 'echarts-gl';
import mapData from '@/assets/map/dujiangyan.json';
echarts.registerMap('dujiangyan', mapData);
console.log(mapData);
let mapChart = null;
let tempName = '';
const mapConfig = {
  series: [{
    map: "dujiangyan", //注册地图的名字
    type: "map3D",
    bottom: 0,
    left: 0,
    top: 0,
    right: 0,
    itemStyle: {
      color: "#4189f2", // 背景
      opacity: 1, //透明度
      borderWidth: 1.5, // 边框宽度
      borderColor: "#fff", // 边框颜色
      fontSize: 16, //
    },
    // 标签
    label: {
      show: true,
      color: "#fff", //地图初始化区域字体颜色
      fontSize: 18,
    },
    // 控制器
    viewControl: {
      beta: 82,
      alpha: 90,
      distance: 180,
      maxBeta: 180
    },
    // 鼠标移入时样式
    emphasis: {
      itemStyle: {
        color: "#F63545"
      }
    },
    // 数据
    data: mapData.features.map((item) => {
      return {
        name: item.properties.name,
        itemStyle: {
          color: "#4189f2"
        }
      }
    }),
  }
  ]
};
export default {
  name: 'DataMap',
  data() {
    return {
    }
  },
  components: {
  },
  methods: {
    filterData(name) {
      this.initConfig();
      let temp = mapConfig.series[0].data.find(item => item.name === name);
      temp.itemStyle.color = '#F63545';
      mapChart.setOption(mapConfig, true);
      this.$emit('filterData', name);
    },
    initConfig() {
      mapConfig.series[0].data.forEach(item => {
        item.itemStyle.color = '#4189f2';
      });
    }
  },
  mounted() {
    mapChart = echarts.init(this.$refs.map);
    mapChart.setOption(mapConfig, true);
    mapChart.on('click', (params) => {
      if (tempName === params.name) {
        tempName = '';
        this.initConfig();
        mapChart.setOption(mapConfig, true);
        this.$emit('filterData', '');
      } else {
        tempName = params.name;
        this.filterData(params.name);
      }
    })
  }
}
</script>
<style lang="scss" scoped>
.map-container {
  width: 100%;
  height: 100%;
  .map-style {
    width: 100%;
    height: 100%;
  }
}
</style>
src/views/home/data-view/components/data-plane.vue
New file
@@ -0,0 +1,30 @@
<template>
  <el-card class="data-container" :body-style="{ height: '100%' }">
    <el-row :gutter="40" style="height: 100%;">
      <el-col :span="12" style="height: 100%;">
        <data-hola></data-hola>
      </el-col>
      <el-col :span="12" style="height: 100%;">
        <data-icon></data-icon>
      </el-col>
    </el-row>
  </el-card>
</template>
<script>
import DataIcon from './data-icon.vue';
import DataHola from './data-hola.vue';
export default {
  components: {
    DataIcon,
    DataHola,
  },
}
</script>
<style lang="scss" scoped>
.data-container {
  width: 100%;
  aspect-ratio: 6/3;
}
</style>
src/views/home/data-view/index.vue
@@ -5,35 +5,40 @@
        <h1 class="title">运维报表</h1>
      </el-col>
    </el-row>
    <el-row :gutter="20" class="data-plane">
      <el-col :xs='24' :md="6" :xl="{ span: '4-8' }" :sm="12" v-for="item, index in dataList" :key="item.id">
        <div class="col-content">
          <el-card>
            <el-row type="flex" align="middle" justify="space-between">
              <el-col :xl="8" :lg="8" :md="10" :sm="8" :xs="6">
                <div class="icon-container" :style="{ backgroundColor: iconList[index].color }">
                  <i :class="iconList[index].icon" class="icon-font"></i>
                </div>
              </el-col>
              <el-col :xl="14" :lg="14" :md="12" :sm="14" :xs="16">
                <div class="data-info">
                  <div class="data-num">{{ item.num }}</div>
                  <div class="data-lable">{{ item.type }}</div>
                </div>
              </el-col>
            </el-row>
          </el-card>
        </div>
      </el-col>
    </el-row>
    <el-card class="map-wrapper">
      <el-row :gutter="40" class="data-plane" style="height: 100%;">
        <el-col :xs='24' :md="24" :sm="24" :lg="12" :xl="6" style="height: 100%;">
          <data-icon :activeData="activeData"></data-icon>
        </el-col>
        <el-col :xs='24' :md="24" :sm="24" :lg="12" :xl="12" style="height: 100%;">
          <data-map @filterData="filterData"></data-map>
        </el-col>
        <el-col :xs='24' :md="24" :sm="24" :lg="12" :xl="6" style="height: 100%;">
          <data-hola :activeData="activeData"></data-hola>
        </el-col>
      </el-row>
    </el-card>
  </div>
</template>
<script>
// import DataPlane from './components/data-plane.vue';
import DataMap from './components/data-map.vue';
import DataIcon from './components/data-icon.vue';
import DataHola from './components/data-hola.vue';
export default {
  name: 'DataView',
  components: {
    DataMap,
    DataIcon,
    DataHola,
    // DataPlane
  },
  data() {
    return {
      dataList: [
@@ -49,8 +54,193 @@
        { icon: 'el-icon-edit', color: '#3da7f8' },
        { icon: 'el-icon-warning', color: '#ffbe40' },
        { icon: 'el-icon-error', color: '#fe640d' },
      ]
      ],
      totalList: [
        {
          "name": "虹口乡",
          "data1": 3,
          "data2": 82,
          "data3": 5,
          "data4": 95,
          "data5": 50
        },
        {
          "name": "玉堂镇",
          "data1": 1,
          "data2": 94,
          "data3": 38,
          "data4": 60,
          "data5": 87
        },
        {
          "name": "崇义镇",
          "data1": 15,
          "data2": 57,
          "data3": 81,
          "data4": 77,
          "data5": 85
        },
        {
          "name": "龙池镇",
          "data1": 8,
          "data2": 7,
          "data3": 60,
          "data4": 77,
          "data5": 43
        },
        {
          "name": "中兴镇",
          "data1": 40,
          "data2": 75,
          "data3": 50,
          "data4": 69,
          "data5": 79
        },
        {
          "name": "蒲阳镇",
          "data1": 68,
          "data2": 38,
          "data3": 27,
          "data4": 43,
          "data5": 95
        },
        {
          "name": "大观镇",
          "data1": 52,
          "data2": 9,
          "data3": 74,
          "data4": 40,
          "data5": 82
        },
        {
          "name": "幸福镇",
          "data1": 52,
          "data2": 10,
          "data3": 26,
          "data4": 70,
          "data5": 61
        },
        {
          "name": "天马镇",
          "data1": 66,
          "data2": 44,
          "data3": 77,
          "data4": 68,
          "data5": 51
        },
        {
          "name": "安龙镇",
          "data1": 80,
          "data2": 77,
          "data3": 84,
          "data4": 79,
          "data5": 47
        },
        {
          "name": "聚源镇",
          "data1": 85,
          "data2": 78,
          "data3": 12,
          "data4": 37,
          "data5": 32
        },
        {
          "name": "胥家镇",
          "data1": 91,
          "data2": 76,
          "data3": 30,
          "data4": 47,
          "data5": 28
        },
        {
          "name": "向峨乡",
          "data1": 32,
          "data2": 41,
          "data3": 45,
          "data4": 60,
          "data5": 54
        },
        {
          "name": "柳街镇",
          "data1": 8,
          "data2": 80,
          "data3": 4,
          "data4": 14,
          "data5": 20
        },
        {
          "name": "紫坪铺镇",
          "data1": 1,
          "data2": 88,
          "data3": 41,
          "data4": 21,
          "data5": 88
        },
        {
          "name": "灌口镇",
          "data1": 85,
          "data2": 72,
          "data3": 79,
          "data4": 27,
          "data5": 42
        },
        {
          "name": "青城山镇",
          "data1": 77,
          "data2": 1,
          "data3": 33,
          "data4": 92,
          "data5": 45
        },
        {
          "name": "滨江街道",
          "data1": 82,
          "data2": 43,
          "data3": 9,
          "data4": 34,
          "data5": 96
        },
        {
          "name": "翠月湖镇",
          "data1": 30,
          "data2": 41,
          "data3": 80,
          "data4": 9,
          "data5": 53
        },
        {
          "name": "石羊镇",
          "data1": 9,
          "data2": 15,
          "data3": 24,
          "data4": 92,
          "data5": 37
        }
      ],
      activeData: {name: '自贡市', data1: 0, data2: 0, data3: 0, data4: 0, data5:0}
    }
  },
  methods: {
    filterData(name) {
      if (name) {
        this.activeData = this.totalList.find(item => item.name === name);
      } else {
        this.countTotal();
      }
    },
    countTotal() {
      let data = {};
      this.totalList.forEach((item) => {
        Object.keys(item).forEach((key) => {
          data[key] = data[key] ? data[key] + item[key] : item[key];
        });
      });
      data.name = '自贡市';
      this.activeData = data;
    }
  },
  created() {
    this.countTotal();
  }
}
</script>
@@ -59,6 +249,7 @@
.data-container {
  margin-bottom: 20px;
}
.title {
  text-align: left;
}
@@ -71,33 +262,13 @@
  margin-bottom: 10px;
}
.icon-container {
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 8px;
.map-wrapper {
  // background-color: rgb(48, 65, 86);
  .icon-font {
    font-size: 30px;
    color: #fff;
  }
}
.data-info {
  display: flex;
  height: 100%;
  flex-direction: column;
  justify-content: center;
  text-align: left;
  .data-num {
    font-size: 32px;
  }
  .data-lable {
    font-size: 16px;
    text-indent: 3px;
  }
.data-plane {
  aspect-ratio: 6/2;
}
@media screen and (min-width: 1200px) {