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(),