From eb451187ff2115f2090ae7b6376a5e11329644ed Mon Sep 17 00:00:00 2001 From: weitang Date: Mon, 30 Jun 2025 09:13:32 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix:=E4=BC=98=E5=8C=96=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=20=E6=B3=A8=E9=87=8A=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E7=BA=BF=E4=B8=8A=E7=9A=84=E6=A8=A1=E6=9D=BF=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/controller/MenuController.java | 13 +++ .../system/service/IMenuService.java | 3 + .../system/service/impl/MenuServiceImpl.java | 31 ++++++ .../template/manage/TemplateCenterManage.java | 104 +++++++++++------- .../service/TemplateMarketService.java | 6 +- .../gisbi/api/template/TemplateMarketApi.java | 2 +- 6 files changed, 118 insertions(+), 41 deletions(-) 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 713f343..e76fca7 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 @@ -60,6 +60,19 @@ public class MenuController { } } + /** + * 移动菜单到指定父级 + */ + @PostMapping("/moveMenu") + public ResponseResult moveMenu(@RequestParam String menuId, @RequestParam String targetParentId) { + boolean result = menuService.moveMenu(menuId, targetParentId); + 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 5bcb013..d737b5e 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 @@ -52,4 +52,7 @@ public interface IMenuService extends IService { boolean changeOrder(String menuId, String direction); + boolean moveMenu(String menuId, String targetParentId); + + } 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 c7f5459..b0d8857 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 @@ -1,5 +1,6 @@ package io.gisbi.application.system.service.impl; +import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -255,6 +256,36 @@ public class MenuServiceImpl extends ServiceImpl implements IM return true; } + @Override + public boolean moveMenu(String menuId, String targetParentId) { + Menu menu = menuMapper.selectById(menuId); + if (menu == null) { + return false; + } + // 更新父级ID + menu.setParentid(targetParentId); + + // 获取新父级下的最大序号 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("parentid", targetParentId); + wrapper.select("orderno","code"); + wrapper.orderByDesc("orderno"); + List list = menuMapper.selectList(wrapper); + if (list.isEmpty()) { + return false; + } + Integer maxOrderNo = list.getFirst().getOrderno(); + // 设置新的序号为最大值+1 + menu.setOrderno(maxOrderNo == null ? 1 : maxOrderNo + 1); + // 设置移动过后的菜单code + + + // 更新菜单信息 + return menuMapper.updateById(menu) > 0; + } + + + private void swapOrder(Menu m1, Menu m2) { Integer temp = m1.getOrderno(); m1.setOrderno(m2.getOrderno()); diff --git a/core/core-backend/src/main/java/io/gisbi/template/manage/TemplateCenterManage.java b/core/core-backend/src/main/java/io/gisbi/template/manage/TemplateCenterManage.java index a37c6ed..525d8b0 100644 --- a/core/core-backend/src/main/java/io/gisbi/template/manage/TemplateCenterManage.java +++ b/core/core-backend/src/main/java/io/gisbi/template/manage/TemplateCenterManage.java @@ -37,7 +37,9 @@ import java.util.stream.Collectors; */ @Service public class TemplateCenterManage { - private final static String POSTS_API_V2 = "/apis/api.store.halo.run/v1alpha1/applications?keyword=&priceMode=&sort=latestReleaseTimestamp%2Cdesc&type=THEME&deVersion=V2&templateType=&label=&page=1&size=2000"; + + private final static String POSTS_API_V2 = "/apis/api.store.halo.run/v1alpha1/applications?keyword=&priceMode" + + "=&sort=latestReleaseTimestamp%2Cdesc&type=THEME&deVersion=V2&templateType=&label=&page=1&size=2000"; private final static String TEMPLATE_META_DATA_URL = "/upload/meta_data.json"; private final static String TEMPLATE_BASE_INFO_URL = "/apis/api.store.halo.run/v1alpha1/applications/"; @Resource @@ -59,7 +61,8 @@ public class TemplateCenterManage { public TemplateManageFileDTO getTemplateFromMarket(String templateUrl) { if (StringUtils.isNotEmpty(templateUrl)) { String templateName = templateUrl.substring(templateUrl.lastIndexOf("/") + 1, templateUrl.length()); - templateUrl = templateUrl.replace(templateName, URLEncoder.encode(templateName, StandardCharsets.UTF_8).replace("+", "%20")); + templateUrl = templateUrl.replace(templateName, + URLEncoder.encode(templateName, StandardCharsets.UTF_8).replace("+", "%20")); String sufUrl = sysParameterManage.groupVal("template.").get("template.url"); String templateInfo = HttpClientUtil.get(sufUrl + templateUrl, null); return JsonUtil.parseObject(templateInfo, TemplateManageFileDTO.class); @@ -75,7 +78,8 @@ public class TemplateCenterManage { if (StringUtils.isNotEmpty(templateName)) { String sufUrl = sysParameterManage.groupVal("template.").get("template.url"); String templateBaseInfo = HttpClientUtil.get(sufUrl + TEMPLATE_BASE_INFO_URL + templateName, null); - MarketTemplateV2ItemResult baseItemInfo = JsonUtil.parseObject(templateBaseInfo, MarketTemplateV2ItemResult.class); + MarketTemplateV2ItemResult baseItemInfo = JsonUtil.parseObject(templateBaseInfo, + MarketTemplateV2ItemResult.class); String templateUrl = ""; if (baseItemInfo.getLatestRelease() != null) { templateUrl = sufUrl + "/store/apps/" + templateName + @@ -117,10 +121,15 @@ public class TemplateCenterManage { } } - public MarketBaseResponse searchTemplate() { + public MarketBaseResponse searchTemplate(String offline) { try { Map templateParams = sysParameterManage.groupVal("template."); - return baseResponseV2Trans(templateQuery(templateParams), searchTemplateFromManage(), templateParams.get("template.url")); + MarketTemplateV2BaseResponse marketTemplateV2BaseResponse = null; + if (StringUtils.isNotEmpty(offline) && "0".equals(offline)) { + marketTemplateV2BaseResponse = templateQuery(templateParams); + } + return baseResponseV2Trans(marketTemplateV2BaseResponse, searchTemplateFromManage(), templateParams.get( + "template.url")); } catch (Exception e) { LogUtil.error(e); e.printStackTrace(); @@ -141,13 +150,15 @@ public class TemplateCenterManage { return null; } - private List baseManage2MarketTrans(List manageResult, Map categoryMap) { + private List baseManage2MarketTrans(List manageResult, + Map categoryMap) { List result = new ArrayList<>(); manageResult.stream().forEach(templateManageDTO -> { templateManageDTO.setCategoryName(categoryMap.get(templateManageDTO.getPid())); List categories = templateManageDTO.getCategories(); if (!CollectionUtils.isEmpty(categories)) { - List categoryNames = categories.stream().map(categoryId -> categoryMap.get(categoryId)).collect(Collectors.toList()); + List categoryNames = + categories.stream().map(categoryId -> categoryMap.get(categoryId)).collect(Collectors.toList()); templateManageDTO.setCategoryNames(categoryNames); result.add(new TemplateMarketDTO(templateManageDTO)); } @@ -155,7 +166,6 @@ public class TemplateCenterManage { return result; } - public MarketBaseResponse searchTemplateRecommend() { MarketTemplateV2BaseResponse v2BaseResponse = null; Map templateParams = sysParameterManage.groupVal("template."); @@ -170,21 +180,25 @@ public class TemplateCenterManage { return baseResponseV2TransRecommend(v2BaseResponse, manage, templateParams.get("template.url")); } - public MarketPreviewBaseResponse searchTemplatePreview() { + public MarketPreviewBaseResponse searchTemplatePreview(String offline) { try { - MarketBaseResponse baseContentRsp = searchTemplate(); - List categories = baseContentRsp.getCategories().stream().filter(category -> !Translator.get("i18n_template_recent").equals(category.getLabel())).toList(); + MarketBaseResponse baseContentRsp = searchTemplate(offline); + List categories = + baseContentRsp.getCategories().stream().filter(category -> !Translator.get("i18n_template_recent").equals(category.getLabel())).toList(); List contents = baseContentRsp.getContents(); List previewContents = new ArrayList<>(); categories.forEach(category -> { if (Translator.get("i18n_template_recommend").equals(category.getLabel())) { - previewContents.add(new TemplateMarketPreviewInfoDTO(category, contents.stream().filter(template -> "Y".equals(template.getSuggest())).collect(Collectors.toList()))); + previewContents.add(new TemplateMarketPreviewInfoDTO(category, + contents.stream().filter(template -> "Y".equals(template.getSuggest())).collect(Collectors.toList()))); } else { - previewContents.add(new TemplateMarketPreviewInfoDTO(category, contents.stream().filter(template -> checkCategoryMatch(template, category.getLabel())).collect(Collectors.toList()))); + previewContents.add(new TemplateMarketPreviewInfoDTO(category, + contents.stream().filter(template -> checkCategoryMatch(template, category.getLabel())).collect(Collectors.toList()))); } }); - return new MarketPreviewBaseResponse(baseContentRsp.getBaseUrl(), categories.stream().map(MarketMetaDataVO::getLabel) - .collect(Collectors.toList()), previewContents); + return new MarketPreviewBaseResponse(baseContentRsp.getBaseUrl(), + categories.stream().map(MarketMetaDataVO::getLabel) + .collect(Collectors.toList()), previewContents); } catch (Exception e) { LogUtil.error(e); } @@ -201,9 +215,11 @@ public class TemplateCenterManage { } } - private MarketBaseResponse baseResponseV2TransRecommend(MarketTemplateV2BaseResponse v2BaseResponse, List templateManages, String url) { + private MarketBaseResponse baseResponseV2TransRecommend(MarketTemplateV2BaseResponse v2BaseResponse, + List templateManages, String url) { Map useTime = coreOptRecentManage.findTemplateRecentUseTime(); - List categoryVO = getCategoriesV2().stream().filter(node -> !"全部".equalsIgnoreCase(node.getLabel())).collect(Collectors.toList()); + List categoryVO = + getCategoriesV2().stream().filter(node -> !"全部".equalsIgnoreCase(node.getLabel())).collect(Collectors.toList()); Map categoriesMap = categoryVO.stream() .collect(Collectors.toMap(MarketMetaDataVO::getSlug, MarketMetaDataVO::getLabel)); List contents = new ArrayList<>(); @@ -212,7 +228,10 @@ public class TemplateCenterManage { MarketApplicationSpecVO spec = marketTemplateV2ItemResult.getApplication().getSpec(); MarketApplicationMetaDataVO metadata = marketTemplateV2ItemResult.getApplication().getMetadata(); if ("Y".equalsIgnoreCase(spec.getSuggest())) { - contents.add(new TemplateMarketDTO(metadata.getName(), spec.getDisplayName(), spec.getScreenshots().get(0).getUrl(), spec.getLinks().get(0).getUrl(), categoriesMap.get(spec.getLabel()), spec.getTemplateType(), useTime.get(spec.getReadmeName()), "Y", spec.getTemplateClassification())); + contents.add(new TemplateMarketDTO(metadata.getName(), spec.getDisplayName(), + spec.getScreenshots().get(0).getUrl(), spec.getLinks().get(0).getUrl(), + categoriesMap.get(spec.getLabel()), spec.getTemplateType(), + useTime.get(spec.getReadmeName()), "Y", spec.getTemplateClassification())); } }); } @@ -220,8 +239,10 @@ public class TemplateCenterManage { Collections.sort(contents); Long countDataV = contents.stream().filter(item -> "PANEL".equals(item.getTemplateType())).count(); Long countDashboard = contents.stream().filter(item -> "SCREEN".equals(item.getTemplateType())).count(); - List templateDataV = templateManages.stream().filter(item -> "PANEL".equals(item.getTemplateType())).collect(Collectors.toList()); - List templateDashboard = templateManages.stream().filter(item -> "SCREEN".equals(item.getTemplateType())).collect(Collectors.toList()); + List templateDataV = + templateManages.stream().filter(item -> "PANEL".equals(item.getTemplateType())).collect(Collectors.toList()); + List templateDashboard = + templateManages.stream().filter(item -> "SCREEN".equals(item.getTemplateType())).collect(Collectors.toList()); if (countDataV < 10) { Long addItemCount = 10 - countDataV; Long addIndex = templateDataV.size() < addItemCount ? templateDataV.size() : addItemCount; @@ -237,12 +258,15 @@ public class TemplateCenterManage { return new MarketBaseResponse(url, categoryVO, contents); } - private MarketBaseResponse baseResponseV2Trans(MarketTemplateV2BaseResponse v2BaseResponse, List contents, String url) { + private MarketBaseResponse baseResponseV2Trans(MarketTemplateV2BaseResponse v2BaseResponse, + List contents, String url) { Map useTime = coreOptRecentManage.findTemplateRecentUseTime(); - List categoryVO = getCategoriesObject().stream().filter(node -> !"全部".equalsIgnoreCase(node.getLabel())).collect(Collectors.toList()); + List categoryVO = + getCategoriesObject().stream().filter(node -> !"全部".equalsIgnoreCase(node.getLabel())).collect(Collectors.toList()); Map categoriesMap = categoryVO.stream() .collect(Collectors.toMap(MarketMetaDataVO::getValue, MarketMetaDataVO::getLabel)); - List activeCategoriesName = new ArrayList<>(Arrays.asList(Translator.get("i18n_template_recent"), Translator.get("i18n_template_recommend"))); + List activeCategoriesName = new ArrayList<>(Arrays.asList(Translator.get("i18n_template_recent"), + Translator.get("i18n_template_recommend"))); contents.stream().forEach(templateMarketDTO -> { Long recentUseTime = useTime.get(templateMarketDTO.getId()); templateMarketDTO.setRecentUseTime(recentUseTime == null ? 0 : recentUseTime); @@ -252,7 +276,10 @@ public class TemplateCenterManage { v2BaseResponse.getItems().stream().forEach(marketTemplateV2ItemResult -> { MarketApplicationSpecVO spec = marketTemplateV2ItemResult.getApplication().getSpec(); MarketApplicationMetaDataVO metadata = marketTemplateV2ItemResult.getApplication().getMetadata(); - contents.add(new TemplateMarketDTO(metadata.getName(), spec.getDisplayName(), spec.getScreenshots().get(0).getUrl(), spec.getLinks().get(0).getUrl(), categoriesMap.get(spec.getLabel()), spec.getTemplateType(), useTime.get(spec.getReadmeName()), spec.getSuggest(), spec.getTemplateClassification())); + contents.add(new TemplateMarketDTO(metadata.getName(), spec.getDisplayName(), + spec.getScreenshots().get(0).getUrl(), spec.getLinks().get(0).getUrl(), + categoriesMap.get(spec.getLabel()), spec.getTemplateType(), useTime.get(spec.getReadmeName()) + , spec.getSuggest(), spec.getTemplateClassification())); if (categoriesMap.get(spec.getLabel()) != null) { activeCategoriesName.add(categoriesMap.get(spec.getLabel())); } @@ -260,10 +287,10 @@ public class TemplateCenterManage { } // 最近使用排序 Collections.sort(contents); - return new MarketBaseResponse(url, categoryVO.stream().filter(node -> activeCategoriesName.contains(node.getLabel())).collect(Collectors.toList()), contents); + return new MarketBaseResponse(url, + categoryVO.stream().filter(node -> activeCategoriesName.contains(node.getLabel())).collect(Collectors.toList()), contents); } - public List getCategories() { return getCategoriesV2().stream().map(MarketMetaDataVO::getLabel) .collect(Collectors.toList()); @@ -271,7 +298,8 @@ public class TemplateCenterManage { public List getCategoriesObject() { List result = getCategoriesV2(); - result.add(0, new MarketMetaDataVO("recent", Translator.get("i18n_template_recent"), CommonConstants.TEMPLATE_SOURCE.PUBLIC)); + result.add(0, new MarketMetaDataVO("recent", Translator.get("i18n_template_recent"), + CommonConstants.TEMPLATE_SOURCE.PUBLIC)); return result; } @@ -285,17 +313,19 @@ public class TemplateCenterManage { List allCategories = new ArrayList<>(); List manageCategories = templateManageMapper.findCategories(null); List manageCategoriesTrans = manageCategories.stream() - .map(templateCategory -> new MarketMetaDataVO(templateCategory.getId(), templateCategory.getName(), CommonConstants.TEMPLATE_SOURCE.MANAGE)) + .map(templateCategory -> new MarketMetaDataVO(templateCategory.getId(), templateCategory.getName(), + CommonConstants.TEMPLATE_SOURCE.MANAGE)) .collect(Collectors.toList()); - try { - Map templateParams = sysParameterManage.groupVal("template."); - String resultStr = marketGet(templateParams.get("template.url") + TEMPLATE_META_DATA_URL, null); - MarketMetaDataBaseResponse metaData = JsonUtil.parseObject(resultStr, MarketMetaDataBaseResponse.class); - allCategories.addAll(metaData.getLabels()); - allCategories.add(0, new MarketMetaDataVO("suggest", Translator.get("i18n_template_recommend"), CommonConstants.TEMPLATE_SOURCE.PUBLIC)); - } catch (Exception e) { - LogUtil.error("模板市场分类获取错误", e); - } +// try { +// Map templateParams = sysParameterManage.groupVal("template."); +// String resultStr = marketGet(templateParams.get("template.url") + TEMPLATE_META_DATA_URL, null); +// MarketMetaDataBaseResponse metaData = JsonUtil.parseObject(resultStr, MarketMetaDataBaseResponse.class); +// allCategories.addAll(metaData.getLabels()); +// allCategories.add(0, new MarketMetaDataVO("suggest", Translator.get("i18n_template_recommend"), +// CommonConstants.TEMPLATE_SOURCE.PUBLIC)); +// } catch (Exception e) { +// LogUtil.error("模板市场分类获取错误", e); +// } return mergeAndDistinctByLabel(allCategories, manageCategoriesTrans); diff --git a/core/core-backend/src/main/java/io/gisbi/template/service/TemplateMarketService.java b/core/core-backend/src/main/java/io/gisbi/template/service/TemplateMarketService.java index 75b7b3b..cfa5562 100644 --- a/core/core-backend/src/main/java/io/gisbi/template/service/TemplateMarketService.java +++ b/core/core-backend/src/main/java/io/gisbi/template/service/TemplateMarketService.java @@ -23,7 +23,7 @@ public class TemplateMarketService implements TemplateMarketApi { private TemplateCenterManage templateCenterManage; @Override public MarketBaseResponse searchTemplate() { - return templateCenterManage.searchTemplate(); + return templateCenterManage.searchTemplate("0"); } @Override public MarketBaseResponse searchTemplateRecommend() { @@ -31,8 +31,8 @@ public class TemplateMarketService implements TemplateMarketApi { } @Override - public MarketPreviewBaseResponse searchTemplatePreview() { - return templateCenterManage.searchTemplatePreview(); + public MarketPreviewBaseResponse searchTemplatePreview(String offline) { + return templateCenterManage.searchTemplatePreview(offline); } @Override diff --git a/sdk/api/api-base/src/main/java/io/gisbi/api/template/TemplateMarketApi.java b/sdk/api/api-base/src/main/java/io/gisbi/api/template/TemplateMarketApi.java index f469fcf..4c57c87 100644 --- a/sdk/api/api-base/src/main/java/io/gisbi/api/template/TemplateMarketApi.java +++ b/sdk/api/api-base/src/main/java/io/gisbi/api/template/TemplateMarketApi.java @@ -25,7 +25,7 @@ public interface TemplateMarketApi { @GetMapping("/searchPreview") @Operation(summary = "预览") - MarketPreviewBaseResponse searchTemplatePreview(); + MarketPreviewBaseResponse searchTemplatePreview(String offline); @GetMapping("/categories") @Operation(summary = "分类") From 8edd88c0025bae954943fabc75c5852d0215e964 Mon Sep 17 00:00:00 2001 From: wangxk Date: Mon, 30 Jun 2025 14:11:14 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=8D=AB=E6=98=9F=E5=9B=BE=E5=B1=82?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E9=A1=B5=E9=9D=A2=E5=A4=B1=E6=95=88=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E5=92=8C=E4=BD=8D=E7=BD=AE=E5=8F=98=E5=8A=A8=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E8=A7=A3=E5=86=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../views/components/ChartComponentG2Plot.vue | 266 ++++++++++++++---- 1 file changed, 213 insertions(+), 53 deletions(-) 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 1a953c9..72d69d5 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 @@ -30,6 +30,10 @@ import { L7ChartView } from '@/views/chart/components/js/panel/types/impl/l7' import { useI18n } from '@/hooks/web/useI18n' import { ExportImage, Scale, Fullscreen, Control, Scene, TileLayer } from '@antv/l7' import { GaodeMap } from '@antv/l7-maps'; +//三维导入 +import * as THREE from 'three'; +import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; +import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js' // 控制器 const { t } = useI18n() const dvMainStore = dvMainStoreWithOut() const { nowPanelTrackInfo, nowPanelJumpInfo, mobileInPc, embeddedCallBack, inMobile } = @@ -118,7 +122,11 @@ const state = reactive({ let chartData = shallowRef>({ fields: [] }) - +// 添加普通变量存储Three.js对象 +let threeScene: THREE.Scene | null = null; +let threeRenderer: THREE.WebGLRenderer | null = null; +let threeCamera: THREE.PerspectiveCamera | null = null; +let model: THREE.Object3D | null = null; const containerId = 'container-' + showPosition.value + '-' + view.value.id + '-' + suffixId.value const viewTrack = ref(null) @@ -332,8 +340,51 @@ const renderL7Plot = async (chart: ChartObj, chartView: L7PlotChartView { + // console.log('12345677',isSatelliteVisible); + 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) + + } + }; + // // 确保地图加载完成 + // scene.on('loaded', () => { + // console.log('地图加载完成'); + + // }); + + return btn; + } +} +let mapL7Timer: any let scaleControl: Scale | null = null // 存储比例尺实例 let fullscreenControl let satelliteControlInstance = null; // 用于存储卫星控件实例 @@ -355,10 +406,6 @@ const renderL7 = async (chart: ChartObj, chartView: L7ChartView, callb }); myChart.getScene()?.addControl(scaleControl); } - - // 创建并添加新比例尺 - - // 添加全屏控件 if (fullscreenControl) { @@ -368,60 +415,14 @@ const renderL7 = async (chart: ChartObj, chartView: L7ChartView, callb }); 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 { + if (!satelliteControlInstance) { // 添加新的卫星控件到地图 satelliteControlInstance = new SatelliteControl({ position: 'bottomright' }); myChart.getScene()?.addControl(satelliteControlInstance); } - - // ====== 修复完成 ====== myChart?.render(); @@ -734,6 +735,138 @@ defineExpose({ trackMenu, clearLinkage }) + +//三维 three.js 实现方法 +// 新增方法 - 初始化 Three.js +const initThree = (container: HTMLElement) => { + // 创建场景 + threeScene = new THREE.Scene(); + + // 创建相机 + threeCamera = new THREE.PerspectiveCamera( + 75, + container.clientWidth / container.clientHeight, + 0.1, + 1000 + ); + threeCamera.position.z = 5; + + // 创建渲染器 + threeRenderer = new THREE.WebGLRenderer({ alpha: true, antialias: true }); + threeRenderer.setSize(container.clientWidth, container.clientHeight); + // 设置关键样式 + threeRenderer.domElement.style.position = 'absolute'; + threeRenderer.domElement.style.top = '0'; + threeRenderer.domElement.style.left = '0'; + threeRenderer.domElement.style.zIndex = '1'; // 确保在地图之上 + container.appendChild(threeRenderer.domElement); + + + // 添加光源 + const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); + threeScene.add(ambientLight); + + const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); + directionalLight.position.set(10, 10, 10); + threeScene.add(directionalLight); +}; +// 新增方法 - 加载模型 +const loadModel = (filePath: string) => { + const loader = new GLTFLoader(); + const dracoLoader = new DRACOLoader() + dracoLoader.setDecoderPath('./static/js/') + dracoLoader.setDecoderConfig({ type: 'js' }) + loader.setDRACOLoader(dracoLoader) + + // 确保地图场景存在 + if (!myChart?.getScene()) { + console.warn('地图场景尚未初始化,延迟加载模型'); + // 延迟重试 + setTimeout(() => loadModel(filePath), 500); + return; + } + + const scene = myChart.getScene(); + + // 检查场景是否已加载 + if (scene.loaded) { + // 场景已加载,直接加载模型 + loadModelInternal(loader, filePath); + } else { + // 添加一次性事件监听器 + const loadedHandler = () => { + scene.off('loaded', loadedHandler); // 移除监听器 + loadModelInternal(loader, filePath); + }; + scene.on('loaded', loadedHandler); + } +}; + +// 内部加载方法 +const loadModelInternal = (loader, filePath) => { + loader.load( + filePath, + (gltf) => { + console.log('Model loaded successfully:', gltf); + model = gltf.scene; + threeScene?.add(model); + // animate(); + placeModelByLngLat(116.3974, 39.9093); // 直接调用放置方法 + }, + (progress) => { + console.log('Loading progress:', progress); + }, + (error) => { + console.error('模型加载失败:', error); + } + ); +}; +// 新增方法 - 根据经纬度放置模型 +const placeModelByLngLat = (lng: number, lat: number) => { + debugger + if (!model || !myChart?.getScene()) { + console.warn('模型或地图场景未初始化'); + return; + } + + const scene = myChart.getScene(); + console.log('地图场景状态:', scene); + + try { + const containerPoint = scene.lngLatToContainer([lng, lat]); + console.log('容器坐标:', containerPoint); + + const container = document.getElementById(containerId); + if (!container) { + console.error('容器元素未找到'); + return; + } + + // 转换为Three.js的标准化设备坐标 + const x = (containerPoint.x / container.clientWidth) * 2 - 1; + const y = -(containerPoint.y / container.clientHeight) * 2 + 1; + + console.log('Three.js坐标:', { x, y }); + + // 更新模型位置 + model.position.set(x * 5, y * 5, 0); + + // 确保相机看向模型 + if (threeCamera) { + threeCamera.lookAt(model.position); + console.log('相机已调整朝向模型'); + } + } catch (e) { + console.error('坐标转换错误:', e); + } +}; +// 动画循环 +const animate = () => { + requestAnimationFrame(animate); + if (threeRenderer && threeScene && threeCamera) { + threeRenderer.render(threeScene, threeCamera); + } +}; let resizeObserver const TOLERANCE = 0.01 const RESIZE_MONITOR_CHARTS = ['map', 'bubble-map', 'flow-map', 'heat-map'] @@ -760,6 +893,15 @@ onMounted(() => { resizeObserver.observe(containerDom) useEmitt({ name: 'l7-prepare-picture', callback: preparePicture }) useEmitt({ name: 'l7-unprepare-picture', callback: unPreparePicture }) + // 初始化 Three.js + // const container = document.getElementById(containerId); + // if (container) { + // initThree(container); + // // 加载模型(替换为实际路径) + // // loadModel(`./static/3DModel/Camera1.glb`); + // // loadModel('static/3DModel/scene.glb'); + + // } }) onBeforeUnmount(() => { try { @@ -768,6 +910,9 @@ onBeforeUnmount(() => { } catch (e) { console.warn(e) } + if (threeRenderer) { + threeRenderer.dispose(); + } }) @@ -809,6 +954,21 @@ onBeforeUnmount(() => { fill: #fff !important; color: #fff !important; } +:deep(.l7-control-zoom){ + position:fixed; + right: 0px; + bottom: 65px; +} +:deep(.l7-control-button){ + position:fixed; + right: 0px; + bottom: 35px; +} +// :deep(.l7-button-control){ +// position:fixed; +// right: 0px; +// bottom: 0px; +// } // :deep(.l7-control-container .l7-top) { // top: auto !important; From ef380035b684da75843c4b3382af30c8557ad524 Mon Sep 17 00:00:00 2001 From: wangxk Date: Mon, 30 Jun 2025 14:22:39 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=8D=AB=E6=98=9F=E5=9B=BE=E5=B1=82?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E9=A1=B5=E9=9D=A2=E5=A4=B1=E6=95=88=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E5=92=8C=E4=BD=8D=E7=BD=AE=E5=8F=98=E5=8A=A8=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E8=A7=A3=E5=86=B3-=E8=A1=A5=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/views/components/ChartComponentG2Plot.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 72d69d5..da23672 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 @@ -955,12 +955,12 @@ onBeforeUnmount(() => { color: #fff !important; } :deep(.l7-control-zoom){ - position:fixed; + position:fixed !important; right: 0px; bottom: 65px; } :deep(.l7-control-button){ - position:fixed; + position:fixed !important; right: 0px; bottom: 35px; }