Procházet zdrojové kódy

feat: 企业数据可视化页面搭建

zhangying před 10 měsíci
rodič
revize
40baf86906

+ 6 - 0
doc/待更新脚本

@@ -0,0 +1,6 @@
+-- 2024-5-24 添加企业数据可视化地图菜单与权限编码
+INSERT INTO sys_function_code VALUES ('T010203', '企业数据地图', 'T0102', 3);
+INSERT INTO `sys_menu` VALUES ('T010203', 3, '企业可视化地图', NULL, 'companyService/dataMap/index', '/companyDataMap', 'T0102', NULL, 0, 1, 1, 'T010502', 1, NULL);
+-- 2024-5-24 为系统管理员和市级管理员添加企业数据可视化地图权限
+insert into sys_role_sys_function_code (`RoleID`, `FunctionCode`) values('20afde90-a81a-11ed-a6c5-7085c2a9999e','T010203');
+insert into sys_role_sys_function_code (`RoleID`, `FunctionCode`) values('d6f0d433-7a58-497e-b203-d8309edebaba','T010203');

+ 2 - 1
vue/src/router/asyncModules/companyService.ts

@@ -7,5 +7,6 @@ export default {
   'companyService/post/add': () => import('@/views/companyService/post/edit.vue'),
   'companyService/post/edit': () => import('@/views/companyService/post/edit.vue'),
   'companyService/post/recommend': () => import('@/views/companyService/post/recommend.vue'),
-  'companyService/post/detail': () => import('@/views/companyService/post/detail.vue')
+  'companyService/post/detail': () => import('@/views/companyService/post/detail.vue'),
+  'companyService/dataMap/index': () => import('@/views/companyService/dataMap/index.vue'),
 };

+ 24 - 0
vue/src/utils/position.ts

@@ -0,0 +1,24 @@
+// 获取经纬度
+export function getPosition() {
+  return new Promise((resolve, reject) => {
+    if (navigator.geolocation) {
+      navigator.geolocation.getCurrentPosition(function (position) {
+        const latitude = position.coords.latitude.toFixed(5)
+        const longitude = position.coords.longitude.toFixed(5)
+        const data = {
+          latitude: latitude,
+          longitude: longitude
+        }
+        resolve(data)
+      }, function () {
+        // eslint-disable-next-line prefer-rest-params
+        reject(arguments)
+      }, {
+        enableHighAccuracy: true,
+        timeout: 10000
+      })
+    } else {
+      reject('你的浏览器不支持当前地理位置信息获取')
+    }
+  })
+}

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 7805 - 0
vue/src/views/companyService/dataMap/geo.ts


+ 257 - 0
vue/src/views/companyService/dataMap/index.vue

@@ -0,0 +1,257 @@
+<template>
+  <div class="card-search">
+    <div class="map-box">
+      <!-- 地图 -->
+      <div
+        id="mapDiv"
+      ></div>
+      <!-- 企业查询 -->
+      <div class="company-box">
+        <!-- 查询区域 -->
+        <div class="search-box">
+          <!-- 企业名称 -->
+          <div class="flex-div">
+            <a-select
+              v-model:value="searchType"
+            >
+              <a-select-option value="company">找企业</a-select-option>
+              <a-select-option value="post">找岗位</a-select-option>
+            </a-select>
+            <a-input-search
+              v-model:value="companySearchParam.companyName"
+              placeholder="请输入企业名称"
+              enter-button="查询"
+              @search="onSearch"
+            />
+          </div>
+          <!-- 多选框 -->
+          <div class="flex-div" style="flex-wrap: wrap">
+            <a-button style="width: 28%">全部</a-button>
+            <a-select
+              v-model:value="companySearchParam.range"
+              style="width: 34%;"
+              :allow-clear="true"
+            >
+              <a-select-option :value="item.value" v-for="(item,index) in rangeList" :key="index">{{
+                  item.label
+                }}
+              </a-select-option>
+            </a-select>
+            <a-select
+              style="width: 38%;"
+              v-model:value="companySearchParam.companyModel"
+              :options="companyModelList"
+              :field-names="{ label: 'name', value: 'value' }"
+              placeholder="企业规模"
+              :allow-clear="true"
+            >
+            </a-select>
+            <a-select
+              style="width: 50%;"
+              v-model:value="companySearchParam.regionCode"
+              :allow-clear="true"
+              :options="regionList"
+              :field-names="{ label: 'name', value: 'code' }"
+              placeholder="所属县区"
+            >
+            </a-select>
+            <a-select
+              style="width: 50%;"
+              v-model:value="companySearchParam.siteID"
+              :allow-clear="true"
+              :options="siteList"
+              :field-names="{ label: 'siteName', value: 'siteID' }"
+              placeholder="所属驿站"
+            >
+            </a-select>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import {onMounted, reactive, ref} from "vue";
+import huiZhouGeoJSON from "./geo"
+import {getPosition} from "@/utils/position";
+import thIcon from "@/assets/images/th.jpg"
+import type {SelectProps} from "ant-design-vue";
+import {getSysDictionaryList} from "@/api/system/dictionary";
+import {getSiteList} from "@/api/baseSettings/siteInfo";
+import {getRegionCodeList} from "@/api/system/area/index";
+
+const T = (window as any).T;
+const zoom = 9;
+let map = null;
+// 定位
+const position = reactive({
+  longitude: 114.4,
+  latitude: 23.08
+});
+// 查询类型
+const searchType = ref("company")
+// 企业查询条件
+const companySearchParam = reactive({
+  companyName: "",
+  range: 5,
+  companyModel: undefined,
+  siteID: undefined,
+  regionCode: undefined
+})
+
+// 范围列表
+const rangeList = [
+  {value: 5, label: "5KM"},
+  {value: 3, label: "3KM"},
+  {value: 1, label: "1KM"}
+]
+// 企业规模
+const companyModelList = ref<SelectProps['options']>();
+// 所属驿站
+const siteList = ref<any>([]);
+// 所属县区
+const regionList = ref<SelectProps['options']>();
+
+// 查询企业规模
+const getCompanyModelList = async function () {
+  companyModelList.value = await getSysDictionaryList("CompanyModel");
+}
+// 查询驿站
+const getAllSites = () => {
+  getSiteList({pageIndex: 1, pageSize: 9999}).then((result: any) => {
+    siteList.value = result.list;
+  })
+}
+// 查询县区
+const getRegionList = async function () {
+  regionList.value = await getRegionCodeList();
+}
+
+// 查询事件
+function onSearch() {
+  console.log(companySearchParam)
+}
+
+// 地图初始化
+const initMap = () => {
+  // 初始化容器
+  map = new T.Map('mapDiv');
+
+  if (map != null) {
+    // 设置地图显示中心点为惠州市
+    (map as any).centerAndZoom(new T.LngLat(114.4, 23.08), zoom);
+  }
+
+  // 设置城市边界
+  setBoundary()
+
+  // 设置登录用户的定位
+  setLoginLocation();
+};
+
+// 设置惠州市边界
+function setBoundary() {
+  if (map != null) {
+    const points = new Array<any>();
+    huiZhouGeoJSON.geometry.coordinates.forEach(subset => {
+      subset.forEach((item: any) => {
+        item.forEach((coord: any) => {
+          const point = new T.LngLat(coord[0], coord[1]);
+
+          points.push(point);
+        })
+      })
+    });
+    const polygon = new T.Polygon(points, {
+      color: "deepskyblue",
+      weight: 3,
+      opacity: 0.8,
+      fillColor: "LightCyan",
+      fillOpacity: 0.3
+    });
+
+    // 添加多边形到地图
+    (map as any).addOverLay(polygon);
+  }
+}
+
+// 获取当前登录用户定位
+function setLoginLocation() {
+  getPosition().then((data: any) => {
+    if (data.longitude && data.latitude) {
+      // position.longitude = data.longitude;
+      // position.latitude = data.latitude;
+
+      position.longitude = 114.420244;
+      position.latitude = 23.116236;
+
+      // 设置中心点
+      (map as any).centerAndZoom(new T.LngLat(position.longitude, position.latitude), 12);
+      const icon = new T.Icon({
+        iconUrl: thIcon,
+        iconSize: new T.Point(30, 30),
+        iconAnchor: new T.Point(10, 56)
+      })
+      const point = new T.LngLat(position.longitude, position.latitude, {
+        icon: icon
+      })
+      // 创建标注
+      const marker = new T.Marker(point);
+      //向地图上标记
+      (map as any).addOverLay(marker);
+    }
+  })
+}
+
+onMounted(() => {
+  initMap();
+  getCompanyModelList();
+  getAllSites();
+  getRegionList();
+})
+</script>
+
+<script lang="ts">
+// 设置页面名称进行组件缓存
+export default {
+  name: "CompanyDataMap"
+}
+</script>
+
+<style lang="less" scoped>
+.map-box {
+  width: 100%;
+  height: calc(100vh - 235px);
+  position: relative;
+
+  #mapDiv {
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    z-index: 100;
+  }
+
+  .company-box {
+    width: 300px;
+    height: 100%;
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 300px;
+    z-index: 110;
+    background-color: white;
+    border: 1px rgba(115, 115, 115, 0.5) solid;
+
+    .search-box {
+      width: 100%;
+
+      .flex-div {
+        width: 100%;
+        display: flex;
+      }
+    }
+  }
+}
+</style>