工程级MVT地图瓦片服务器Web前端架构设计文档

1. 架构概述

1.1 设计原则

  • 组件化:UI拆分为可复用的独立组件,遵循单一职责原则
  • 模块化:功能按职责分离(Services、Stores、Composables),每个模块独立可维护
  • 状态管理集中化:使用Pinia统一管理应用状态,确保数据流清晰
  • 路由懒加载:按需加载页面,优化首屏性能和用户体验
  • 类型安全:全面使用TypeScript,编译时类型检查,减少运行时错误
  • 国际化支持:基于vue-i18n实现多语言切换,支持中英文

1.2 技术栈

  • 框架: Vue 3.5+ (Composition API)
  • 构建工具: Vite 8.0+ (快速开发服务器和优化构建)
  • 状态管理: Pinia 2.3+ (轻量级类型安全状态管理)
  • 路由: Vue Router 4.5+ (SPA路由管理)
  • UI组件库: Element Plus 2.9+ (企业级UI组件)
  • 地图引擎: MapLibre GL 5.5+ (开源矢量地图渲染)
  • HTTP客户端: Axios 1.9+ (请求拦截和统一错误处理)
  • 国际化: Vue I18n 9.14+ (多语言支持)
  • CSS预处理器: Sass 1.87+ (样式变量和混入)
  • 图标: Element Plus Icons + 自定义SVG图标系统

1.3 架构分层

复制代码
┌─────────────────────────────────────────┐
│          Presentation Layer             │
│     (Views & Components - UI展示)       │
├─────────────────────────────────────────┤
│          Business Logic Layer           │
│        (Composables - 业务逻辑)         │
├─────────────────────────────────────────┤
│          State Management Layer         │
│         (Pinia Stores - 状态管理)       │
├─────────────────────────────────────────┤
│          Service Layer                  │
│      (API Services - 数据访问)          │
├─────────────────────────────────────────┤
│          Infrastructure Layer           │
│  (Router, HTTP Client, i18n, Utils)    │
└─────────────────────────────────────────┘

数据流向

复制代码
用户交互 → Component → Composable → Store → Service → API
                                              ↓
                                         Response
                                              ↓
Store更新 → Composable响应 → Component重新渲染

2. 完整目录结构

复制代码
web/
├── src/
│   ├── main.ts                           # 应用入口(初始化Pinia、Router、i18n、Element Plus)
│   ├── App.vue                           # 根组件(路由视图容器)
│   ├── style.css                         # 全局样式
│   │
│   ├── router/                           # 路由配置
│   │   ├── index.ts                      # 路由实例创建和守卫
│   │   ├── routes.ts                     # 路由定义(懒加载)
│   │   └── guards.ts                     # 路由守卫(可选)
│   │
│   ├── stores/                           # Pinia状态管理
│   │   ├── index.ts                      # Store导出
│   │   ├── app.store.ts                  # 应用全局状态(主题、语言、侧边栏)
│   │   ├── geojson.store.ts              # GeoJSON文件状态(列表、上传状态)
│   │   ├── layer.store.ts                # 图层状态(列表、选中、过滤)
│   │   ├── style.store.ts                # 样式状态(当前编辑、模板)
│   │   └── icon.store.ts                 # 图标状态(列表、上传、选择)
│   │
│   ├── services/                         # API服务层
│   │   ├── index.ts                      # 服务导出
│   │   ├── http.service.ts               # HTTP客户端封装(Axios + 拦截器)
│   │   ├── geojson.service.ts            # GeoJSON文件API
│   │   ├── layer.service.ts              # 图层管理API
│   │   ├── style.service.ts              # 样式配置API
│   │   ├── tile.service.ts               # MVT瓦片URL生成
│   │   └── icon.service.ts               # 图标管理API
│   │
│   ├── views/                            # 页面视图(路由级别组件)
│   │   ├── index.ts                      # 视图导出
│   │   ├── LayerMapView.vue              # 图层管理与地图预览(首页)
│   │   ├── DataUploadView.vue            # 数据上传页面
│   │   ├── StyleEditorView.vue           # 样式编辑页面
│   │   ├── IconManagerView.vue           # 图标管理页面
│   │   └── WorkspaceSettingsView.vue     # 工作空间设置页面
│   │
│   ├── components/                       # 公共组件
│   │   ├── layout/                       # 布局组件
│   │   │   ├── AppHeader.vue             # 应用头部导航
│   │   │   ├── AppSidebar.vue            # 侧边栏菜单
│   │   │   ├── AppFooter.vue             # 应用底部信息
│   │   │   ├── MainLayout.vue            # 主布局容器
│   │   │   └── index.ts                  # 组件导出
│   │   │
│   │   ├── common/                       # 通用组件
│   │   │   ├── LoadingSpinner.vue        # 加载动画
│   │   │   ├── EmptyState.vue            # 空状态展示
│   │   │   ├── ErrorBoundary.vue         # 错误边界
│   │   │   ├── ConfirmDialog.vue         # 确认对话框
│   │   │   ├── FileUploader.vue          # 文件上传组件
│   │   │   ├── SearchBox.vue             # 搜索框组件
│   │   │   ├── Pagination.vue            # 分页组件
│   │   │   └── index.ts                  # 组件导出
│   │   │
│   │   ├── layer/                        # 图层相关组件
│   │   │   ├── LayerList.vue             # 图层列表容器
│   │   │   ├── LayerCard.vue             # 图层卡片展示
│   │   │   ├── LayerSearch.vue           # 图层搜索框
│   │   │   ├── CreateLayerDialog.vue     # 创建图层对话框
│   │   │   └── index.ts                  # 组件导出
│   │   │
│   │   ├── map/                          # 地图相关组件
│   │   │   ├── MapContainer.vue          # MapLibre地图容器
│   │   │   ├── MapControls.vue           # 地图控制按钮(缩放、复位)
│   │   │   ├── LayerVisibilityControl.vue # 图层显隐控制面板
│   │   │   ├── FeaturePopup.vue          # 要素属性弹窗
│   │   │   ├── MapLegend.vue             # 地图图例
│   │   │   ├── ScaleBar.vue              # 比例尺
│   │   │   └── index.ts                  # 组件导出
│   │   │
│   │   ├── style/                        # 样式相关组件
│   │   │   ├── StyleEditor.vue           # 样式编辑器主组件
│   │   │   ├── PointStyleConfig.vue      # 点样式配置
│   │   │   ├── LineStyleConfig.vue       # 线样式配置
│   │   │   ├── PolygonStyleConfig.vue    # 面样式配置
│   │   │   ├── StylePreview.vue          # 样式实时预览
│   │   │   ├── ColorPicker.vue           # 颜色选择器
│   │   │   ├── IconSelector.vue          # 图标选择器
│   │   │   └── index.ts                  # 组件导出
│   │   │
│   │   ├── icon/                         # 图标相关组件
│   │   │   ├── IconGrid.vue              # 图标网格展示
│   │   │   ├── IconCard.vue              # 图标卡片
│   │   │   ├── IconUploadDialog.vue      # 图标上传对话框
│   │   │   ├── IconPreview.vue           # 图标预览
│   │   │   └── index.ts                  # 组件导出
│   │   │
│   │   └── geojson/                      # GeoJSON相关组件
│   │       ├── GeoJSONFileList.vue       # GeoJSON文件列表
│   │       └── index.ts                  # 组件导出
│   │
│   ├── composables/                      # 组合式函数(业务逻辑封装)
│   │   ├── index.ts                      # Composables导出
│   │   ├── useLayers.ts                  # 图层业务逻辑(CRUD、搜索)
│   │   ├── useMap.ts                     # 地图核心逻辑(初始化、图层管理)
│   │   ├── useMapControls.ts             # 地图控制逻辑(缩放、平移)
│   │   ├── useFileUpload.ts              # 文件上传逻辑(验证、进度)
│   │   ├── useStyleEditor.ts             # 样式编辑逻辑(配置、预览)
│   │   ├── useDebounce.ts                # 防抖工具函数
│   │   ├── useLocalStorage.ts            # 本地存储工具
│   │   └── useTranslation.ts             # 国际化翻译工具
│   │
│   ├── types/                            # TypeScript类型定义
│   │   ├── index.ts                      # 类型导出
│   │   ├── api.types.ts                  # API响应/请求类型
│   │   ├── layer.types.ts                # 图层类型(Layer、LayerType等)
│   │   ├── geojson.types.ts              # GeoJSON类型(Feature、Geometry等)
│   │   ├── style.types.ts                # 样式类型(StyleConfig、PointStyle等)
│   │   ├── icon.types.ts                 # 图标类型(Icon、IconMetadata)
│   │   ├── map.types.ts                  # 地图类型(MapConfig、ViewState)
│   │   ├── workspace.types.ts            # 工作空间类型
│   │   ├── common.types.ts               # 通用类型(UUID、DateTime等)
│   │   └── index.ts                      # 类型导出
│   │
│   ├── utils/                            # 工具函数
│   │   ├── index.ts                      # 工具函数导出
│   │   ├── logger.ts                     # 日志工具(分级日志)
│   │   ├── format.ts                     # 格式化工具(文件大小、日期)
│   │   ├── validator.ts                  # 验证工具(GeoJSON、文件类型)
│   │   ├── geojson.ts                    # GeoJSON处理工具
│   │   ├── style.ts                      # 样式处理工具
│   │   ├── file.ts                       # 文件处理工具
│   │   ├── constants.ts                  # 常量定义
│   │   └── helpers.ts                    # 辅助函数
│   │
│   ├── i18n/                             # 国际化配置
│   │   ├── index.ts                      # i18n实例创建
│   │   ├── locales/                      # 语言包
│   │   │   ├── zh-CN.ts                  # 中文语言包
│   │   │   └── en-US.ts                  # 英文语言包
│   │   └── messages.ts                   # 消息键值定义
│   │
│   └── assets/                           # 静态资源
│       ├── styles/                       # 样式文件
│       │   ├── main.scss                 # 主样式(导入所有样式)
│       │   ├── variables.scss            # SCSS变量(颜色、间距、字体)
│       │   ├── mixins.scss               # SCSS混入(Flex、响应式)
│       │   └── reset.scss                # 样式重置
│       │
│       ├── images/                       # 图片资源
│       │   └── logo.png                  # Logo图片
│       │
│       └── icons/                        # SVG图标
│           ├── upload.svg
│           ├── delete.svg
│           ├── edit.svg
│           └── preview.svg
│
├── public/                               # 公共资源(不经过Vite构建)
│   ├── favicon.ico                       # 网站图标
│   ├── favicon.svg                       # SVG图标
│   └── icons.svg                         # 图标精灵
│
├── .env                                  # 环境变量(通用)
├── .env.development                      # 开发环境变量
├── .env.production                       # 生产环境变量
├── package.json                          # 依赖配置
├── tsconfig.json                         # TypeScript配置
├── tsconfig.app.json                     # 应用TS配置
├── tsconfig.node.json                    # Node TS配置
├── vite.config.ts                        # Vite配置(代理、代码分割)
├── index.html                            # HTML模板
└── README.md                             # Web端说明

3. 核心模块说明

3.1 应用入口

src/main.ts

职责

  • 创建Vue应用实例
  • 注册全局插件(Pinia、Vue Router、i18n、Element Plus)
  • 注册Element Plus图标组件
  • 配置全局错误处理器
  • 导入全局样式
  • 挂载应用到DOM

关键代码

typescript 复制代码
const app = createApp(App);
app.use(createPinia());
app.use(router);
app.use(i18n);
app.use(ElementPlus);
// 注册所有Element Plus图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component);
}
app.config.errorHandler = (err, instance, info) => {
  // 全局错误处理
};
app.mount('#app');
src/App.vue

职责

  • 根组件
  • 路由视图容器 (<router-view>)
  • 提供全局布局结构

3.2 路由配置

src/router/index.ts

职责

  • 创建路由实例(createRouter)
  • 配置路由历史模式(createWebHistory)
  • 注册全局路由守卫(可选)
  • 导出路由实例
src/router/routes.ts

职责

  • 定义所有路由规则
  • 配置路由元信息(title、icon、keepAlive)
  • 路由懒加载配置(() => import('@/views/...'))

路由列表

路径 组件 说明
/ LayerMapView 图层管理与地图预览(首页)
/upload DataUploadView 数据上传
/style/:layerId StyleEditorView 样式编辑
/icons IconManagerView 图标管理
/settings WorkspaceSettingsView 工作空间设置

3.3 状态管理 (Pinia Stores)

src/stores/app.store.ts

管理内容

  • 应用主题(light/dark)
  • 语言设置(zh-CN/en-US)
  • 侧边栏展开/折叠状态
  • 全局加载状态
src/stores/geojson.store.ts

管理内容

  • GeoJSON文件列表
  • 文件上传状态(uploading、progress)
  • 文件删除操作
  • 文件解析结果
src/stores/layer.store.ts

管理内容

  • 图层列表(支持分页、搜索过滤)
  • 当前选中图层
  • 图层创建/编辑/删除状态
  • 图层启用/停用状态
  • 图层加载状态

关键特性

  • 支持图层搜索过滤
  • 自动同步后端状态
  • 提供丰富的actions(fetchLayers、createLayer、updateLayer等)
src/stores/style.store.ts

管理内容

  • 当前编辑的样式配置
  • 样式模板列表
  • 样式预览状态
  • 样式保存/重置操作
src/stores/icon.store.ts

管理内容

  • 图标列表(网格展示)
  • 图标上传状态
  • 图标选择状态
  • 图标删除操作

3.4 API服务层

src/services/http.service.ts

职责

  • Axios实例配置(baseURL、timeout)
  • 请求拦截器(添加Token、Request ID)
  • 响应拦截器(统一错误处理、日志记录)
  • HTTP错误分类处理(4xx、5xx、网络错误)

关键特性

  • 自动添加Request ID用于追踪
  • 统一错误消息提示(ElMessage)
  • 支持请求/响应日志(开发环境)
  • 错误重试机制(可选)
src/services/geojson.service.ts

提供方法

  • uploadFile(file: File) - 上传GeoJSON文件
  • deleteFile(id: string) - 删除GeoJSON文件
  • listFiles() - 获取文件列表
  • getFileById(id: string) - 获取单个文件信息
src/services/layer.service.ts

提供方法

  • createLayer(data: CreateLayerDTO) - 创建图层
  • updateLayer(id: string, data: UpdateLayerDTO) - 更新图层
  • deleteLayer(id: string) - 删除图层
  • listLayers(params?: ListParams) - 获取图层列表(支持分页、搜索)
  • getLayerById(id: string) - 获取单个图层
  • toggleLayerStatus(id: string) - 切换图层状态
src/services/style.service.ts

提供方法

  • saveStyle(layerId: string, styleConfig: StyleConfig) - 保存样式
  • getStyle(layerId: string) - 获取图层样式
  • getDefaultStyle(geometryType: string) - 获取默认样式
  • updateStyle(layerId: string, styleConfig: StyleConfig) - 更新样式

特点

  • 样式配置深度合并
  • 支持样式模板应用
  • 自动验证样式配置合法性
src/services/tile.service.ts

提供方法

  • getTileUrl(layerId: string, z: number, x: number, y: number) - 生成MVT瓦片URL
  • getSourceConfig(layerId: string) - 获取MapLibre数据源配置
src/services/icon.service.ts

提供方法

  • uploadIcon(file: File) - 上传图标(SVG/PNG)
  • deleteIcon(id: string) - 删除图标
  • listIcons() - 获取图标列表
  • getIconById(id: string) - 获取单个图标

3.5 页面视图

src/views/LayerMapView.vue

功能

  • 左侧:图层管理面板
  • 右侧:地图预览
  • 集成LayerList和MapContainer组件
src/views/DataUploadView.vue

功能

  • 文件拖拽上传
  • 上传进度显示
  • 上传结果反馈
src/views/StyleEditorView.vue

功能

  • 图层选择
  • 样式可视化配置
  • 实时预览
  • 保存/取消操作
src/views/IconManagerView.vue

功能

  • 图标网格展示
  • 图标上传
  • 图标删除
  • 图标预览
src/views/WorkspaceSettingsView.vue

功能

  • 工作空间路径显示
  • 工作空间路径修改
  • 磁盘使用情况统计

3.6 公共组件

布局组件 (components/layout/)
  • AppHeader.vue: 应用顶部导航栏
  • AppSidebar.vue: 左侧导航菜单
  • AppFooter.vue: 应用底部信息
  • MainLayout.vue: 主布局容器,包含header、sidebar、footer
通用组件 (components/common/)
  • LoadingSpinner.vue: 全局加载动画
  • EmptyState.vue: 空数据状态展示
  • ErrorBoundary.vue: 错误捕获和展示
  • ConfirmDialog.vue: 二次确认对话框
  • FileUploader.vue: 通用文件上传组件
图层组件 (components/layer/)
  • LayerList.vue: 图层列表容器
  • LayerCard.vue: 图层卡片展示
  • LayerItem.vue: 图层列表单项
  • LayerStatusSwitch.vue: 启用/停用开关
  • LayerSearchBox.vue: 搜索过滤框
  • CreateLayerDialog.vue: 创建图层对话框
地图组件 (components/map/)
  • MapContainer.vue: MapLibre GL地图容器
  • MapControls.vue: 地图缩放、平移控制按钮
  • LayerVisibilityControl.vue: 图层显隐控制面板
  • FeaturePopup.vue: 点击要素显示属性
  • MapLegend.vue: 地图图例说明
样式组件 (components/style/)
  • StyleEditor.vue: 样式编辑器主组件
  • PointStyleConfig.vue: 点样式配置面板
  • LineStyleConfig.vue: 线样式配置面板
  • PolygonStyleConfig.vue: 面样式配置面板
  • StylePreview.vue: 样式实时预览
  • ColorPicker.vue: 颜色选择器
  • IconSelector.vue: 图标选择器
  • StyleTemplateList.vue: 预设样式模板列表
图标组件 (components/icon/)
  • IconGrid.vue: 图标网格布局
  • IconCard.vue: 单个图标卡片
  • IconUploadDialog.vue: 图标上传对话框
  • IconPreview.vue: 图标放大预览
上传组件 (components/upload/)
  • UploadZone.vue: 拖拽上传区域
  • UploadProgress.vue: 上传进度条
  • UploadResult.vue: 上传成功/失败结果

3.7 组合式函数 (Composables)

架构定位:Composables是业务逻辑层,封装可复用的状态和逻辑,连接Components和Stores/Services。

src/composables/useLayers.ts

提供功能

  • 图层列表获取和刷新
  • 图层创建/更新/删除操作封装
  • 图层状态切换(active/inactive)
  • 图层搜索过滤逻辑
  • 选中图层管理

使用示例

typescript 复制代码
const { layers, loading, fetchLayers, createLayer, deleteLayer } = useLayers();
src/composables/useMap.ts

提供功能

  • MapLibre GL地图实例初始化
  • 地图事件监听(click、move、zoom)
  • MVT图层添加到地图
  • 图层显隐控制
  • 要素点击查询和Popup显示
  • 地图视图控制(flyTo、fitBounds)
  • 图例数据生成

关键特性

  • 单例模式管理地图实例
  • 自动处理图层样式更新
  • 支持动态添加/移除图层
  • 性能优化(防抖、节流)
src/composables/useMapControls.ts

提供功能

  • 地图缩放控制(zoomIn、zoomOut)
  • 地图复位(resetView)
  • 全屏切换
  • 地图截图(可选)
src/composables/useFileUpload.ts

提供功能

  • 文件选择和验证(类型、大小)
  • 文件上传进度跟踪
  • 上传结果处理(成功/失败)
  • 拖拽上传支持
  • 多文件上传队列管理
src/composables/useStyleEditor.ts

提供功能

  • 样式配置状态管理
  • 样式实时预览(同步到地图)
  • 样式保存/重置/取消
  • 样式模板应用
  • 颜色/图标选择器集成
src/composables/useDebounce.ts

提供功能

  • 防抖函数封装
  • 用于搜索输入优化(减少API请求)
  • 窗口resize事件优化

使用示例

typescript 复制代码
const debouncedSearch = useDebounce(searchQuery, 300);
src/composables/useLocalStorage.ts

提供功能

  • 本地存储读写封装
  • 持久化用户偏好(主题、语言、侧边栏状态)
  • 自动JSON序列化/反序列化
  • 默认值支持
src/composables/useTranslation.ts

提供功能

  • vue-i18n翻译函数封装
  • 简化t()调用
  • 支持动态语言切换

3.8 类型定义

src/types/api.types.ts

定义内容

  • ApiResponse
  • ApiError
  • PaginationParams
src/types/layer.types.ts

定义内容

  • Layer
  • LayerType ('single' | 'group')
  • LayerStatus ('active' | 'inactive')
  • CreateLayerDTO
  • UpdateLayerDTO
src/types/geojson.types.ts

定义内容

  • GeoJSONFile
  • GeometryType
  • FeatureCollection
src/types/style.types.ts

定义内容

  • StyleConfig
  • PointStyle
  • LineStyle
  • PolygonStyle
  • StyleTemplate
src/types/icon.types.ts

定义内容

  • Icon
  • IconMetadata
src/types/common.types.ts

定义内容

  • DateTime
  • UUID
  • Status

3.9 工具函数

src/utils/format.ts

提供函数

  • formatFileSize(bytes) - 格式化文件大小
  • formatDateTime(date) - 格式化日期时间
  • truncateText(text, length) - 文本截断
src/utils/validator.ts

提供函数

  • validateGeoJSON(file) - 验证GeoJSON文件
  • validateIcon(file) - 验证图标文件
  • isValidURL(url) - URL验证
src/utils/geojson.ts

提供函数

  • parseGeoJSON(content) - 解析GeoJSON
  • getGeometryType(geojson) - 获取几何类型
  • countFeatures(geojson) - 统计要素数量
src/utils/style.ts

提供函数

  • mergeStyles(base, override) - 合并样式
  • getDefaultStyle(geometryType) - 获取默认样式
  • validateStyleConfig(style) - 验证样式配置
src/utils/file.ts

提供函数

  • readFileAsText(file) - 读取文件为文本
  • readFileAsArrayBuffer(file) - 读取文件为ArrayBuffer
  • getFileNameWithoutExtension(filename) - 获取无扩展名文件名
src/utils/constants.ts

定义常量

  • MAX_FILE_SIZE
  • ALLOWED_FILE_TYPES
  • DEFAULT_MAP_CONFIG
  • API_BASE_URL

3.10 样式文件

src/assets/styles/main.scss

内容

  • 全局样式
  • 导入variables、mixins、reset
src/assets/styles/variables.scss

内容

  • 颜色变量
  • 字体变量
  • 间距变量
  • 断点变量
src/assets/styles/mixins.scss

内容

  • Flex布局混入
  • 文本省略混入
  • 响应式混入
src/assets/styles/reset.scss

内容

  • CSS Reset
  • Element Plus样式覆盖

4. 模块依赖关系

4.1 依赖层次

复制代码
main.ts
  ├── router/ (路由配置)
  ├── stores/ (状态管理)
  ├── i18n/ (国际化)
  └── App.vue (根组件)
      └── views/ (页面视图)
          ├── components/ (UI组件)
          ├── composables/ (业务逻辑)
          ├── services/ (API服务)
          ├── stores/ (状态访问)
          └── utils/ (工具函数)

4.2 依赖方向规则

  • Views → Components、Composables、Services、Stores
  • Components → Composables、Utils、Types(不直接访问Services/Stores)
  • Composables → Services、Stores、Utils(封装业务逻辑)
  • Services → Types、Utils、HTTP Client(纯数据访问)
  • Stores → Services、Types(状态管理和持久化)
  • Utils → 无依赖(纯函数)

原则

  • 单向依赖,禁止循环依赖
  • 高层模块依赖低层模块
  • 通过Composables解耦Components和Services/Stores

5. 路由设计

5.1 路由列表

路径 组件 说明
/ LayerMapView 图层管理与地图预览(首页)
/upload DataUploadView 数据上传
/style/:layerId StyleEditorView 样式编辑
/icons IconManagerView 图标管理
/settings WorkspaceSettingsView 工作空间设置

5.2 路由元信息

typescript 复制代码
{
  title: '页面标题',
  icon: '图标名称',
  requiresAuth: false, // 未来扩展
  keepAlive: true // 是否缓存
}

6. 状态管理设计

6.1 Store组织结构

复制代码
app.store.ts          # 全局应用状态
  ├── theme
  ├── language
  └── sidebarCollapsed

geojson.store.ts      # GeoJSON文件状态
  ├── fileList
  ├── uploading
  └── uploadProgress

layer.store.ts        # 图层状态
  ├── layerList
  ├── selectedLayer
  ├── loading
  └── filters

style.store.ts        # 样式状态
  ├── currentStyle
  ├── styleTemplates
  └── previewEnabled

icon.store.ts         # 图标状态
  ├── iconList
  ├── selectedIcon
  └── uploading

6.2 Store交互流程

复制代码
用户操作 → Component → Composable → Service → API
                                    ↓
                              Store (更新状态)
                                    ↓
                              Component (响应式更新)

7. 组件通信策略

7.1 Props Down, Events Up

  • 父子组件:props传递数据,emit触发事件

7.2 Provide / Inject

  • 跨层级组件:地图实例、全局配置

7.3 Pinia Store

  • 全局状态:图层列表、用户偏好

7.4 Event Bus (mitt)

  • 非相关组件:地图事件通知

8. 性能优化策略

8.1 路由懒加载

实现方式

typescript 复制代码
const LayerMapView = () => import('@/views/LayerMapView.vue')

效果:首屏只加载必要代码,减少初始包体积

8.2 代码分割 (Vite Rollup)

配置 (vite.config.ts):

typescript 复制代码
manualChunks(id) {
  if (id.includes('node_modules')) {
    if (id.includes('vue') || id.includes('vue-router') || id.includes('pinia')) {
      return 'vendor';  // Vue核心库
    }
    if (id.includes('element-plus')) {
      return 'element';  // UI组件库
    }
    if (id.includes('maplibre-gl')) {
      return 'maplibre';  // 地图引擎
    }
  }
}

效果:第三方库单独打包,利用浏览器缓存

8.3 组件懒加载

实现方式

typescript 复制代码
const MapContainer = defineAsyncComponent(() => 
  import('@/components/map/MapContainer.vue')
)

适用场景:大型组件(如地图容器)、非首屏组件

8.4 防抖和节流

应用场景

  • 搜索输入:300ms防抖,减少API请求
  • 窗口resize:200ms防抖,避免频繁重绘
  • 地图移动事件:节流处理,控制Popup更新频率

实现

typescript 复制代码
const debouncedSearch = useDebounce(searchQuery, 300);

8.5 图片优化

  • SVG图标使用精灵图 (icons.svg)
  • 图标懒加载(Intersection Observer)
  • Element Plus图标按需引入

8.6 MapLibre性能优化

  • MVT瓦片按需加载(视口内瓦片)
  • 图层显隐控制(隐藏图层不渲染)
  • 要素查询优化(限制返回数量)
  • 地图事件防抖(move、zoom事件)

8.7 状态管理优化

  • Pinia持久化(localStorage)减少重复请求
  • 图层列表分页加载(避免一次性加载大量数据)
  • 计算属性缓存(computed)避免重复计算

9. 开发规范

9.1 命名规范

  • 文件命名
    • 组件:PascalCase (LayerList.vue)
    • 工具/服务:camelCase (http.service.ts)
    • Stores:camelCase + .store.ts (layer.store.ts)
    • Composables:camelCase + use前缀 (useLayers.ts)
  • 变量命名 :camelCase (layerListisLoading)
  • 常量命名 :UPPER_SNAKE_CASE (MAX_FILE_SIZEAPI_BASE_URL)
  • 类型命名 :PascalCase (LayerCreateLayerDTO)

9.2 组件设计原则

  • 单一职责:每个组件只负责一个功能
  • 可复用性:通用逻辑提取到Composables
  • 可测试性:业务逻辑与UI分离
  • Props向下,Events向上:父子组件通信标准模式
  • 组件大小:单个组件不超过300行(超过则拆分)

9.3 Composition API使用规范

  • 优先使用 <script setup> 语法
  • 逻辑按功能分组(非选项API的data/methods分组)
  • Composables返回值使用解构赋值
  • 响应式数据明确标注(ref/reactive)

示例

typescript 复制代码
<script setup lang="ts">
import { ref, computed } from 'vue';
import { useLayers } from '@/composables';

const { layers, loading, fetchLayers } = useLayers();
const searchQuery = ref('');

const filteredLayers = computed(() => {
  return layers.value.filter(l => l.name.includes(searchQuery.value));
});
</script>

9.4 样式规范

  • 使用SCSS预处理器
  • BEM命名规范(.layer-list__item--active
  • 避免全局样式污染(使用scoped或CSS Modules)
  • 使用CSS变量管理主题色
  • 响应式设计(移动优先)

9.5 TypeScript规范

  • 严格模式(strict: true)
  • 禁止使用 any 类型(使用unknown或具体类型)
  • 接口命名以 I 开头或使用Type别名
  • DTO类型用于API请求/响应
  • 泛型提高代码复用性

9.6 代码组织

  • 每个函数不超过50行(超过则拆分)
  • 每个文件不超过500行(超过则拆分模块)
  • 导入顺序:Vue → 第三方库 → 内部模块 → 样式
  • 使用绝对路径导入(@/components/...

10. 测试策略

10.1 单元测试

  • 工具函数测试
  • Composables测试
  • Store测试

10.2 组件测试

  • 组件渲染测试
  • 用户交互测试

10.3 E2E测试

  • 关键业务流程测试
  • 使用Cypress或Playwright

11. 国际化支持

11.1 语言包结构

复制代码
locales/
  ├── zh-CN.ts
  └── en-US.ts

11.2 使用方式

typescript 复制代码
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
t('layer.create') // "创建图层"

12. 环境配置

12.1 Vite配置 (vite.config.ts)

关键配置项

typescript 复制代码
export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), '');
  
  return {
    base: env.VITE_BASE_URL || '/',  // 应用基础路径
    
    resolve: {
      alias: {
        '@': path.resolve(__dirname, './src'),  // 路径别名
      },
    },

    server: {
      port: 5173,
      host: '0.0.0.0',
      proxy: {
        '/api': {
          target: 'http://localhost:3000',  // 后端代理
          changeOrigin: true,
        },
      },
    },

    build: {
      outDir: 'dist',
      sourcemap: false,  // 生产环境不生成source map
      chunkSizeWarningLimit: 1000,
      rollupOptions: {
        output: {
          manualChunks(id) {
            // 代码分割配置
          },
        },
      },
    },
  };
});

12.2 环境变量

.env.development (开发环境)
env 复制代码
VITE_BASE_URL=/geoai-geojson-mvt
VITE_API_BASE_URL=http://localhost:3000
VITE_APP_TITLE=GeoAI MVT Manager (Dev)
.env.production (生产环境)
env 复制代码
VITE_BASE_URL=/geoai-geojson-mvt
VITE_API_BASE_URL=/api  # 使用相对路径,由Express提供服务
VITE_APP_TITLE=GeoAI MVT Manager

注意

  • 只有 VITE_ 前缀的变量会暴露给客户端
  • 生产环境API使用相对路径,由后端Express提供代理
  • 开发环境通过Vite Proxy代理到后端服务器

13. 构建与部署

13.1 开发环境

bash 复制代码
cd web
npm install      # 安装依赖
npm run dev      # 启动开发服务器
# 访问 http://localhost:5173/geoai-geojson-mvt

特性

  • 热模块替换 (HMR) - 代码修改即时生效
  • TypeScript类型检查
  • ESLint实时检查(可选)
  • API请求代理到后端 (localhost:3000)

13.2 生产构建

bash 复制代码
npm run build    # 构建生产版本
# 输出到 dist/ 目录

构建产物

复制代码
dist/
├── index.html                    # 入口HTML
├── favicon.ico                   # 网站图标
├── icons.svg                     # 图标精灵
└── assets/
    ├── css/
    │   └── index.[hash].css      # 样式文件(带hash)
    ├── js/
    │   ├── index.[hash].js       # 应用代码
    │   ├── vendor.[hash].js      # Vue核心库
    │   ├── element.[hash].js     # Element Plus
    │   └── maplibre.[hash].js    # MapLibre GL
    └── images/                   # 图片资源

优化

  • 代码压缩和混淆
  • CSS压缩和自动前缀
  • 静态资源带内容hash(长期缓存)
  • Tree Shaking移除未使用代码
  • Source map不生成(减小体积)

13.3 部署方式

方式1:独立部署(开发/测试)
bash 复制代码
npm run preview   # 本地预览生产构建
# 访问 http://localhost:4173
方式2:集成到后端(生产)
  • 构建产物复制到 server/client/ 目录
  • Express提供静态文件服务
  • 打包时由 build/package.js 自动处理

部署流程

bash 复制代码
# 1. 构建前端
cd web && npm run build

# 2. 复制到后端
cp -r dist/* ../server/client/

# 3. 后端打包
cd ../build && npm run package

13.4 Nginx配置(可选)

nginx 复制代码
server {
    listen 80;
    server_name your-domain.com;
    root /var/www/geoai-mvt-web;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;  # SPA路由支持
    }

    location /api {
        proxy_pass http://localhost:3000;  # 后端代理
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

14. 总结

本前端架构设计遵循以下核心原则:

14.1 架构优势

  1. 组件化: UI拆分为细粒度可复用组件,遵循单一职责原则
  2. 模块化: 功能按职责清晰分离(Services、Stores、Composables、Components)
  3. 类型安全: 全面TypeScript覆盖,编译时类型检查,减少运行时错误
  4. 状态管理: Pinia集中管理全局状态,数据流清晰可追踪
  5. 性能优化: 路由懒加载、代码分割、防抖节流、MapLibre瓦片按需加载
  6. 可维护性: 清晰的目录结构、命名规范、Composition API逻辑复用
  7. 国际化: vue-i18n支持多语言切换,易于扩展
  8. 开发体验: Vite HMR快速热更新、TypeScript智能提示、Element Plus组件库

14.2 技术亮点

  • Composition API: 逻辑复用和组织的最佳实践
  • Composables模式: 封装业务逻辑,连接UI和数据层
  • Vite构建: 极速开发服务器和优化生产构建
  • 代码分割: 第三方库单独打包(vendor、element、maplibre)
  • MapLibre集成: 专业GIS地图渲染,MVT瓦片高效加载
  • 响应式设计: SCSS变量和混入,支持主题切换

14.3 关键决策

为什么选择Pinia而非Vuex?

  • 更轻量和现代化
  • 更好的TypeScript支持
  • 更简洁的API(无需mutations)
  • Vue 3官方推荐

为什么使用Composables?

  • 替代Mixins,避免命名冲突
  • 更好的类型推断
  • 逻辑复用更灵活
  • 符合Composition API理念

为什么选择MapLibre GL?

  • 开源免费(Mapbox GL JS的fork)
  • 完整的MVT支持
  • 活跃的社区和维护
  • 与Mapbox API兼容

14.4 可扩展性

当前架构为以下扩展预留空间:

  • ✅ 更多地图图层类型(热力图、聚类图等)
  • ✅ 高级样式编辑器(表达式、数据驱动样式)
  • ✅ 用户认证和权限管理
  • ✅ 协作编辑功能
  • ✅ 离线地图支持(Service Worker)
  • ✅ 移动端适配(响应式布局)
  • ✅ 插件系统(自定义工具栏、面板)

14.5 性能指标

构建产物大小(生产环境):

  • 总大小: ~1-2 MB (压缩后)
  • vendor chunk: ~300 KB (Vue核心)
  • element chunk: ~400 KB (UI组件)
  • maplibre chunk: ~500 KB (地图引擎)
  • app chunk: ~200 KB (应用代码)

运行时性能

  • 首屏加载: < 2s (3G网络)
  • 地图初始化: < 500ms
  • 图层切换: < 100ms
  • 搜索响应: < 300ms (含防抖)
相关推荐
小鹿软件办公1 小时前
Google 在 Chrome 和搜索中加入 SynthID AI 图像检测功能
前端·人工智能·chrome
海兰1 小时前
【实用程序】图片处理服务,前端应用 (Vue 3 + Pinia + Vite)后端服务 (Node.js + Express + Sharp)
前端·javascript·vue.js·node.js·pinia
是谁眉眼1 小时前
css讲解
前端
IT_陈寒1 小时前
Vite热更新失效?我在这坑里卡了一下午
前端·人工智能·后端
代码搬运媛1 小时前
双Token刷新机制详解
前端
一天 24h1 小时前
从单体到分布式:JWT 如何彻底改变 Web 认证系统
前端·分布式
持梦远方1 小时前
Nginx 静态资源挂载与前端部署实战笔记
linux·前端·笔记·nginx
木斯佳1 小时前
前端八股文面经大全:腾讯云智前端一面(2026-05-13)·面经深度解析
前端·状态模式
fanzhonghong1 小时前
javaWeb后端开发之Linux项目部署3和Docker部署1
linux·服务器·前端·docker