refactor(superManagement): 重构超级后台首页地图展示功能
- 新增 MapVisionParams 类用于地图视野参数 - 移除 EnterprisesUnitController 中的 mapPoint 方法 - 新增 SuperIndexController、SuperIndexMapper 和 SuperIndexService - 更新 SecurityUnitUseStatisticsDTO,添加省市区街道编码字段 - 优化 SignInterceptor 中的签名生成和验证逻辑 - 更新 OpenApiMapper.xml,移除冗余的删除标志条件 - 重构 MapContainer组件,移除初始化地图样式- 更新路由配置,移除数据总览菜单项 - 重命名 EnterprisesUnitInfoWindowContent 组件 - 重构数据总览页面,改为在首页展示地图信息
This commit is contained in:
parent
5bb44b0dc2
commit
00c6b0409f
|
@ -0,0 +1,22 @@
|
|||
package com.changhu.common.pojo.params;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.locationtech.jts.geom.Point;
|
||||
|
||||
/**
|
||||
* @author 20252
|
||||
* @createTime 2024/11/21 上午11:18
|
||||
* @desc MapVisionParams...
|
||||
*/
|
||||
@Data
|
||||
public class MapVisionParams {
|
||||
@Schema(description = "左上角")
|
||||
private Point upperLeft;
|
||||
@Schema(description = "右上角")
|
||||
private Point upperRight;
|
||||
@Schema(description = "左下角")
|
||||
private Point lowerLeft;
|
||||
@Schema(description = "右下角")
|
||||
private Point lowerRight;
|
||||
}
|
|
@ -6,7 +6,6 @@ import com.changhu.common.annotation.JsonBody;
|
|||
import com.changhu.common.db.enums.UserType;
|
||||
import com.changhu.common.exception.MessageException;
|
||||
import com.changhu.common.pojo.vo.SelectNodeVo;
|
||||
import com.changhu.module.management.pojo.entity.EnterprisesUnit;
|
||||
import com.changhu.module.management.pojo.params.EnterprisesUnitSaveOrUpdateParams;
|
||||
import com.changhu.module.management.pojo.queryParams.EnterprisesUnitPagerQueryParams;
|
||||
import com.changhu.module.management.pojo.vo.EnterprisesUnitPagerVo;
|
||||
|
@ -64,10 +63,4 @@ public class EnterprisesUnitController {
|
|||
return enterprisesUnitService.queryListByAdministrativeDivisionCodes(administrativeDivisionCodes);
|
||||
}
|
||||
|
||||
@Operation(summary = "企事业单位地图点位")
|
||||
@GetMapping("/mapPoint")
|
||||
public List<EnterprisesUnit> mapPoint() {
|
||||
return enterprisesUnitService.list();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package com.changhu.module.superManagement.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.toolkit.Db;
|
||||
import com.changhu.common.annotation.JsonBody;
|
||||
import com.changhu.module.management.pojo.entity.EnterprisesUnit;
|
||||
import com.changhu.module.superManagement.service.SuperIndexService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author 20252
|
||||
* @createTime 2024/11/21 上午11:31
|
||||
* @desc SuperIndexController...
|
||||
*/
|
||||
@JsonBody
|
||||
@Tag(name = "超级后台首页")
|
||||
@RequestMapping("/super/index")
|
||||
public class SuperIndexController {
|
||||
|
||||
@Autowired
|
||||
private SuperIndexService superIndexService;
|
||||
|
||||
@Operation(summary = "企事业单位地图点位")
|
||||
@GetMapping("/mapPoint")
|
||||
public List<EnterprisesUnit> mapPoint() {
|
||||
return Db.lambdaQuery(EnterprisesUnit.class).list();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.changhu.module.superManagement.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* @author 20252
|
||||
* @createTime 2024/11/21 上午11:32
|
||||
* @desc SuperIndexMapper...
|
||||
*/
|
||||
@Mapper
|
||||
public interface SuperIndexMapper {
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.changhu.module.superManagement.service;
|
||||
|
||||
/**
|
||||
* @author 20252
|
||||
* @createTime 2024/11/21 上午11:31
|
||||
* @desc SuperIndexService...
|
||||
*/
|
||||
public interface SuperIndexService {
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.changhu.module.superManagement.service.impl;
|
||||
|
||||
import com.changhu.module.superManagement.service.SuperIndexService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author 20252
|
||||
* @createTime 2024/11/21 上午11:31
|
||||
* @desc SuperIndexServiceImpl...
|
||||
*/
|
||||
@Service
|
||||
public class SuperIndexServiceImpl implements SuperIndexService {
|
||||
}
|
|
@ -20,12 +20,20 @@ public class SecurityUnitUseStatisticsDTO {
|
|||
private Long enterprisesUnitId;
|
||||
@Schema(description = "事业单位名称")
|
||||
private String enterprisesUnitName;
|
||||
@Schema(description = "省编码")
|
||||
private String province;
|
||||
@Schema(description = "省")
|
||||
private String provinceName;
|
||||
@Schema(description = "市编码")
|
||||
private String city;
|
||||
@Schema(description = "市")
|
||||
private String cityName;
|
||||
@Schema(description = "区/县编码")
|
||||
private String districts;
|
||||
@Schema(description = "区/县")
|
||||
private String districtsName;
|
||||
@Schema(description = "街道编码")
|
||||
private String street;
|
||||
@Schema(description = "街道")
|
||||
private String streetName;
|
||||
@Schema(description = "事业单位详细地址")
|
||||
|
|
|
@ -4,7 +4,7 @@ import cn.hutool.core.util.StrUtil;
|
|||
import cn.hutool.core.util.URLUtil;
|
||||
import cn.hutool.crypto.digest.MD5;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson2.TypeReference;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.Db;
|
||||
import com.changhu.common.db.enums.IsEnable;
|
||||
import com.changhu.common.exception.MessageException;
|
||||
|
@ -67,7 +67,7 @@ public class SignInterceptor implements HandlerInterceptor {
|
|||
.orElseThrow(() -> new MessageException("无效的accessKey"));
|
||||
|
||||
if (IsEnable.FALSE.equals(accessKeyEntity.getIsEnable())) {
|
||||
throw new MessageException("无效的accessKey");
|
||||
throw new MessageException("accessKey已禁用");
|
||||
}
|
||||
|
||||
if (accessKeyEntity.getEffectiveTime() > 0 && System.currentTimeMillis() - Long.parseLong(timestamp) > accessKeyEntity.getEffectiveTime()) {
|
||||
|
@ -80,20 +80,17 @@ public class SignInterceptor implements HandlerInterceptor {
|
|||
}
|
||||
|
||||
Map<String, Object> hashMap = new HashMap<>();
|
||||
//添加请求url参数
|
||||
Map<String, String> map = HttpUtil.decodeParamMap(request.getQueryString(), StandardCharsets.UTF_8);
|
||||
if (!map.isEmpty()) {
|
||||
hashMap.putAll(map);
|
||||
}
|
||||
|
||||
hashMap.put(ACCESS_KEY, accessKey);
|
||||
hashMap.put(TIMESTAMP, timestamp);
|
||||
//添加请求url参数
|
||||
Optional.ofNullable(HttpUtil.decodeParamMap(request.getQueryString(), StandardCharsets.UTF_8))
|
||||
.ifPresent(hashMap::putAll);
|
||||
//添加body参数
|
||||
CustomHttpServletRequestWrapper c = (CustomHttpServletRequestWrapper) request;
|
||||
Optional.ofNullable(new TypeReference<Map<String, Object>>() {
|
||||
}.parseObject(c.getBody())).ifPresent(hashMap::putAll);
|
||||
|
||||
Optional.ofNullable(JSON.<Map<String, Object>>parseObject(((CustomHttpServletRequestWrapper) request).getBody(), Map.class))
|
||||
.ifPresent(hashMap::putAll);
|
||||
//生成签名
|
||||
String nowSign = generatedSign(hashMap, accessKeyEntity.getSecretKey());
|
||||
//比对签名
|
||||
if (!sign.equals(nowSign)) {
|
||||
throw new MessageException("签名错误");
|
||||
}
|
||||
|
@ -118,9 +115,4 @@ public class SignInterceptor implements HandlerInterceptor {
|
|||
return MD5.create().digestHex(str).toUpperCase();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String str1 = "Access-Key=w2wzi0wefmmo6s735z2el8tfzitya5gj&addr=%E6%B9%96%E5%8D%97%E7%9C%81%E9%95%BF%E6%B2%99%E5%B8%82&age=14&name=zhangsan&Time-Stamp=1732084303463&Secret-Key=db1b5214-02ee-497f-957c-88323b4351bf";
|
||||
String str2 = "Access-Key=w2wzi0wefmmo6s735z2el8tfzitya5gj&addr=%E6%B9%96%E5%8D%97%E7%9C%81%E9%95%BF%E6%B2%99%E5%B8%82&age=14&name=zhangsan&Time-Stamp=1732084303463&Secret-Key=db1b5214-02ee-497f-957c-88323b4351bf";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
from ck_assessment_record car
|
||||
left join enterprises_unit eu on car.enterprises_unit_id = eu.snow_flake_id and eu.delete_flag = 0
|
||||
left join ck_project cp on car.ck_project_id = cp.snow_flake_id and cp.delete_flag = 0
|
||||
left join mini_program_user mpu on mpu.identity = 'police' and car.create_by = mpu.snow_flake_id and mpu.delete_flag = 0
|
||||
left join police_unit pu on mpu.unit_id = pu.snow_flake_id and pu.delete_flag = 0
|
||||
left join mini_program_user mpu on mpu.identity = 'police' and car.create_by = mpu.snow_flake_id
|
||||
left join police_unit pu on mpu.unit_id = pu.snow_flake_id
|
||||
left join ck_assessment_record_details card on car.snow_flake_id = card.ck_assessment_record_id and card.delete_flag = 0
|
||||
left join ck_standard cs on card.ck_standard_id = cs.snow_flake_id
|
||||
where car.delete_flag = 0
|
||||
|
|
|
@ -47,6 +47,10 @@
|
|||
select
|
||||
eu.snow_flake_id as 'enterprisesUnitId',
|
||||
eu.name as 'enterprisesUnitName',
|
||||
eu.province,
|
||||
eu.city,
|
||||
eu.districts,
|
||||
eu.street,
|
||||
ad1.name as 'provinceName',
|
||||
ad2.name as 'cityName',
|
||||
ad3.name as 'districtsName',
|
||||
|
|
|
@ -19,7 +19,6 @@ const props = withDefaults(defineProps<MapContainerProps>(), {
|
|||
viewMode: "3D",
|
||||
// 初始化地图级别
|
||||
zoom: 11,
|
||||
mapStyle: 'amap://styles/darkblue'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -52,13 +52,6 @@ export const SYSTEM_MENUS: SystemMenu[] = [
|
|||
component: () => import('@/views/unitManage/securityUnit/index.vue')
|
||||
}
|
||||
]
|
||||
}, {
|
||||
title: '数据总览',
|
||||
name: 'dataOverview',
|
||||
path: '/dataOverview',
|
||||
type: 'menu',
|
||||
isFull: true,
|
||||
component: () => import('@/views/data/dataOverview.vue')
|
||||
}, {
|
||||
title: '开放平台',
|
||||
name: 'openPlatform',
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {EnterprisesUnit} from "@/types/views/data/dataOverview.ts";
|
||||
import {EnterprisesUnit} from "@/types/views/index.ts";
|
||||
|
||||
defineProps<EnterprisesUnit>()
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>警保联动数据总览</h1>
|
||||
</div>
|
||||
<MapContainer class="map-container" ref="mapRef" :init-callback="initMap">
|
||||
<div class="left-panel panel">
|
||||
<h2>左侧统计面板</h2>
|
||||
<!-- 添加你的统计数据 -->
|
||||
</div>
|
||||
<div class="right-panel panel">
|
||||
<h2>右侧统计面板</h2>
|
||||
<!-- 添加你的统计数据 -->
|
||||
</div>
|
||||
</MapContainer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import MapContainer from "@/components/aMap/MapContainer.vue";
|
||||
import {createApp, h, ref} from "vue";
|
||||
import {ComponentExposed} from "vue-component-type-helpers";
|
||||
import api from "@/axios";
|
||||
import EnterprisesUnitInfoWindowContent from "@/views/data/components/EnterprisesUnitInfoWindowContent.vue";
|
||||
import {EnterprisesUnit} from "@/types/views/data/dataOverview.ts";
|
||||
|
||||
const mapRef = ref<ComponentExposed<typeof MapContainer>>(null)
|
||||
|
||||
let infoWindow: AMap.InfoWindow = null;
|
||||
|
||||
const initMap = async () => {
|
||||
const {data} = await api.get<EnterprisesUnit[]>('/enterprisesUnit/mapPoint')
|
||||
mapRef.value?.mapInstance?.clearMap()
|
||||
const markers = data.map(item => {
|
||||
if (!item.point) {
|
||||
return null;
|
||||
}
|
||||
const marker = new AMap.Marker({
|
||||
icon: new AMap.Icon({
|
||||
image: __APP_ENV.VITE_APP_MINIO_URL + item.type.extData.icon,
|
||||
size: new AMap.Size(66, 66),
|
||||
imageSize: new AMap.Size(66, 66),
|
||||
}),
|
||||
position: item.point,
|
||||
offset: new AMap.Pixel(-33, -66)
|
||||
})
|
||||
marker.on('click', () => {
|
||||
if (!infoWindow) {
|
||||
infoWindow = new AMap.InfoWindow({
|
||||
isCustom: true,
|
||||
offset: new AMap.Pixel(66, -66),
|
||||
closeWhenClickMap: true
|
||||
});
|
||||
}
|
||||
const element = document.createElement('div')
|
||||
//h 渲染组件 跟vue一样的用法
|
||||
const _InfoWindow = h(EnterprisesUnitInfoWindowContent, item)
|
||||
const app = createApp(_InfoWindow)
|
||||
app.mount(element)
|
||||
infoWindow.setContent(element)
|
||||
infoWindow.open(mapRef.value?.mapInstance, item.point)
|
||||
})
|
||||
return marker
|
||||
}).filter(Boolean)
|
||||
mapRef.value.mapInstance.add(markers)
|
||||
mapRef.value.mapInstance.setFitView()
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
position: relative;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
color: #333;
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.map-container {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.panel {
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
padding: 20px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
position: absolute;
|
||||
top: 100px; /* 调整顶部距离以避免与标题重叠 */
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.left-panel {
|
||||
width: 15%;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.right-panel {
|
||||
width: 15%;
|
||||
right: 10px;
|
||||
}
|
||||
</style>
|
|
@ -1,13 +1,112 @@
|
|||
<template>
|
||||
<div>
|
||||
index页面
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>警保联动数据总览</h1>
|
||||
</div>
|
||||
<MapContainer class="map-container" ref="mapRef" :init-callback="initMap">
|
||||
<div class="left-panel panel">
|
||||
<h2>左侧统计面板</h2>
|
||||
<!-- 添加你的统计数据 -->
|
||||
</div>
|
||||
<div class="right-panel panel">
|
||||
<h2>右侧统计面板</h2>
|
||||
<!-- 添加你的统计数据 -->
|
||||
</div>
|
||||
</MapContainer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import MapContainer from "@/components/aMap/MapContainer.vue";
|
||||
import {createApp, h, ref} from "vue";
|
||||
import {ComponentExposed} from "vue-component-type-helpers";
|
||||
import api from "@/axios";
|
||||
import EnterprisesUnitInfoWindowContent from "@/views/components/EnterprisesUnitInfoWindowContent.vue";
|
||||
import {EnterprisesUnit} from "@/types/views/index.ts";
|
||||
|
||||
const mapRef = ref<ComponentExposed<typeof MapContainer>>(null)
|
||||
|
||||
let infoWindow: AMap.InfoWindow = null;
|
||||
|
||||
const initMap = async () => {
|
||||
const {data} = await api.get<EnterprisesUnit[]>('/super/index/mapPoint')
|
||||
mapRef.value?.mapInstance?.clearMap()
|
||||
const markers = data.map(item => {
|
||||
if (!item.point) {
|
||||
return null;
|
||||
}
|
||||
const marker = new AMap.Marker({
|
||||
icon: new AMap.Icon({
|
||||
image: __APP_ENV.VITE_APP_MINIO_URL + item.type.extData.icon,
|
||||
size: new AMap.Size(66, 66),
|
||||
imageSize: new AMap.Size(66, 66),
|
||||
}),
|
||||
position: item.point,
|
||||
offset: new AMap.Pixel(-33, -66)
|
||||
})
|
||||
marker.on('click', () => {
|
||||
if (!infoWindow) {
|
||||
infoWindow = new AMap.InfoWindow({
|
||||
isCustom: true,
|
||||
offset: new AMap.Pixel(66, -66),
|
||||
closeWhenClickMap: true
|
||||
});
|
||||
}
|
||||
const element = document.createElement('div')
|
||||
//h 渲染组件 跟vue一样的用法
|
||||
const _InfoWindow = h(EnterprisesUnitInfoWindowContent, item)
|
||||
const app = createApp(_InfoWindow)
|
||||
app.mount(element)
|
||||
infoWindow.setContent(element)
|
||||
infoWindow.open(mapRef.value?.mapInstance, item.point)
|
||||
})
|
||||
return marker
|
||||
}).filter(Boolean)
|
||||
mapRef.value.mapInstance.add(markers)
|
||||
mapRef.value.mapInstance.setFitView()
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
color: #333;
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.map-container {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.panel {
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
padding: 20px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
position: absolute;
|
||||
top: 100px; /* 调整顶部距离以避免与标题重叠 */
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.left-panel {
|
||||
width: 15%;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.right-panel {
|
||||
width: 15%;
|
||||
right: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -129,8 +129,8 @@ const a = () => {
|
|||
const secretKey = "db1b5214-02ee-497f-957c-88323b4351bf"
|
||||
const now = Date.now()
|
||||
const params = {
|
||||
code: 'SSP001',
|
||||
level: 5
|
||||
id: "1855852231820054528",
|
||||
type: 'ENTERPRISES_UNIT'
|
||||
}
|
||||
const sign = generatedSign(params, now, accessKey, secretKey)
|
||||
const headers2 = {
|
||||
|
|
Loading…
Reference in New Issue