From 67f9653829859164f43814e4cb703d0ac5590c42 Mon Sep 17 00:00:00 2001 From: Zzc <1373857752@qq.com> Date: Fri, 7 Nov 2025 15:43:39 +0800 Subject: [PATCH] =?UTF-8?q?refactor(map):=20=E5=B0=86=E5=9C=B0=E5=9B=BE?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=B0=81=E8=A3=85=E6=88=90=E7=8B=AC=E7=AB=8B?= =?UTF-8?q?=E7=9A=84=E5=8D=95=E5=85=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 将 `SvgIcon` 组件移至 `map/shared/SvgIcon` * 将地图图标迁移至 `map/assets/icons` * 更新组件导入,使用 `MapIcon` 替代 `svg-icon` * 为 Cesium 地图 SDK 添加详尽的 `README.md` * 更新 vite 配置,纳入新的图标目录 * 移除 `main.js` 中的 `SvgIcon` 导入 --- packages/screen/src/main.js | 2 - packages/screen/src/map/README.md | 389 ++++++++++++++++++ .../assets/icons}/GisLandcoverMap.svg | 0 .../svg => map/assets/icons}/GisLayers.svg | 0 .../svg => map/assets/icons}/compass.svg | 0 .../svg => map/assets/icons}/compass_bg.svg | 0 .../src/map/components/BaseMapSwitcher.vue | 5 +- .../map/components/LayerDirectoryControl.vue | 3 +- .../screen/src/map/components/MapCompass.vue | 6 +- packages/screen/src/map/index.js | 2 + .../shared}/SvgIcon/index.vue | 0 packages/screen/vite.config.js | 5 +- 12 files changed, 403 insertions(+), 9 deletions(-) create mode 100644 packages/screen/src/map/README.md rename packages/screen/src/{assets/icons/svg => map/assets/icons}/GisLandcoverMap.svg (100%) rename packages/screen/src/{assets/icons/svg => map/assets/icons}/GisLayers.svg (100%) rename packages/screen/src/{assets/icons/svg => map/assets/icons}/compass.svg (100%) rename packages/screen/src/{assets/icons/svg => map/assets/icons}/compass_bg.svg (100%) rename packages/screen/src/{components => map/shared}/SvgIcon/index.vue (100%) diff --git a/packages/screen/src/main.js b/packages/screen/src/main.js index 71c6a5d..bbefd42 100644 --- a/packages/screen/src/main.js +++ b/packages/screen/src/main.js @@ -7,7 +7,6 @@ import ElementPlus from 'element-plus' import zhCn from 'element-plus/es/locale/lang/zh-cn' import 'cesium/Build/Cesium/Widgets/widgets.css' import 'virtual:svg-icons-register' -import SvgIcon from './components/SvgIcon/index.vue' const app = createApp(App) @@ -16,6 +15,5 @@ app.use(ElementPlus, { locale: zhCn, }) app.use(router) -app.component('svg-icon', SvgIcon) app.mount('#app') diff --git a/packages/screen/src/map/README.md b/packages/screen/src/map/README.md new file mode 100644 index 0000000..f68a725 --- /dev/null +++ b/packages/screen/src/map/README.md @@ -0,0 +1,389 @@ +# 🗺️ Cesium 地图 SDK + +基于 Cesium 的 Vue 3 地图组件库,提供完整的地图交互、图层管理、底图切换等功能。 + +## ✨ 特性 + +- 🎯 **完全自包含** - 所有依赖集成在 `/map` 目录内 +- 🚀 **开箱即用** - 复制目录即可使用,无需额外配置 +- 📦 **模块化设计** - 组件化架构,灵活组合 +- 🎨 **UI 集成** - 内置精美的地图控件 UI +- 🔧 **TypeScript 友好** - 完整的类型支持(计划中) +- 🌍 **多底图支持** - 天地图、ArcGIS、Cesium Ion 等 + +## 📦 核心组件 + +### 地图容器 +- **MapViewport** - 地图视口容器,Cesium Viewer 初始化 +- **MapControls** - 地图控制面板容器 + +### 交互控件 +- **BaseMapSwitcher** - 底图切换器 +- **LayerDirectoryControl** - 图层目录管理 +- **MapCompass** - 指南针导航 +- **SceneModeToggle** - 2D/3D 场景切换 + +### 工具组件 +- **MapIcon** - SVG 图标组件 + +### 状态管理 +- **useMapStore** - 地图核心状态管理 +- **useMapUiStore** - 地图 UI 状态管理 + +### Composables +- **useMapViewSnapshot** - 地图视图快照管理 + +--- + +## 🚀 快速开始 + +### 1. 复制模块 + +```bash +# 复制整个地图模块到你的项目 +cp -r src/map /your-project/src/ +``` + +### 2. 安装依赖 + +```bash +# 核心依赖 +npm install cesium@^1.135.0 +npm install vite-plugin-cesium@^1.2.22 +npm install vite-plugin-svg-icons@^2.0.1 + +# Vue 生态(如果项目中没有) +npm install vue@^3.5.0 pinia@^3.0.0 +npm install element-plus@^2.0.0 +npm install vue-router@^4.0.0 +``` + +### 3. Vite 配置 + +```javascript +// vite.config.js +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import cesium from 'vite-plugin-cesium' +import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' +import { resolve } from 'path' + +export default defineConfig({ + plugins: [ + vue(), + cesium(), + createSvgIconsPlugin({ + iconDirs: [resolve(__dirname, 'src/map/assets/icons')], + symbolId: 'icon-[name]' + }) + ], + define: { + CESIUM_BASE_URL: JSON.stringify('/cesium') + }, + resolve: { + alias: { + '@': resolve(__dirname, 'src') + } + } +}) +``` + +### 4. 主入口配置 + +```javascript +// main.js +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import ElementPlus from 'element-plus' +import 'element-plus/dist/index.css' +import 'cesium/Build/Cesium/Widgets/widgets.css' +import 'virtual:svg-icons-register' +import App from './App.vue' + +const app = createApp(App) +app.use(createPinia()) +app.use(ElementPlus) +app.mount('#app') +``` + +### 5. 使用示例 + +```vue + + + + + +``` + +--- + +## 📚 API 文档 + +### MapViewport + +地图视口容器,负责初始化 Cesium Viewer。 + +**Props:** 无 + +**Events:** 无 + +**说明:** +- 自动初始化 Cesium Viewer +- 配置地图基础参数(地形、场景模式等) +- 加载默认底图 +- 注入 mapStore 实例 + +### MapControls + +地图控制面板容器,包含所有交互控件。 + +**Props:** 无 + +**使用示例:** +```vue + +``` + +### useMapStore() + +地图核心状态管理 Store。 + +**主要方法:** +- `init(viewer)` - 初始化地图实例 +- `onReady(callback)` - 地图就绪回调 +- `services()` - 获取地图服务(camera, layer, entity, query) +- `destroy()` - 销毁地图实例 + +**使用示例:** +```javascript +import { useMapStore } from '@/map' + +const mapStore = useMapStore() + +// 等待地图就绪 +mapStore.onReady(() => { + const { camera, layer } = mapStore.services() + + // 添加图层 + layer.addLayer({ + id: 'my-layer', + type: 'WmtsServiceLayer', + url: 'https://...', + options: { visible: true } + }) +}) +``` + +--- + +## 🔧 高级配置 + +### 底图配置 + +编辑 `src/map/data/baseMap.json` 配置底图服务: + +```json +{ + "Groups": [ + { + "Attribute": { + "rid": "tianditu-group", + "name": "天地图", + "sortValue": 1 + }, + "Children": [ + { + "Attribute": { + "rid": "tianditu-img", + "name": "天地图影像", + "serviceTypeName": "TiandituImgLayer", + "servicePath": "http://t{s}.tianditu.gov.cn/img_w/wmts?...", + "sortValue": 1 + } + } + ] + } + ] +} +``` + +### 图层目录配置 + +编辑 `src/map/data/layerMap.json` 配置图层目录: + +```json +[ + { + "Name": "业务图层", + "Rid": "business-layers", + "Children": [ + { + "Name": "我的图层", + "Attribute": { + "rid": "my-layer-001", + "serviceTypeName": "WmtsServiceLayer", + "servicePath": "https://..." + } + } + ] + } +] +``` + +### 环境变量 + +```bash +# .env +VITE_CESIUM_ION_TOKEN=your_cesium_ion_token +``` + +--- + +## 📦 目录结构 + +``` +src/map/ +├── components/ # 地图组件 +│ ├── MapViewport.vue # 地图视口 +│ ├── MapControls.vue # 控制面板 +│ ├── BaseMapSwitcher.vue # 底图切换器 +│ ├── LayerDirectoryControl.vue # 图层目录 +│ ├── MapCompass.vue # 指南针 +│ └── SceneModeToggle.vue # 场景切换 +├── services/ # 地图服务 +│ ├── createCameraService.js # 相机服务 +│ ├── createLayerService.js # 图层服务 +│ ├── createEntityService.js # 实体服务 +│ └── createQueryService.js # 查询服务 +├── stores/ # 状态管理 +│ ├── mapStore.js # 地图状态 +│ └── mapUiStore.js # UI 状态 +├── composables/ # 组合式函数 +│ └── useMapViewSnapshot.js +├── shared/ # 共享组件 +│ └── SvgIcon/ # 图标组件 +├── assets/ # 资源文件 +│ └── icons/ # SVG 图标 +├── data/ # 配置数据 +│ ├── baseMap.json # 底图配置 +│ ├── mapBaseConfig.json # 地图配置 +│ └── layerMap.json # 图层目录 +├── utils/ # 工具函数 +│ ├── pickPosition.js +│ └── utils.js +├── index.js # 导出入口 +└── README.md # 本文档 +``` + +--- + +## 🌍 浏览器支持 + +- Chrome >= 90 +- Firefox >= 88 +- Safari >= 14 +- Edge >= 90 + +**注意:** Cesium 需要 WebGL 2.0 支持。 + +--- + +## 📝 依赖清单 + +### PeerDependencies + +```json +{ + "cesium": "^1.135.0", + "vue": "^3.5.0", + "pinia": "^3.0.0", + "element-plus": "^2.0.0", + "vue-router": "^4.0.0" +} +``` + +### DevDependencies + +```json +{ + "vite-plugin-cesium": "^1.2.22", + "vite-plugin-svg-icons": "^2.0.1" +} +``` + +--- + +## 🔨 开发指南 + +### 添加新组件 + +1. 在 `components/` 创建新组件 +2. 在 `index.js` 导出组件 +3. 更新本 README 文档 + +### 添加新服务 + +1. 在 `services/` 创建服务文件 +2. 在 `mapStore.js` 中注册服务 +3. 提供完整的 JSDoc 注释 + +### 添加新图标 + +1. 将 SVG 文件放到 `assets/icons/` +2. 使用 `` 引用 + +--- + +## 📄 License + +MIT License + +--- + +## 🤝 贡献 + +欢迎提交 Issue 和 Pull Request! + +--- + +## 📮 联系方式 + +如有问题或建议,请通过以下方式联系: + +- Issue: [GitHub Issues](#) +- Email: [your-email@example.com](#) + +--- + +**Generated with ❤️ by Cesium Map SDK Team** diff --git a/packages/screen/src/assets/icons/svg/GisLandcoverMap.svg b/packages/screen/src/map/assets/icons/GisLandcoverMap.svg similarity index 100% rename from packages/screen/src/assets/icons/svg/GisLandcoverMap.svg rename to packages/screen/src/map/assets/icons/GisLandcoverMap.svg diff --git a/packages/screen/src/assets/icons/svg/GisLayers.svg b/packages/screen/src/map/assets/icons/GisLayers.svg similarity index 100% rename from packages/screen/src/assets/icons/svg/GisLayers.svg rename to packages/screen/src/map/assets/icons/GisLayers.svg diff --git a/packages/screen/src/assets/icons/svg/compass.svg b/packages/screen/src/map/assets/icons/compass.svg similarity index 100% rename from packages/screen/src/assets/icons/svg/compass.svg rename to packages/screen/src/map/assets/icons/compass.svg diff --git a/packages/screen/src/assets/icons/svg/compass_bg.svg b/packages/screen/src/map/assets/icons/compass_bg.svg similarity index 100% rename from packages/screen/src/assets/icons/svg/compass_bg.svg rename to packages/screen/src/map/assets/icons/compass_bg.svg diff --git a/packages/screen/src/map/components/BaseMapSwitcher.vue b/packages/screen/src/map/components/BaseMapSwitcher.vue index 977184b..9eab338 100644 --- a/packages/screen/src/map/components/BaseMapSwitcher.vue +++ b/packages/screen/src/map/components/BaseMapSwitcher.vue @@ -27,7 +27,7 @@ @click="selectBaseGroup(group)" >
- @@ -55,7 +55,7 @@ :aria-controls="panelId" @click.stop="togglePanel" > - +
@@ -64,6 +64,7 @@ import { computed, onBeforeUnmount, onMounted, ref, shallowRef, watch } from 'vue' import { storeToRefs } from 'pinia' import { ElMessage } from 'element-plus' +import MapIcon from '@/map/shared/SvgIcon/index.vue' import useMapStore from '@/map/stores/mapStore' const panelId = 'base-map-switcher-panel' diff --git a/packages/screen/src/map/components/LayerDirectoryControl.vue b/packages/screen/src/map/components/LayerDirectoryControl.vue index 8dc8cea..35ace3a 100644 --- a/packages/screen/src/map/components/LayerDirectoryControl.vue +++ b/packages/screen/src/map/components/LayerDirectoryControl.vue @@ -6,7 +6,7 @@ type="primary" @click="togglePanel" > - + @@ -116,6 +116,7 @@ import { computed, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, watch import { storeToRefs } from 'pinia' import { ElMessage } from 'element-plus' import { ArrowDown, ArrowUp, Close, DataAnalysis, Hide, Operation, Search, View, CollectionTag } from '@element-plus/icons-vue' +import MapIcon from '@/map/shared/SvgIcon/index.vue' import useMapStore from '@/map/stores/mapStore' import layerCatalog from '@/map/data/layerMap.json' import { DEFAULT_VECTOR_LAYER_ID } from '@/map/utils/utils' diff --git a/packages/screen/src/map/components/MapCompass.vue b/packages/screen/src/map/components/MapCompass.vue index 1c0bf94..6e59b6d 100644 --- a/packages/screen/src/map/components/MapCompass.vue +++ b/packages/screen/src/map/components/MapCompass.vue @@ -8,15 +8,15 @@ > 指南针背景 - + 指南针指针 diff --git a/packages/screen/src/map/index.js b/packages/screen/src/map/index.js index 9bfd875..71f33ef 100644 --- a/packages/screen/src/map/index.js +++ b/packages/screen/src/map/index.js @@ -6,6 +6,8 @@ export { default as SceneModeToggle } from './components/SceneModeToggle.vue' export { default as MapCompass } from './components/MapCompass.vue' export { default as LayerDirectoryControl } from './components/LayerDirectoryControl.vue' +export { default as MapIcon } from './shared/SvgIcon/index.vue' + export { default as useMapStore } from './stores/mapStore' export { default as useMapUiStore } from './stores/mapUiStore' diff --git a/packages/screen/src/components/SvgIcon/index.vue b/packages/screen/src/map/shared/SvgIcon/index.vue similarity index 100% rename from packages/screen/src/components/SvgIcon/index.vue rename to packages/screen/src/map/shared/SvgIcon/index.vue diff --git a/packages/screen/vite.config.js b/packages/screen/vite.config.js index fa72769..45298ce 100644 --- a/packages/screen/vite.config.js +++ b/packages/screen/vite.config.js @@ -69,7 +69,10 @@ export default defineConfig(({ command, mode }) => { resolvers: [ElementPlusResolver()], }), createSvgIconsPlugin({ - iconDirs: [resolve(__dirname, 'src/assets/icons/svg')], + iconDirs: [ + resolve(__dirname, 'src/assets/icons/svg'), + resolve(__dirname, 'src/map/assets/icons') + ], symbolId: 'icon-[dir]-[name]', }), cesium(),