diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..356d355 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,132 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +This is the **青岛机场无人驾驶车辆协同云平台** (Qingdao Airport Autonomous Vehicle Collaborative Cloud Platform), a Vue 3 based web application for managing and monitoring autonomous vehicles at Qingdao Airport. The project uses RuoYi-Vue3 as the base framework. + +## Development Commands + +```bash +# Install dependencies +npm install + +# Development server (runs on port 6580) +npm run dev +# or +yarn dev + +# Build for production +npm run build:prod + +# Build for staging +npm run build:stage + +# Preview production build +npm run preview +``` + +**Note**: This project does not have configured linting, testing, or type checking scripts. Manual code review and browser testing are the primary quality assurance methods. + +## Architecture Overview + +### Tech Stack +- **Frontend Framework**: Vue 3.2.45 with Composition API +- **UI Library**: Element Plus 2.2.21 +- **State Management**: Pinia 2.0.22 +- **Router**: Vue Router 4.1.4 +- **Build Tool**: Vite 3.2.3 +- **Map Integration**: OpenLayers 6.15.1 with SuperMap iclient-ol +- **Real-time Communication**: WebSocket + STOMP protocol (@stomp/stompjs, sockjs-client) + +### Key Features +- **Vehicle Management**: Real-time monitoring and control of autonomous vehicles +- **Map Visualization**: OpenLayers-based mapping with SuperMap integration for airport layouts +- **Real-time Data**: WebSocket connections for live vehicle tracking and status updates +- **System Administration**: User management, role-based permissions, operational logs + +### Project Structure + +#### Core Directories +- `src/views/platform/` - Main platform dashboard +- `src/views/car/` - Vehicle management interfaces (monitor, park, type) +- `src/components/map/` - OpenLayers map components and controls +- `src/components/car/` - Vehicle-specific UI components +- `src/api/` - API service definitions organized by domain +- `src/utils/websocket.js` - WebSocket service for real-time communication + +#### Map System Architecture +The mapping system is built around OpenLayers with these key components: + +**Core Map Component**: `src/components/map/OpenLayersMap.vue` +- Initializes map with EPSG:4528 projection for airport coordinates +- Integrates SuperMap tile services for base mapping + +**Control Systems**: +- `VehicleAnimationSystem.vue` - Smooth vehicle movement animations with 60FPS engine +- `VehicleMovementControlRefactored.vue` - Enhanced vehicle tracking with motion prediction +- `LayerSwitcher.vue` - Dynamic layer management +- `VehicleStyleManager.vue` - Vehicle appearance and styling + +**Real-time Features**: +- Motion prediction algorithms for smooth vehicle transitions +- 300ms timeout handling for connection interruptions +- Physical engine simulation based on vehicle speed and direction + +### WebSocket Integration + +The application uses a custom WebSocket service (`src/utils/websocket.js`) for real-time vehicle data: +- Auto-reconnection with configurable intervals +- Event-driven message handling +- Connection state management +- STOMP protocol support for structured messaging + +### Development Server Configuration + +The Vite development server is configured to: +- Run on port 6580 with auto-open +- Proxy API requests to backend servers: + - `/dev-api` → `http://10.0.0.126:8080` (田哥 server) + - Alternative: `http://10.0.0.17:8099` (昊天 server) + +### Map Coordinate System + +The project uses a custom projection `EPSG:4528` for airport mapping: +```javascript +proj4.defs("EPSG:4528", "+proj=tmerc +lat_0=0 +lon_0=120 +k=1 +x_0=40500000 +y_0=0 +ellps=GRS80 +units=m +no_defs"); +``` + +Center coordinates: `[40507885.133754, 4025694.476392]` + +### Component Patterns + +**Global Components** (auto-registered): +- `Pagination` - Standardized pagination +- `RightToolbar` - Table operation toolbar +- `FileUpload` / `ImageUpload` - File handling +- `TreeSelect` - Hierarchical selection +- `DictTag` - Dictionary value display + +**Route Structure**: +- Static routes defined in `src/router/index.js` +- Dynamic routes based on user permissions +- Layout-based routing with nested components + +### Performance Optimizations + +**Vehicle Animation System**: +- `requestAnimationFrame` for 60FPS smooth animations +- Distance threshold checks (0.1m) to avoid unnecessary calculations +- Motion history tracking (3 points) for trajectory prediction +- Easing functions for natural movement curves + +### Known Issues & TODO +As documented in README.md: +1. Left sidebar menu state not preserved on refresh +2. First-level menu missing background color when second-level menu is selected + +### API Backend Integration +- Uses axios for HTTP requests with interceptors +- JWT token authentication via js-cookie +- Centralized error handling and response formatting \ No newline at end of file diff --git a/README.md b/README.md index 78fe374..f735f42 100644 --- a/README.md +++ b/README.md @@ -26,87 +26,6 @@ yarn dev 超图地图开发使用基础 1、前期准备工作熟悉超图地图服务以及基本的操作。 2、熟悉Openlayers以及Leaflet相关操作 -具体代码操作: -1、定义一个地图渲染承载框
-2、定义一个地图实例 map: null, 定义一个渲染位置图层 layer: null -3、初始化地图 -// 初始化地图 -initMap() { - ol.proj.setProj4(proj4); - proj4.defs("EPSG:4528","+proj=tmerc +lat_0=0 +lon_0=120 +k=1 +x_0=40500000 +y_0=0 +ellps=GRS80 +units=m +no_defs"); - var projection = new ol.proj.Projection({ - code: 'EPSG:4528',// 地图坐标系 - }); - this.map = new ol.Map({ - target: 'replay_map',//第一步设置的地图承载框 - controls: ol.control.defaults({ - attribution: false, - rotate: false - }), - view: new ol.View({ - center: [40507885.133754 , 4025694.476392],//地图中心点 - zoom: 12,//初始时的缩放比例 - projection: projection,//坐标系等的设置 - rotation: 0.3 - }), -//图层,这个是后期所有自定义的展示层 - layers: [ - new ol.layer.Tile({ - source: new ol.source.TileSuperMapRest({ - crossOrigin: 'anonymous', - url: this.$map_url, - extent: [40347872.25,2703739.74,40599933.05,5912395.20] - }), - projection: projection, - }) - ] - }); - // 添加位置图层 - this.layer = new ol.layer.Vector({ - source: new ol.source.Vector(), - zIndex: 2, - }); -//把自定义展示的图层放到地图中 - this.map.addLayer(this.layer); -}, -3、图层自定义内容 -//创建一个Feature -const feature = new ol.Feature({ -//以一个点作为示例,可以是点、线、面 - geometry: new ol.geom.Point([item.longitude, item.latitude]), -}); -//定义样式 -feature.setStyle(() => { - //自定义样式 - const style = []; - style.push(this.getStyle(type, item)); - return style; -} -//这个layer就是已开始定义的渲染图层 -this.layer.getSource().addFeature(feature); - -// 得到style实例 -getStyle(type, item, status) { - return new ol.style.Style({ - image: new ol.style.Icon({ - src: getImage(type, item, status), - rotateWithView: true, - scale: this.getScale(type), - rotation: 0, - }), - zIndex: 3, - text: new ol.style.Text({ - font: '12px 微软雅黑', - text: this.getText(type, item), - offsetY: -15, - fill: new ol.style.Fill({ - color: '#515a71', - }), - }), - }); -}, - - @@ -114,17 +33,6 @@ getStyle(type, item, status) { -/** 获取用户列表 */ -function getUserOptions() { - - getRoleUsers(3).then(res => { - userOptions.value = res.rows; - - }); -} - -使用SockJS + STOMP协议 -滑出蓝色 滑入黄色 20250711关键改进说明 1. 平滑动画核心系统 @@ -161,4 +69,13 @@ resetVehicleAnimations():重置所有动画数据 将此组件整合到现有项目中 调用startVehicleSmoothing()启动平滑效果 处理WebSocket消息时继续调用updateVehiclePosition() -当组件隐藏时调用stopVehicleSmoothing()节省资源 \ No newline at end of file +当组件隐藏时调用stopVehicleSmoothing()节省资源 + +### 运行方向分析: + 地图上方(heading=72) + | + | +地图左侧(heading=342) --+-- 地图右侧(heading=162) + | + | + 地图下方(heading=252) \ No newline at end of file diff --git a/public/quyu.json b/public/quyu.json new file mode 100644 index 0000000..ba0745a --- /dev/null +++ b/public/quyu.json @@ -0,0 +1,65 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [120.082584, 36.370196], + [120.085137, 36.370196], + [120.085137, 36.365117], + [120.082584, 36.365117], + [120.082584, 36.370196] + ] + ] + }, + "properties": { + "name": "无人车A测试区域", + "type": "polygon", + "color": "#FF5733" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [120.085765, 36.371484], + [120.087465, 36.371484], + [120.087465, 36.368099], + [120.085765, 36.368099], + [120.085765, 36.371484] + ] + ] + }, + "properties": { + "name": "无人车B测试区域", + "type": "polygon", + "color": "#3374FF" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [120.083, 36.371], + [120.087, 36.371], + [120.087, 36.365], + [120.083, 36.365], + [120.083, 36.371] + ] + ] + }, + "properties": { + "name": "无人车交汇测试区域", + "type": "polygon", + "color": "#33FF57" + } + } + ] + } \ No newline at end of file diff --git a/public/quyu1.json b/public/quyu1.json new file mode 100644 index 0000000..3d5abd2 --- /dev/null +++ b/public/quyu1.json @@ -0,0 +1,49 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 120.08646134220226, + 36.36997466676866 + ], + [ + 120.086830266589, + 36.37063980458865 + ], + [ + 120.08515882034526, + 36.37156622537344 + ], + [ + 120.08543839423878, + 36.37073891647525 + ], + [ + 120.0851419887492, + 36.370416189872486 + ], + [ + 120.0858980160674, + 36.36986114517269 + ], + [ + 120.08646134220226, + 36.36997466676866 + ] + ] + ] + }, + "properties": { + "type": "polygon", + "area": 10388.360616276083, + "perimeter": 452.43662412430064, + "vertices": 6 + } + } + ] +} \ No newline at end of file diff --git a/public/quyu2.json b/public/quyu2.json new file mode 100644 index 0000000..dce8e84 --- /dev/null +++ b/public/quyu2.json @@ -0,0 +1,77 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 120.08483597765024, + 36.36489863472901 + ], + [ + 120.08549104408633, + 36.36594996564427 + ], + [ + 120.08416649728491, + 36.36673180599232 + ], + [ + 120.08378219088705, + 36.36561378252756 + ], + [ + 120.08483597765024, + 36.36489863472901 + ] + ] + ] + }, + "properties": { + "type": "polygon", + "area": 11470.775100380806, + "perimeter": 439.0229879087821, + "vertices": 4 + } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 120.08483597765024, + 36.36489863472901 + ], + [ + 120.08549104408633, + 36.36594996564427 + ], + [ + 120.08416649728491, + 36.36673180599232 + ], + [ + 120.08378219088705, + 36.36561378252756 + ], + [ + 120.08483597765024, + 36.36489863472901 + ] + ] + ] + }, + "properties": { + "type": "polygon", + "area": 11470.775100380806, + "perimeter": 439.0229879087821, + "vertices": 4 + } + } + ] +} \ No newline at end of file diff --git a/src/components/map/controls/LayerSwitcher.vue b/src/components/map/controls/LayerSwitcher.vue index 2f3d2e2..4ca24f7 100644 --- a/src/components/map/controls/LayerSwitcher.vue +++ b/src/components/map/controls/LayerSwitcher.vue @@ -83,6 +83,22 @@ + +