diff --git a/core/core-backend/src/main/java/io/gisbi/application/module/controller/ModuleController.java b/core/core-backend/src/main/java/io/gisbi/application/module/controller/ModuleController.java index 95939c9..437a3c0 100644 --- a/core/core-backend/src/main/java/io/gisbi/application/module/controller/ModuleController.java +++ b/core/core-backend/src/main/java/io/gisbi/application/module/controller/ModuleController.java @@ -1,5 +1,6 @@ package io.gisbi.application.module.controller; +import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -14,7 +15,6 @@ import java.time.LocalDateTime; import java.util.List; import java.util.Map; - /** *

* 应用_系统模块 前端控制器 @@ -35,8 +35,8 @@ public class ModuleController { @GetMapping("/list") public ResponseResult page(@RequestParam String appId) { QueryWrapper wrapper = new QueryWrapper<>(); - wrapper.eq("app_id",appId); - wrapper.orderByAsc("pid","sort"); // 按编码倒序排列 + wrapper.eq("app_id", appId); + wrapper.orderByAsc("pid", "sort"); // 按编码倒序排列 List> list = moduleService.listMaps(wrapper); return ResponseResult.successData(list); } @@ -49,6 +49,35 @@ public class ModuleController { return ResponseResult.successData(moduleService.createModule(module)); } + // 复制模块 + @PostMapping("/copy/{id}") + public ResponseResult copy(@PathVariable String id) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(Module::getId, id); + Map moduleMap = moduleService.getMap(wrapper); + + if (moduleMap == null || moduleMap.isEmpty()) { + return ResponseResult.error("模块不存在"); + } + + try { + Module module = BeanUtil.toBean(moduleMap, Module.class); + module.setId(null); + module.setName(module.getName() + "(复制)"); + module.setCreateTime(LocalDateTime.now()); + module.setCreateBy(AuthUtils.getUser().getUserId().toString()); + + boolean result = moduleService.createModule(module); + if (result) { + return ResponseResult.success("模块复制成功"); + } else { + return ResponseResult.error("模块复制失败"); + } + } catch (Exception e) { + return ResponseResult.error("复制模块失败,请联系管理员"); + } + } + // 修改模块 @PostMapping("/update") public ResponseResult update(@RequestBody Module module) { @@ -64,7 +93,7 @@ public class ModuleController { // 获取模块详情 @GetMapping("/{id}") public ResponseResult getById(@PathVariable String id) { - Map moduleMap=null; + Map moduleMap = null; try { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Module::getId, id); @@ -77,8 +106,8 @@ public class ModuleController { // 新增:根据pid判断是否有子节点 @GetMapping("/checkHasChildren") - public boolean checkHasChildren(@RequestParam String appId,@RequestParam String pid) { - boolean hasChildren = moduleService.existsChildrenByPid(appId,pid); + public boolean checkHasChildren(@RequestParam String appId, @RequestParam String pid) { + boolean hasChildren = moduleService.existsChildrenByPid(appId, pid); return hasChildren; } } diff --git a/core/core-backend/src/main/java/io/gisbi/application/system/controller/MenuController.java b/core/core-backend/src/main/java/io/gisbi/application/system/controller/MenuController.java index b8d6038..713f343 100644 --- a/core/core-backend/src/main/java/io/gisbi/application/system/controller/MenuController.java +++ b/core/core-backend/src/main/java/io/gisbi/application/system/controller/MenuController.java @@ -47,6 +47,19 @@ public class MenuController { } } + /** + * 上移/下移菜单 + */ + @PostMapping("/changeOrder") + public ResponseResult changeOrder(@RequestParam String menuId, @RequestParam String direction) { + boolean result = menuService.changeOrder(menuId, direction); + if (result) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + /*********************************** * 用途说明:修改菜单及按钮根据ID * 参数说明 diff --git a/core/core-backend/src/main/java/io/gisbi/application/system/service/IMenuService.java b/core/core-backend/src/main/java/io/gisbi/application/system/service/IMenuService.java index 0e7d950..5bcb013 100644 --- a/core/core-backend/src/main/java/io/gisbi/application/system/service/IMenuService.java +++ b/core/core-backend/src/main/java/io/gisbi/application/system/service/IMenuService.java @@ -49,4 +49,7 @@ public interface IMenuService extends IService

{ * 返回值说明: 菜单结构树集合 ***********************************/ List> permissionAssignment(String appId ,String roleId); + + boolean changeOrder(String menuId, String direction); + } diff --git a/core/core-backend/src/main/java/io/gisbi/application/system/service/impl/MenuServiceImpl.java b/core/core-backend/src/main/java/io/gisbi/application/system/service/impl/MenuServiceImpl.java index f2c836a..c7f5459 100644 --- a/core/core-backend/src/main/java/io/gisbi/application/system/service/impl/MenuServiceImpl.java +++ b/core/core-backend/src/main/java/io/gisbi/application/system/service/impl/MenuServiceImpl.java @@ -214,6 +214,56 @@ public class MenuServiceImpl extends ServiceImpl implements IM return listTree; } + @Override + public boolean changeOrder(String menuId, String direction) { + Menu currentMenu = menuMapper.selectById(menuId); + if (currentMenu == null) { + return false; + } + + String parentId = currentMenu.getParentid(); + + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("parentid", parentId); + wrapper.orderByAsc("orderno"); + + List siblings = menuMapper.selectList(wrapper); + + int index = -1; + for (int i = 0; i < siblings.size(); i++) { + if (siblings.get(i).getId().equals(menuId)) { + index = i; + break; + } + } + + if ("up".equals(direction)) { + if (index > 0) { + swapOrder(siblings.get(index), siblings.get(index - 1)); + } else { + return false; // 已是第一个,无法上移 + } + } else if ("down".equals(direction)) { + if (index < siblings.size() - 1) { + swapOrder(siblings.get(index), siblings.get(index + 1)); + } else { + return false; // 已是最后一个,无法下移 + } + } else { + return false; // 方向错误 + } + return true; + } + + private void swapOrder(Menu m1, Menu m2) { + Integer temp = m1.getOrderno(); + m1.setOrderno(m2.getOrderno()); + m2.setOrderno(temp); + + menuMapper.updateById(m1); + menuMapper.updateById(m2); + } + /********************************** * 用途说明: 生成权菜单权限树 * 参数说明 sysMenus diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/server/StaticResourceServer.java b/core/core-backend/src/main/java/io/gisbi/visualization/server/StaticResourceServer.java index 7cf1a21..49fb8c0 100644 --- a/core/core-backend/src/main/java/io/gisbi/visualization/server/StaticResourceServer.java +++ b/core/core-backend/src/main/java/io/gisbi/visualization/server/StaticResourceServer.java @@ -34,7 +34,7 @@ import java.util.Map; @RequestMapping("/staticResource") public class StaticResourceServer implements StaticResourceApi { - @Value("${gisbi.path.static-resource:/opt/gisbi2.0/data/static-resource/}") + @Value("${gisbi.path.static-resource:E:/opt/gisbi2.0/data/static-resource/}") private String staticDir; @Override diff --git a/core/core-backend/src/main/resources/application.yml b/core/core-backend/src/main/resources/application.yml index f9a804a..4e513ed 100644 --- a/core/core-backend/src/main/resources/application.yml +++ b/core/core-backend/src/main/resources/application.yml @@ -36,9 +36,9 @@ logging: file: path: /opt/gisbi2.0/logs # sql日志生产环境注释掉 -mybatis-plus: - configuration: - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl +#mybatis-plus: +# configuration: +# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl quartz: enabled: true diff --git a/core/core-frontend/index.html b/core/core-frontend/index.html index 82a8495..2679d00 100644 --- a/core/core-frontend/index.html +++ b/core/core-frontend/index.html @@ -7,6 +7,8 @@ +
diff --git a/core/core-frontend/src/api/application/module.ts b/core/core-frontend/src/api/application/module.ts index 0cf321b..19d8800 100644 --- a/core/core-frontend/src/api/application/module.ts +++ b/core/core-frontend/src/api/application/module.ts @@ -13,4 +13,9 @@ export const moduleById = id => request.get({ url: '/application/module/'+id }) // request.get({ url: `/application/module/${id}` }) export const moduleDel = async id => - request.delete({ url: `/application/module/${id}` }) \ No newline at end of file + request.delete({ url: `/application/module/${id}` }) + export const moduleCopy = async id => + request.post({ url: `/application/module/copy/${id}` }) + + + \ No newline at end of file diff --git a/core/core-frontend/src/components/data-visualization/canvas/ComponentWrapper.vue b/core/core-frontend/src/components/data-visualization/canvas/ComponentWrapper.vue index 599c211..5fe8fa5 100644 --- a/core/core-frontend/src/components/data-visualization/canvas/ComponentWrapper.vue +++ b/core/core-frontend/src/components/data-visualization/canvas/ComponentWrapper.vue @@ -522,6 +522,7 @@ const updateFromMobile = (e, type) => { height: 100%; position: relative; background-size: 100% 100% !important; + padding: 0 !important; .wrapper-inner-adaptor { position: relative; transform-style: preserve-3d; diff --git a/core/core-frontend/src/components/data-visualization/canvas/Shape.vue b/core/core-frontend/src/components/data-visualization/canvas/Shape.vue index e094036..750bb22 100644 --- a/core/core-frontend/src/components/data-visualization/canvas/Shape.vue +++ b/core/core-frontend/src/components/data-visualization/canvas/Shape.vue @@ -1181,6 +1181,7 @@ onMounted(() => { height: 100%; position: relative; background-size: 100% 100% !important; + padding:0 !important; } .shape-selected { diff --git a/core/core-frontend/src/locales/en.ts b/core/core-frontend/src/locales/en.ts index 6f0a740..0ca238f 100644 --- a/core/core-frontend/src/locales/en.ts +++ b/core/core-frontend/src/locales/en.ts @@ -1881,6 +1881,7 @@ export default { map_style_fresh: 'Grass green', map_style_grey: 'Gray', map_style_blue: 'Indigo blue', + map_style_translate:'Satellite map', map_style_darkblue: 'Polar night blue', map_line_type: 'Type', type: 'Type', diff --git a/core/core-frontend/src/locales/tw.ts b/core/core-frontend/src/locales/tw.ts index 9bee08b..239a5b7 100644 --- a/core/core-frontend/src/locales/tw.ts +++ b/core/core-frontend/src/locales/tw.ts @@ -1833,6 +1833,7 @@ export default { map_style_fresh: '草色青', map_style_grey: '雅士灰', map_style_blue: '靛青藍', + map_style_translate:'衛星地圖', map_style_darkblue: '極夜藍', map_line_type: '類型', type: '類型', diff --git a/core/core-frontend/src/locales/zh-CN.ts b/core/core-frontend/src/locales/zh-CN.ts index b2f2758..86ef5b5 100644 --- a/core/core-frontend/src/locales/zh-CN.ts +++ b/core/core-frontend/src/locales/zh-CN.ts @@ -1838,6 +1838,7 @@ export default { map_style_fresh: '草色青', map_style_grey: '雅士灰', map_style_blue: '靛青蓝', + map_style_translate:'卫星地图', map_style_darkblue: '极夜蓝', map_line_type: '类型', type: '类型', diff --git a/core/core-frontend/src/style/index.less b/core/core-frontend/src/style/index.less index 468eebc..939e837 100644 --- a/core/core-frontend/src/style/index.less +++ b/core/core-frontend/src/style/index.less @@ -695,3 +695,51 @@ strong { .ed-checkbox__label:hover{ color: #fff ; } + + +.ed-select-dropdown__item.hover, .ed-select-dropdown__item:hover { + background-color: rgba(67, 67, 67, 1) !important; +} + +.ed-input.is-disabled .ed-input__wrapper{ + background-color: rgba(37, 38, 38, 1) !important; + box-shadow: 0 0 0 1px rgba(51, 51, 51, 0)inset; +} +.de-el-dropdown-menu .dimension li{ + color: #ffffff !important; +} +.de-el-dropdown-menu .dimension li:hover{ + background-color: rgba(67, 67, 67, 1)!important; +} +.de-el-dropdown-menu-fixed .de-panel{ + background-color: rgba(37, 38, 38, 1)!important; +} +.de-el-dropdown-menu-fixed .de-panel .mod-left{ + color: #ffffff !important; +} +.de-el-dropdown-menu-fixed .de-panel .right-top{ + color: #ffffff !important; +} +.de-el-dropdown-menu-fixed .de-panel .autochecker-list .right-checkbox__label{ + color: #ffffff !important; +} +.de-el-dropdown-menu-fixed .de-panel .right-top .right-btn{ + color: #ffffff !important; +} +.de-el-dropdown-menu-fixed .de-panel .right-top .right-btn{ + background-color: rgba(37, 38, 38, 0) !important; + border:1px solid rgba(67, 67, 67, 1) !important; +} +.de-el-dropdown-menu-manu{ + background-color: rgba(37, 38, 38, 1) !important; +} +.de-el-dropdown-menu-manu .text-area .input{ + background-color: rgba(37, 38, 38, 1) !important; + color: #ffffff !important; +} +.de-el-dropdown-menu-manu .text-area .text-area-btn{ + background-color: rgba(37, 38, 38, 0) !important; +} +.de-el-dropdown-menu-fixed .de-panel .mod-left .ed-input__wrapper{ + background-color: rgba(37, 38, 38, 0) !important; +} \ No newline at end of file diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/map/common.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/map/common.ts index e9de26b..660526d 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/map/common.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/map/common.ts @@ -63,6 +63,7 @@ export const gaodeMapStyleOptions = [ { name: t('chart.map_style_fresh'), value: 'fresh' }, { name: t('chart.map_style_grey'), value: 'grey' }, { name: t('chart.map_style_blue'), value: 'blue' }, + { name: t('chart.map_style_translate'), value: 'Satellite' }, { name: t('commons.custom'), value: 'custom' } ] diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/map/flow-map.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/map/flow-map.ts index 286d938..e53d3de 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/map/flow-map.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/map/flow-map.ts @@ -8,16 +8,12 @@ import { import { MAP_EDITOR_PROPERTY_INNER } from '@/views/chart/components/js/panel/charts/map/common' import { hexColorToRGBA, parseJson } from '@/views/chart/components/js/util' import { deepCopy } from '@/utils/utils' +import { GaodeMap } from '@antv/l7-maps' import { Scene } from '@antv/l7-scene' import { LineLayer } from '@antv/l7-layers' import { PointLayer } from '@antv/l7-layers' -import { - getMapCenter, - getMapScene, - getMapStyle, - mapRendered, - qqMapRendered -} from '@/views/chart/components/js/panel/common/common_antv' +import { mapRendered, mapRendering } from '@/views/chart/components/js/panel/common/common_antv' +import { DEFAULT_BASIC_STYLE } from '@/views/chart/components/editor/util/chart' const { t } = useI18n() /** @@ -92,16 +88,103 @@ export class FlowMap extends L7ChartView { const xAxisExt = deepCopy(chart.xAxisExt) const { basicStyle, misc } = deepCopy(parseJson(chart.customAttr)) + let center: [number, number] = [ + DEFAULT_BASIC_STYLE.mapCenter.longitude, + DEFAULT_BASIC_STYLE.mapCenter.latitude + ] + if (basicStyle.autoFit === false) { + center = [basicStyle.mapCenter.longitude, basicStyle.mapCenter.latitude] + } + let mapStyle = basicStyle.mapStyleUrl + if (basicStyle.mapStyle !== 'custom') { + mapStyle = `amap://styles/${basicStyle.mapStyle ? basicStyle.mapStyle : 'normal'}` + } const mapKey = await this.getMapKey() - const mapStyle = getMapStyle(mapKey, basicStyle) // 底层 const chartObj = drawOption.chartObj as unknown as L7Wrapper let scene = chartObj?.getScene() - - const center = getMapCenter(basicStyle) - scene = await getMapScene(chart, scene, container, mapKey, basicStyle, misc, mapStyle, center) - - this.configZoomButton(chart, scene, mapKey) + if(scene){ + if (scene.getLayers()?.length) { + await scene.removeAllLayer() + scene.setPitch(misc.mapPitch) + } + } + if (mapStyle.indexOf('Satellite') == -1) { + scene = new Scene({ + id: container, + logoVisible: false, + map: new GaodeMap({ + token: mapKey?.key ?? undefined, + style: mapStyle, + pitch: misc.mapPitch, + center, + zoom: basicStyle.autoFit === false ? basicStyle.zoomLevel : undefined, + showLabel: !(basicStyle.showLabel === false), + WebGLParams: { + preserveDrawingBuffer: true + } + }) + }) + }else{ + scene = new Scene({ + id: container, + logoVisible: false, + map: new GaodeMap({ + token: mapKey?.key ?? undefined, + style: mapStyle, + features: ['bg', 'road'], // 必须开启路网层 + plugin: ['AMap.TileLayer.Satellite'], // 显式声明卫星图层 + WebGLParams: { + preserveDrawingBuffer: true + } + }) + }) + } + // if (!scene) { + // scene = new Scene({ + // id: container, + // logoVisible: false, + // map: new GaodeMap({ + // token: mapKey?.key ?? undefined, + // style: mapStyle, + // pitch: misc.mapPitch, + // center: basicStyle.autoFit === false ? center : undefined, + // zoom: basicStyle.autoFit === false ? basicStyle.zoomLevel : undefined, + // showLabel: !(basicStyle.showLabel === false), + // WebGLParams: { + // preserveDrawingBuffer: true + // } + // }) + // }) + // } else { + // if (scene.getLayers()?.length) { + // await scene.removeAllLayer() + // scene.setPitch(misc.mapPitch) + // scene.setMapStyle(mapStyle) + // scene.map.showLabel = !(basicStyle.showLabel === false) + // } + // if (basicStyle.autoFit === false) { + // scene.setZoomAndCenter(basicStyle.zoomLevel, center) + // } + // } + mapRendering(container) + if (mapStyle.indexOf('Satellite') == -1) { + scene.once('loaded', () => { + mapRendered(container) + }) + } else { + scene.once('loaded', () => { + // 创建卫星图层实例 + const satelliteLayer = new AMap.TileLayer.Satellite() + // 与矢量图层叠加显示 + satelliteLayer.setMap(scene.map) + mapRendered(container) + }) + } + // scene.once('loaded', () => { + // mapRendered(container) + // }) + this.configZoomButton(chart, scene) if (xAxis?.length < 2 || xAxisExt?.length < 2) { return new L7Wrapper(scene, undefined) } @@ -112,11 +195,6 @@ export class FlowMap extends L7ChartView { configList[0].once('inited', () => { mapRendered(container) }) - for (let i = 0; i < configList.length; i++) { - configList[i].on('inited', () => { - qqMapRendered(scene) - }) - } return new L7Wrapper(scene, configList) } @@ -143,13 +221,13 @@ export class FlowMap extends L7ChartView { let lineWidthField = null const yAxis = deepCopy(chart.yAxis) if (yAxis.length > 0) { - lineWidthField = yAxis[0].gisbiName + lineWidthField = yAxis[0].dataeaseName } // 线条颜色 let lineColorField = null const yAxisExt = deepCopy(chart.yAxisExt) if (yAxisExt.length > 0) { - lineColorField = yAxisExt[0].gisbiName + lineColorField = yAxisExt[0].dataeaseName } const asteriskField = '*' const data = [] @@ -173,10 +251,10 @@ export class FlowMap extends L7ChartView { .source(data, { parser: { type: 'json', - x: xAxis[0].gisbiName, - y: xAxis[1].gisbiName, - x1: xAxisExt[0].gisbiName, - y1: xAxisExt[1].gisbiName + x: xAxis[0].dataeaseName, + y: xAxis[1].dataeaseName, + x1: xAxisExt[0].dataeaseName, + y1: xAxisExt[1].dataeaseName } }) .size(flowLineStyle.size) @@ -226,11 +304,11 @@ export class FlowMap extends L7ChartView { .source(chart.data?.tableRow, { parser: { type: 'json', - x: xAxis[0].gisbiName, - y: xAxis[1].gisbiName + x: xAxis[0].dataeaseName, + y: xAxis[1].dataeaseName } }) - .shape(flowMapStartName[0].gisbiName, args => { + .shape(flowMapStartName[0].dataeaseName, args => { if (has.has('from-' + args)) { return '' } @@ -254,11 +332,11 @@ export class FlowMap extends L7ChartView { .source(chart.data?.tableRow, { parser: { type: 'json', - x: xAxisExt[0].gisbiName, - y: xAxisExt[1].gisbiName + x: xAxisExt[0].dataeaseName, + y: xAxisExt[1].dataeaseName } }) - .shape(flowMapEndName[0].gisbiName, args => { + .shape(flowMapEndName[0].dataeaseName, args => { if (has.has('from-' + args) || has.has('to-' + args)) { return '' } @@ -287,8 +365,8 @@ export class FlowMap extends L7ChartView { .source(chart.data?.tableRow, { parser: { type: 'json', - x: xAxis[0].gisbiName, - y: xAxis[1].gisbiName + x: xAxis[0].dataeaseName, + y: xAxis[1].dataeaseName } }) .shape('circle') @@ -301,8 +379,8 @@ export class FlowMap extends L7ChartView { .source(chart.data?.tableRow, { parser: { type: 'json', - x: xAxisExt[0].gisbiName, - y: xAxisExt[1].gisbiName + x: xAxisExt[0].dataeaseName, + y: xAxisExt[1].dataeaseName } }) .shape('circle') diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/map/heat-map.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/map/heat-map.ts index e36ad9e..088db46 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/map/heat-map.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/map/heat-map.ts @@ -8,16 +8,11 @@ import { import { MAP_EDITOR_PROPERTY_INNER } from '@/views/chart/components/js/panel/charts/map/common' import { flow, parseJson } from '@/views/chart/components/js/util' import { deepCopy } from '@/utils/utils' +import { GaodeMap } from '@antv/l7-maps' import { Scene } from '@antv/l7-scene' import { HeatmapLayer } from '@antv/l7-layers' import { DEFAULT_BASIC_STYLE } from '@/views/chart/components/editor/util/chart' -import { - getMapCenter, - getMapScene, - getMapStyle, - mapRendered, - qqMapRendered -} from '@/views/chart/components/js/panel/common/common_antv' +import { mapRendered, mapRendering } from '@/views/chart/components/js/panel/common/common_antv' const { t } = useI18n() /** @@ -74,31 +69,94 @@ export class HeatMap extends L7ChartView { basicStyle = parseJson(chart.customAttr).basicStyle miscStyle = parseJson(chart.customAttr).misc } + let center: [number, number] = [ + DEFAULT_BASIC_STYLE.mapCenter.longitude, + DEFAULT_BASIC_STYLE.mapCenter.latitude + ] + if (basicStyle.autoFit === false) { + center = [basicStyle.mapCenter.longitude, basicStyle.mapCenter.latitude] + } + let mapStyle = basicStyle.mapStyleUrl + if (basicStyle.mapStyle !== 'custom') { + mapStyle = `amap://styles/${basicStyle.mapStyle ? basicStyle.mapStyle : 'normal'}` + } const mapKey = await this.getMapKey() - const mapStyle = getMapStyle(mapKey, basicStyle) // 底层 const chartObj = drawOption.chartObj as unknown as L7Wrapper let scene = chartObj?.getScene() - const center = getMapCenter(basicStyle) - scene = await getMapScene( - chart, - scene, - container, - mapKey, - basicStyle, - miscStyle, - mapStyle, - center - ) - this.configZoomButton(chart, scene, mapKey) + if(scene){ + if (scene.getLayers()?.length) { + await scene.removeAllLayer() + scene.setPitch(miscStyle.mapPitch) + } + } + + if (mapStyle.indexOf('Satellite') == -1) { + scene = new Scene({ + id: container, + logoVisible: false, + map: new GaodeMap({ + token: mapKey?.key ?? undefined, + style: mapStyle, + pitch: miscStyle.mapPitch, + center, + zoom: basicStyle.autoFit === false ? basicStyle.zoomLevel : undefined, + showLabel: !(basicStyle.showLabel === false), + WebGLParams: { + preserveDrawingBuffer: true + } + }) + }) + } else { + scene = new Scene({ + id: container, + logoVisible: false, + map: new GaodeMap({ + token: mapKey?.key ?? undefined, + style: mapStyle, + features: ['bg', 'road'], // 必须开启路网层 + plugin: ['AMap.TileLayer.Satellite'], // 显式声明卫星图层 + WebGLParams: { + preserveDrawingBuffer: true + } + }) + }) + } + + // } else { + // // if (scene.getLayers()?.length) { + // await scene.removeAllLayer() + // scene.setPitch(miscStyle.mapPitch) + // scene.setMapStyle(mapStyle) + // scene.map.showLabel = !(basicStyle.showLabel === false) + // if (basicStyle.autoFit === false) { + // scene.setZoomAndCenter(basicStyle.zoomLevel, center) + // } + // // } + // } + mapRendering(container) + if (mapStyle.indexOf('Satellite') == -1) { + scene.once('loaded', () => { + mapRendered(container) + }) + } else { + scene.once('loaded', () => { + // 创建卫星图层实例 + const satelliteLayer = new AMap.TileLayer.Satellite() + // 与矢量图层叠加显示 + satelliteLayer.setMap(scene.map) + mapRendered(container) + }) + } + + this.configZoomButton(chart, scene) if (xAxis?.length < 2 || yAxis?.length < 1) { return new L7Wrapper(scene, undefined) } const config: L7Config = new HeatmapLayer({ name: 'line', blend: 'normal', - autoFit: !(basicStyle.autoFit === false), - zIndex: 10 + autoFit: !(basicStyle.autoFit === false) }) .source(chart.data?.data, { parser: { @@ -119,13 +177,6 @@ export class HeatMap extends L7ChartView { } }) - config.once('inited', () => { - mapRendered(container) - }) - config.on('inited', () => { - qqMapRendered(scene) - }) - return new L7Wrapper(scene, config) } diff --git a/core/core-frontend/src/views/chart/components/views/components/ChartComponentG2Plot.vue b/core/core-frontend/src/views/chart/components/views/components/ChartComponentG2Plot.vue index 3a02ffe..1a953c9 100644 --- a/core/core-frontend/src/views/chart/components/views/components/ChartComponentG2Plot.vue +++ b/core/core-frontend/src/views/chart/components/views/components/ChartComponentG2Plot.vue @@ -14,11 +14,12 @@ import { ChartLibraryType } from '@/views/chart/components/js/panel/types' import { G2PlotChartView } from '@/views/chart/components/js/panel/types/impl/g2plot' import { L7PlotChartView } from '@/views/chart/components/js/panel/types/impl/l7plot' import chartViewManager from '@/views/chart/components/js/panel' +import { useAppStoreWithOut } from '@/store/modules/app' import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain' import ViewTrackBar from '@/components/visualization/ViewTrackBar.vue' import { storeToRefs } from 'pinia' import { parseJson } from '@/views/chart/components/js/util' -import { defaultsDeep, cloneDeep, concat } from 'lodash-es' +import { defaultsDeep, cloneDeep } from 'lodash-es' import ChartError from '@/views/chart/components/views/components/ChartError.vue' import { BASE_VIEW_CONFIG } from '../../editor/util/chart' import { customAttrTrans, customStyleTrans, recursionTransObj } from '@/utils/canvasStyle' @@ -27,8 +28,8 @@ import { isDashboard, trackBarStyleCheck } from '@/utils/canvasUtils' import { useEmitt } from '@/hooks/web/useEmitt' import { L7ChartView } from '@/views/chart/components/js/panel/types/impl/l7' import { useI18n } from '@/hooks/web/useI18n' -import { ExportImage } from '@antv/l7' -import { configEmptyDataStyle } from '@/views/chart/components/js/panel/common/common_antv' +import { ExportImage, Scale, Fullscreen, Control, Scene, TileLayer } from '@antv/l7' +import { GaodeMap } from '@antv/l7-maps'; const { t } = useI18n() const dvMainStore = dvMainStoreWithOut() const { nowPanelTrackInfo, nowPanelJumpInfo, mobileInPc, embeddedCallBack, inMobile } = @@ -75,11 +76,6 @@ const props = defineProps({ type: String, required: false, default: 'inherit' - }, - active: { - type: Boolean, - required: false, - default: true } }) @@ -94,14 +90,6 @@ const emit = defineEmits([ const g2TypeSeries1 = ['bidirectional-bar'] const g2TypeSeries0 = ['bar-range'] const g2TypeTree = ['circle-packing'] -const g2TypeStack = [ - 'bar-stack', - 'bar-group-stack', - 'percentage-bar-stack', - 'bar-stack-horizontal', - 'percentage-bar-stack-horizontal' -] -const g2TypeGroup = ['bar-group'] const { view, showPosition, scale, terminal, suffixId } = toRefs(props) @@ -124,7 +112,8 @@ const state = reactive({ }, linkageActiveParam: null, pointParam: null, - data: { fields: [] } // 图表数据 + data: { fields: [] }, // 图表数据 + satelliteVisible: false, // 新增卫星图层状态 }) let chartData = shallowRef>({ fields: [] @@ -145,10 +134,7 @@ const clearLinkage = () => { } const reDrawView = () => { linkageActiveHistory.value = false - const slider = myChart?.chart?.getController('slider') - if (!slider) { - myChart?.render() - } + myChart?.render() } const linkageActivePre = () => { if (linkageActiveHistory.value) { @@ -160,103 +146,43 @@ const linkageActivePre = () => { } const linkageActive = () => { linkageActiveHistory.value = true - myChart?.setState('active', () => true, false) - myChart?.setState('inactive', () => true, false) - myChart?.setState('selected', () => true, false) myChart?.setState('active', param => { if (Array.isArray(param)) { return false } else { - return checkSelected(param) + if (checkSelected(param)) { + return true + } } }) myChart?.setState('inactive', param => { if (Array.isArray(param)) { return false } else { - return !checkSelected(param) - } - }) - myChart?.setState('selected', param => { - if (Array.isArray(param)) { - return false - } else { - return checkSelected(param) + if (!checkSelected(param)) { + return true + } } }) } const checkSelected = param => { - // 获取当前视图的所有联动字段ID - const mappingFieldIds = Array.from( - new Set( - (view.value.type.includes('chart-mix') - ? concat(chartData.value?.left?.fields, chartData.value?.right?.fields) - : chartData.value?.fields - ) - .map(item => item?.id) - .filter(id => - Object.keys(nowPanelTrackInfo.value).some( - key => key.startsWith(view.value.id) && key.split('#')[1] === id - ) - ) - ) - ) - // 维度字段匹配 - const [xAxis, xAxisExt, extStack] = ['xAxis', 'xAxisExt', 'extStack'].map(key => - view.value[key].find(item => mappingFieldIds.includes(item.id)) - ) - // 选中字段数据 - const { group, name, category } = state.linkageActiveParam - // 选中字段数据匹配 if (g2TypeSeries1.includes(view.value.type)) { - return name === param.field + return state.linkageActiveParam.name === param.field } else if (g2TypeSeries0.includes(view.value.type)) { - return category === param.category + return state.linkageActiveParam.category === param.category } else if (g2TypeTree.includes(view.value.type)) { - if (param.path?.startsWith(name) || name === t('commons.all')) { + if ( + param.path?.startsWith(state.linkageActiveParam.name) || + state.linkageActiveParam.name === t('commons.all') + ) { return true } - return name === param.name - } else if (g2TypeGroup.includes(view.value.type)) { - const isNameMatch = name === param.name || (name === 'NO_DATA' && !param.name) - const isCategoryMatch = category === param.category - if (xAxis && xAxisExt) { - return isNameMatch && isCategoryMatch - } - if (xAxis && !xAxisExt) { - return isNameMatch - } - if (!xAxis && xAxisExt) { - return isCategoryMatch - } - return false - } else if (g2TypeStack.includes(view.value.type)) { - const isGroupMatch = group === param.group || (group === 'NO_DATA' && !param.group) - const isNameMatch = name === param.name || (name === 'NO_DATA' && !param.name) - const isCategoryMatch = category === param.category - // 全部匹配 - if (xAxis && xAxisExt && extStack) { - return isNameMatch && isGroupMatch && isCategoryMatch - } - // 只匹配到维度 - if (xAxis && !xAxisExt && !extStack) { - return isNameMatch - } else if (!xAxis && xAxisExt && !extStack) { - return isGroupMatch - } else if (!xAxis && !xAxisExt && extStack) { - return isCategoryMatch - } else if (xAxis && xAxisExt && !extStack) { - return isNameMatch && isGroupMatch - } else if (xAxis && !xAxisExt && extStack) { - return isNameMatch && isCategoryMatch - } else if (!xAxis && xAxisExt && extStack) { - return isGroupMatch && isCategoryMatch - } else { - return false - } + return state.linkageActiveParam.name === param.name } else { return ( - (name === param.name || (name === 'NO_DATA' && !param.name)) && category === param.category + (state.linkageActiveParam.name === param.name || + (state.linkageActiveParam.name === 'NO_DATA' && !param.name)) && + state.linkageActiveParam.category === param.category ) } } @@ -350,8 +276,6 @@ const renderG2Plot = async (chart, chartView: G2PlotChartView) => { g2Timer && clearTimeout(g2Timer) g2Timer = setTimeout(async () => { try { - // 在这里清理掉之前图表的空dom - configEmptyDataStyle([1], containerId) myChart?.destroy() myChart = await chartView.drawChart({ chartObj: myChart, @@ -373,6 +297,7 @@ const renderG2Plot = async (chart, chartView: G2PlotChartView) => { const dynamicAreaId = ref('') const country = ref('') +const appStore = useAppStoreWithOut() const chartContainer = ref(null) let scope let mapTimer: number @@ -409,21 +334,101 @@ const renderL7Plot = async (chart: ChartObj, chartView: L7PlotChartView, callback) => { - mapL7Timer && clearTimeout(mapL7Timer) + mapL7Timer && clearTimeout(mapL7Timer); mapL7Timer = setTimeout(async () => { myChart = await chartView.drawChart({ chartObj: myChart, container: containerId, chart: chart, action - }) - myChart?.render() - callback?.() - emit('resetLoading') - }, 500) -} + }); + // 清除已有比例尺 + if (!scaleControl) { + scaleControl = new Scale({ + position: 'bottomleft', + imperial: false + }); + myChart.getScene()?.addControl(scaleControl); + } + + // 创建并添加新比例尺 + + + // 添加全屏控件 + if (fullscreenControl) { + + } else { + fullscreenControl = new Fullscreen({ + position: 'bottomright', + }); + myChart.getScene()?.addControl(fullscreenControl, 'bottomright'); + } + + + // ====== 使用高德地图原生API实现卫星图层切换 ====== + let satelliteLayer: any = null; + let isSatelliteVisible = false; + + class SatelliteControl extends Control { + protected onAdd() { + const btn = document.createElement('button'); + btn.className = 'l7-control-button l7-satellite-control'; + btn.innerHTML = '卫星'; + // btn.title = '切换到卫星视图'; + btn.style.backgroundColor = '#000'; + btn.style.color = '#fff'; + btn.style.padding = '2px'; + btn.style.borderRadius = '4px'; + btn.style.cursor = 'pointer' + btn.style.fontSize = '11px'; + const scene = myChart.getScene() + // 确保地图加载完成 + scene.on('loaded', () => { + // 创建高德卫星图层 + satelliteLayer = new window.AMap.TileLayer.Satellite(); + btn.onclick = () => { + isSatelliteVisible = !isSatelliteVisible; + + if (isSatelliteVisible) { + // 使用 scene.addLayer 方法添加卫星图层 + btn.style.backgroundColor = '#409eff'; + scene.map.add(satelliteLayer) + } else { + // 使用 scene.removeLayer 方法移除卫星图层 + btn.style.backgroundColor = '#000'; + scene.map.remove(satelliteLayer) + + } + }; + }); + + return btn; + } + } + + // 添加控件到地图 + // 移除之前的卫星控件(如果存在) + if (satelliteControlInstance) { + + } else { + // 添加新的卫星控件到地图 + satelliteControlInstance = new SatelliteControl({ position: 'bottomright' }); + myChart.getScene()?.addControl(satelliteControlInstance); + } + + + // ====== 修复完成 ====== + + myChart?.render(); + callback?.(); + emit('resetLoading'); + }, 500); +}; const pointClickTrans = () => { if (embeddedCallBack.value === 'yes') { trackClick('pointClick') @@ -437,8 +442,11 @@ const actionDefault = param => { if (param.from === 'word-cloud') { emitter.emit('word-cloud-default-data-range', param) } - if (param.from === 'gauge' || param.from === 'liquid') { - emitter.emit('gauge-liquid-y-value', param) + if (param.from === 'gauge') { + emitter.emit('gauge-default-data', param) + } + if (param.from === 'liquid') { + emitter.emit('liquid-default-data', param) } } @@ -458,8 +466,7 @@ const action = param => { // 下钻 联动 跳转 state.linkageActiveParam = { category: state.pointParam.data.category ? state.pointParam.data.category : 'NO_DATA', - name: state.pointParam.data.name ? state.pointParam.data.name : 'NO_DATA', - group: state.pointParam.data.group ? state.pointParam.data.group : 'NO_DATA' + name: state.pointParam.data.name ? state.pointParam.data.name : 'NO_DATA' } if (trackMenu.value.length < 2) { // 只有一个事件直接调用 @@ -489,7 +496,7 @@ const action = param => { state.trackBarStyle.top = trackBarY + 'px' } - viewTrack.value.trackButtonClick(view.value.id) + viewTrack.value.trackButtonClick() } } @@ -498,28 +505,10 @@ const trackClick = trackAction => { if (!param?.data?.dimensionList) { return } - let checkName = undefined - if (param.data.dimensionList.length > 1) { - // 分组堆叠处理 去能比较出来值的那个维度 - if (view.value.type === 'bar-group-stack') { - const length = param.data.dimensionList.length - // 存在最后一个id - if (param.data.dimensionList[length - 1].id === param.data.dimensionList[length - 2].id) { - param.data.dimensionList.pop() - } - param.data.dimensionList.forEach(dimension => { - if (dimension.value === param.data.category) { - checkName = dimension.id - } - }) - } - if (!checkName) { - // 对多维度的处理 取第一个 - checkName = param.data.dimensionList[0].id - } - } - if (!checkName) { - checkName = param.data.name + let checkName = state.pointParam.data.name + // 对多维度的处理 取第一个 + if (state.pointParam.data.dimensionList.length > 1) { + checkName = state.pointParam.data.dimensionList[0].id } // 跳转字段处理 let jumpName = state.pointParam.data.name @@ -558,7 +547,7 @@ const trackClick = trackAction => { } } let quotaList = state.pointParam.data.quotaList - if (['bar-range', 'bullet-graph'].includes(curView.type)) { + if (['bar-range'].includes(curView.type)) { quotaList = state.pointParam.data.dimensionList } else { quotaList[0]['value'] = state.pointParam.data.value @@ -613,38 +602,37 @@ const trackMenu = computed(() => { let trackMenuInfo = [] // 复用、放大状态的仪表板不进行联动、跳转和下钻的动作 if (!['multiplexing', 'viewDialog'].includes(showPosition.value)) { - let drillFields = - curView?.drill && curView?.drillFilters?.length - ? curView.drillFilters.map(item => item.fieldId) - : [] let linkageCount = 0 let jumpCount = 0 if (curView?.type?.includes('chart-mix')) { - Array.of('left', 'right').forEach(side => { - chartData.value?.[side]?.fields - ?.filter(item => !drillFields.includes(item.id)) - .forEach(item => { - const sourceInfo = view.value.id + '#' + item.id - if (nowPanelTrackInfo.value[sourceInfo]) { - linkageCount++ - } - if (nowPanelJumpInfo.value[sourceInfo]) { - jumpCount++ - } - }) + chartData.value?.left?.fields?.forEach(item => { + const sourceInfo = view.value.id + '#' + item.id + if (nowPanelTrackInfo.value[sourceInfo]) { + linkageCount++ + } + if (nowPanelJumpInfo.value[sourceInfo]) { + jumpCount++ + } + }) + chartData.value?.right?.fields?.forEach(item => { + const sourceInfo = view.value.id + '#' + item.id + if (nowPanelTrackInfo.value[sourceInfo]) { + linkageCount++ + } + if (nowPanelJumpInfo.value[sourceInfo]) { + jumpCount++ + } }) } else { - chartData.value?.fields - ?.filter(item => !drillFields.includes(item.id)) - .forEach(item => { - const sourceInfo = view.value.id + '#' + item.id - if (nowPanelTrackInfo.value[sourceInfo]) { - linkageCount++ - } - if (nowPanelJumpInfo.value[sourceInfo]) { - jumpCount++ - } - }) + chartData.value?.fields?.forEach(item => { + const sourceInfo = view.value.id + '#' + item.id + if (nowPanelTrackInfo.value[sourceInfo]) { + linkageCount++ + } + if (nowPanelJumpInfo.value[sourceInfo]) { + jumpCount++ + } + }) } jumpCount && view.value?.jumpActive && @@ -694,7 +682,7 @@ const canvas2Picture = (pictureData, online) => { mapDom.appendChild(imgDom) } const preparePicture = id => { - if (id !== curView?.id) { + if (id !== curView.id) { return } const chartView = chartViewManager.getChartView(curView.render, curView.type) @@ -718,7 +706,7 @@ const preparePicture = id => { } } const unPreparePicture = id => { - if (id !== curView?.id) { + if (id !== curView.id) { return } const chartView = chartViewManager.getChartView(curView.render, curView.type) @@ -746,7 +734,6 @@ defineExpose({ trackMenu, clearLinkage }) -let intersectionObserver let resizeObserver const TOLERANCE = 0.01 const RESIZE_MONITOR_CHARTS = ['map', 'bubble-map', 'flow-map', 'heat-map'] @@ -771,32 +758,13 @@ onMounted(() => { preSize[1] = size.blockSize }) resizeObserver.observe(containerDom) - intersectionObserver = new IntersectionObserver(([entry]) => { - if (RESIZE_MONITOR_CHARTS.includes(view.value.type)) { - return - } - if (entry.intersectionRatio <= 0) { - myChart?.emit('tooltip:hidden') - } - }) - intersectionObserver.observe(containerDom) useEmitt({ name: 'l7-prepare-picture', callback: preparePicture }) useEmitt({ name: 'l7-unprepare-picture', callback: unPreparePicture }) }) -const MAP_CHARTS = ['map', 'bubble-map', 'flow-map', 'heat-map', 'symbolic-map'] -const onWheel = (e: WheelEvent) => { - if (!MAP_CHARTS.includes(view.value.type)) { - return - } - if (!props.active) { - e.stopPropagation() - } -} onBeforeUnmount(() => { try { myChart?.destroy() resizeObserver?.disconnect() - intersectionObserver?.disconnect() } catch (e) { console.warn(e) } @@ -805,22 +773,9 @@ onBeforeUnmount(() => { @@ -831,12 +786,32 @@ onBeforeUnmount(() => { width: 100%; height: 100%; z-index: 0; + .canvas-content { width: 100% !important; height: 100% !important; + :deep(.g2-tooltip) { position: fixed !important; } } } - + +:deep(.l7-button-control) { + background-color: #000000 !important; +} + +:deep(.l7-button-control:not(:disabled):hover) { + background-color: #000000d5 !important; +} + +:deep(.l7-button-control .l7-iconfont) { + fill: #fff !important; + color: #fff !important; +} + +// :deep(.l7-control-container .l7-top) { +// top: auto !important; +// bottom: 133px !important; + +// } diff --git a/core/core-frontend/src/views/visualized/data/dataset/form/UnionItemEdit.vue b/core/core-frontend/src/views/visualized/data/dataset/form/UnionItemEdit.vue index aa92d98..12e30df 100644 --- a/core/core-frontend/src/views/visualized/data/dataset/form/UnionItemEdit.vue +++ b/core/core-frontend/src/views/visualized/data/dataset/form/UnionItemEdit.vue @@ -194,7 +194,7 @@ init()