From d9a8b72c7da6a7b18afa884e45527e1f29cb0480 Mon Sep 17 00:00:00 2001 From: JackySoft Date: Sun, 22 Sep 2024 00:53:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BC=80=E5=8F=91=E5=9C=B0=E5=9B=BE?= =?UTF-8?q?=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/editor/index.html | 10 ++ packages/editor/src/config/components.ts | 11 ++ .../editor/src/packages/Map/BMap/BMap.tsx | 91 ++++++++++++++ .../editor/src/packages/Map/BMap/Schema.ts | 119 ++++++++++++++++++ .../editor/src/packages/Map/BMap/index.ts | 2 + packages/editor/src/packages/index.tsx | 1 + packages/editor/src/packages/utils/util.ts | 18 ++- packages/materials/Map/BMap/BMap.tsx | 91 ++++++++++++++ packages/materials/Map/BMap/index.ts | 1 + packages/materials/utils/util.ts | 18 +++ 10 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 packages/editor/src/packages/Map/BMap/BMap.tsx create mode 100644 packages/editor/src/packages/Map/BMap/Schema.ts create mode 100644 packages/editor/src/packages/Map/BMap/index.ts create mode 100644 packages/materials/Map/BMap/BMap.tsx create mode 100644 packages/materials/Map/BMap/index.ts diff --git a/packages/editor/index.html b/packages/editor/index.html index 32c8f186..358f5bc0 100644 --- a/packages/editor/index.html +++ b/packages/editor/index.html @@ -43,6 +43,16 @@ s.parentNode.insertBefore(hm, s); })(); + + + + +
diff --git a/packages/editor/src/config/components.ts b/packages/editor/src/config/components.ts index a307fd59..c0fcf051 100644 --- a/packages/editor/src/config/components.ts +++ b/packages/editor/src/config/components.ts @@ -355,6 +355,17 @@ const components = [ }, ], }, + { + type: 'Map', + title: '地图', + data: [ + { + icon: '', + name: 'BMap', + type: 'BMap', + }, + ], + }, { type: 'MicroApp', title: '微服务', diff --git a/packages/editor/src/packages/Map/BMap/BMap.tsx b/packages/editor/src/packages/Map/BMap/BMap.tsx new file mode 100644 index 00000000..fcb3af6e --- /dev/null +++ b/packages/editor/src/packages/Map/BMap/BMap.tsx @@ -0,0 +1,91 @@ +import { ComponentType } from '@/packages/types'; +import { createId, isNotEmpty } from '@/packages/utils/util'; +import { useState, useImperativeHandle, forwardRef, useEffect } from 'react'; + +/** + * + * @param props 组件本身属性 + * @param style 组件样式 + * @returns + */ +const MBMap = ({ id, type, config, onLoaded, onClick }: ComponentType, ref: any) => { + const [visible, setVisible] = useState(true); + const [mapId, setMapId] = useState(''); + const [map, setMap] = useState(null); + useEffect(() => { + setMapId(createId('BMap')); + }, []); + + useEffect(() => { + if (!mapId) return; + const map = new window.BMapGL.Map(mapId); + const point = new window.BMapGL.Point(116.404, 39.915); + map.centerAndZoom(point, config.props.zoom || 15); + map.addEventListener('tilesloaded', function () { + onLoaded?.(); + }); + map.addEventListener('click', function ({ latlng: { lat, lng } }: any) { + onClick?.({ + lat, + lng, + }); + }); + setMap(map); + }, [mapId]); + + useEffect(() => { + if (!mapId || !map) return; + const { cityName, zoom, wheelZoom, rotateAngle, tiltAngle, mapType, ScaleControl, ZoomControl, CityListControl, LocationControl } = config.props; + // 设置当前城市 + if (cityName.trim()) { + const [lat, lng] = cityName.split(','); + if (lat && lng) { + map.centerAndZoom(new window.BMapGL.Point(lat, lng), zoom || 15); + } else { + map.centerAndZoom(cityName, zoom || 15); + } + } + // 设置地图是否允许滚轮缩放 + map.enableScrollWheelZoom(wheelZoom); + // 设置地图旋转角度 + if (isNotEmpty(rotateAngle)) { + map.setHeading(rotateAngle); + } + // 设置地图倾斜角度 + if (isNotEmpty(tiltAngle)) { + map.setTilt(tiltAngle); + } + // 设置地图类型 + map.setMapType(window[mapType]); + // 添加比例尺控件 + if (ScaleControl) { + map.addControl(new window.BMapGL.ScaleControl()); + } + // 添加缩放控件 + if (ZoomControl) { + map.addControl(new window.BMapGL.ZoomControl()); + } + // 添加城市列表控件 + if (CityListControl) { + map.addControl(new window.BMapGL.CityListControl()); + } + // 添加定位控件 + if (LocationControl) { + map.addControl(new window.BMapGL.LocationControl()); + } + }, [map, config.props]); + + // 对外暴露方法 + useImperativeHandle(ref, () => { + return { + show() { + setVisible(true); + }, + hide() { + setVisible(false); + }, + }; + }); + return visible &&
; +}; +export default forwardRef(MBMap); diff --git a/packages/editor/src/packages/Map/BMap/Schema.ts b/packages/editor/src/packages/Map/BMap/Schema.ts new file mode 100644 index 00000000..5a404d1d --- /dev/null +++ b/packages/editor/src/packages/Map/BMap/Schema.ts @@ -0,0 +1,119 @@ +/** + * 组件配置和属性值 + */ + +export default { + // 组件属性配置JSON + attrs: [ + { + type: 'Title', + label: '基础配置', + name: 'basic', + }, + { + type: 'Input', + label: '中心坐标', + name: 'cityName', + props: { + placeholder: '城市或者经纬度,eg: 116.403795,39.914286', + }, + tooltip: '输入经纬度时,逗号分割,纬度在前,经度在后', + }, + { + type: 'Slider', + label: '缩放等级', + name: 'zoom', + props: { + min: 1, + max: 18, + step: 1, + }, + }, + { + type: 'Switch', + label: '滚轮缩放', + name: 'wheelZoom', + }, + { + type: 'InputNumber', + label: '旋转角度', + name: 'rotateAngle', + }, + { + type: 'InputNumber', + label: '倾斜角度', + name: 'tiltAngle', + }, + { + type: 'Select', + label: '地图模式', + name: 'mapType', + props: { + options: [ + { value: 'BMAP_NORMAL_MAP', label: '标准地图' }, + { value: 'BMAP_EARTH_MAP', label: '地球模式' }, + { value: 'BMAP_SATELLITE_MAP', label: '卫星地图' }, + ], + }, + }, + { + type: 'Title', + label: '控件配置', + name: 'controls', + }, + { + type: 'Switch', + label: '比例尺', + name: 'ScaleControl', + }, + { + type: 'Switch', + label: '缩放控件', + name: 'ZoomControl', + }, + { + type: 'Switch', + label: '城市控件', + name: 'CityListControl', + }, + { + type: 'Switch', + label: '定位控件', + name: 'LocationControl', + }, + ], + config: { + // 组件默认属性值 + props: { + cityName: '北京市', + zoom: 15, + wheelZoom: true, + mapType: 'BMAP_NORMAL_MAP', + ScaleControl: true, + ZoomControl: true, + CityListControl: true, + LocationControl: true, + }, + style: { + border: '3px solid #7d33ff', + width: '100%', + height: '600px', + }, + events: [], + api: {}, + source: '', + }, + // 组件事件 + events: [ + { + value: 'onLoaded', + name: '加载完成事件', + }, + { + value: 'onClick', + name: '地图单机事件', + }, + ], + // 组件接口 + api: {}, +}; diff --git a/packages/editor/src/packages/Map/BMap/index.ts b/packages/editor/src/packages/Map/BMap/index.ts new file mode 100644 index 00000000..66d9a8e7 --- /dev/null +++ b/packages/editor/src/packages/Map/BMap/index.ts @@ -0,0 +1,2 @@ +export { default as BMap } from './BMap'; +export { default as BMapConfig } from './Schema'; diff --git a/packages/editor/src/packages/index.tsx b/packages/editor/src/packages/index.tsx index 778c8d20..0857513f 100644 --- a/packages/editor/src/packages/index.tsx +++ b/packages/editor/src/packages/index.tsx @@ -7,5 +7,6 @@ export * from './EChart'; export * from './Functional'; export * from './Basic'; export * from './FeedBack'; +export { BMap, BMapConfig } from './Map/BMap'; export { IFrame, IFrameConfig } from './IFrame'; import './index.less'; diff --git a/packages/editor/src/packages/utils/util.ts b/packages/editor/src/packages/utils/util.ts index 1e5327f6..2cae0f3b 100644 --- a/packages/editor/src/packages/utils/util.ts +++ b/packages/editor/src/packages/utils/util.ts @@ -213,7 +213,6 @@ export function renderFormula(formula: string, eventParams: any = {}) { const pageStore = usePageStore.getState().page; const formData = cloneDeep(pageStore.formData || {}); originIds.forEach((id: string) => { - fnParams.push(id); // 如果绑定的是表单项,则通过Form实例对象获取对应表单值 const formValues = pageStore.formData?.[id] || {}; if (!formData?.id) { @@ -375,6 +374,23 @@ export const loadStyle = (id: string, src: string) => { }); }; +/** + * 动态加载JS,主要用于解决不常用的JS包,防止影响整体性能,比如抖音和快手 + * @param src + * @returns Promise + */ +export const loadScript = (src: string) => { + return new Promise((resolve, reject) => { + const script = document.createElement('script'); + script.type = 'text/javascript'; + // script.defer = true; + script.onload = resolve; + script.onerror = reject; + script.src = src; + document.head.append(script); + }); +}; + /** * 获取环境变量 * 1. vanEnv 当前项目环境 diff --git a/packages/materials/Map/BMap/BMap.tsx b/packages/materials/Map/BMap/BMap.tsx new file mode 100644 index 00000000..7f019f4d --- /dev/null +++ b/packages/materials/Map/BMap/BMap.tsx @@ -0,0 +1,91 @@ +import { ComponentType } from '../../types'; +import { createId, isNotEmpty } from '../../utils/util'; +import { useState, useImperativeHandle, forwardRef, useEffect } from 'react'; + +/** + * + * @param props 组件本身属性 + * @param style 组件样式 + * @returns + */ +const MBMap = ({ config, onLoaded, onClick }: ComponentType, ref: any) => { + const [visible, setVisible] = useState(true); + const [mapId, setMapId] = useState(''); + const [map, setMap] = useState(null); + useEffect(() => { + setMapId(createId('BMap')); + }, []); + + useEffect(() => { + if (!mapId) return; + const map = new window.BMapGL.Map(mapId); + const point = new window.BMapGL.Point(116.404, 39.915); + map.centerAndZoom(point, config.props.zoom || 15); + map.addEventListener('tilesloaded', function () { + onLoaded?.(); + }); + map.addEventListener('click', function ({ latlng: { lat, lng } }: any) { + onClick?.({ + lat, + lng, + }); + }); + setMap(map); + }, [mapId]); + + useEffect(() => { + if (!mapId || !map) return; + const { cityName, zoom, wheelZoom, rotateAngle, tiltAngle, mapType, ScaleControl, ZoomControl, CityListControl, LocationControl } = config.props; + // 设置当前城市 + if (cityName.trim()) { + const [lat, lng] = cityName.split(','); + if (lat && lng) { + map.centerAndZoom(new window.BMapGL.Point(lat, lng), zoom || 15); + } else { + map.centerAndZoom(cityName, zoom || 15); + } + } + // 设置地图是否允许滚轮缩放 + map.enableScrollWheelZoom(wheelZoom); + // 设置地图旋转角度 + if (isNotEmpty(rotateAngle)) { + map.setHeading(rotateAngle); + } + // 设置地图倾斜角度 + if (isNotEmpty(tiltAngle)) { + map.setTilt(tiltAngle); + } + // 设置地图类型 + map.setMapType(window[mapType]); + // 添加比例尺控件 + if (ScaleControl) { + map.addControl(new window.BMapGL.ScaleControl()); + } + // 添加缩放控件 + if (ZoomControl) { + map.addControl(new window.BMapGL.ZoomControl()); + } + // 添加城市列表控件 + if (CityListControl) { + map.addControl(new window.BMapGL.CityListControl()); + } + // 添加定位控件 + if (LocationControl) { + map.addControl(new window.BMapGL.LocationControl()); + } + }, [map, config.props]); + + // 对外暴露方法 + useImperativeHandle(ref, () => { + return { + show() { + setVisible(true); + }, + hide() { + setVisible(false); + }, + }; + }); + return visible &&
; +}; +export default forwardRef(MBMap); diff --git a/packages/materials/Map/BMap/index.ts b/packages/materials/Map/BMap/index.ts new file mode 100644 index 00000000..476a1a86 --- /dev/null +++ b/packages/materials/Map/BMap/index.ts @@ -0,0 +1 @@ +export { default as BMap } from './BMap'; diff --git a/packages/materials/utils/util.ts b/packages/materials/utils/util.ts index 7cea9f12..51e0ec14 100644 --- a/packages/materials/utils/util.ts +++ b/packages/materials/utils/util.ts @@ -8,6 +8,7 @@ import { ComponentType } from '../types'; import { get } from 'lodash-es'; import { cloneDeep } from 'lodash-es'; import copy from 'copy-to-clipboard'; + /** * 生成ID * @param name @@ -373,6 +374,23 @@ export const loadStyle = (id: string, src: string) => { }); }; +/** + * 动态加载JS,主要用于解决不常用的JS包,防止影响整体性能,比如抖音和快手 + * @param src + * @returns Promise + */ +export const loadScript = (src: string) => { + return new Promise((resolve, reject) => { + const script = document.createElement('script'); + script.type = 'text/javascript'; + // script.defer = true; + script.onload = resolve; + script.onerror = reject; + script.src = src; + document.head.append(script); + }); +}; + /** * 获取环境变量 * 1. vanEnv 当前项目环境