diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d02bff6..e198b18 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,8 +18,8 @@ importers: specifier: ^2.3.2 version: 2.3.2(vue@3.5.25) DroneCtrl: - specifier: 1.0.2 - version: 1.0.2 + specifier: 1.0.1 + version: 1.0.1 axios: specifier: ^1.13.2 version: 1.13.2 @@ -137,28 +137,24 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [glibc] '@rolldown/binding-linux-arm64-musl@1.0.0-beta.50': resolution: {integrity: sha512-L0zRdH2oDPkmB+wvuTl+dJbXCsx62SkqcEqdM+79LOcB+PxbAxxjzHU14BuZIQdXcAVDzfpMfaHWzZuwhhBTcw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [musl] '@rolldown/binding-linux-x64-gnu@1.0.0-beta.50': resolution: {integrity: sha512-gyoI8o/TGpQd3OzkJnh1M2kxy1Bisg8qJ5Gci0sXm9yLFzEXIFdtc4EAzepxGvrT2ri99ar5rdsmNG0zP0SbIg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [glibc] '@rolldown/binding-linux-x64-musl@1.0.0-beta.50': resolution: {integrity: sha512-zti8A7M+xFDpKlghpcCAzyOi+e5nfUl3QhU023ce5NCgUxRG5zGP2GR9LTydQ1rnIPwZUVBWd4o7NjZDaQxaXA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [musl] '@rolldown/binding-openharmony-arm64@1.0.0-beta.50': resolution: {integrity: sha512-eZUssog7qljrrRU9Mi0eqYEPm3Ch0UwB+qlWPMKSUXHNqhm3TvDZarJQdTevGEfu3EHAXJvBIe0YFYr0TPVaMA==} @@ -252,8 +248,8 @@ packages: '@vueuse/shared@9.13.0': resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==} - DroneCtrl@1.0.2: - resolution: {integrity: sha512-EQWN1q8S4mN64gMlBQkQyJIYSBVE75YLPsYI+L/67TPypOyGWnI/kxCYMPY1hNVB8sIxJO0Z3DU3wlKxwg4Qiw==} + DroneCtrl@1.0.1: + resolution: {integrity: sha512-3ibzb0sXZGXAkbSTg4Zb8heTx6ASBkWaI2yAO8V+4/Y2ygULruPCzb8o3c89wWlnfQQ/AALWlNmkpVV/ezBujQ==} async-validator@4.2.5: resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} @@ -411,28 +407,24 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] lightningcss-linux-arm64-musl@1.30.2: resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] lightningcss-linux-x64-gnu@1.30.2: resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] lightningcss-linux-x64-musl@1.30.2: resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] lightningcss-win32-arm64-msvc@1.30.2: resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} @@ -781,7 +773,7 @@ snapshots: - '@vue/composition-api' - vue - DroneCtrl@1.0.2: {} + DroneCtrl@1.0.1: {} async-validator@4.2.5: {} diff --git a/src/App.vue b/src/App.vue index cd0cc72..031fd33 100644 --- a/src/App.vue +++ b/src/App.vue @@ -19,12 +19,12 @@
- + - +
-
电子围栏控制
- - -
-
地图类型:
-
- - 普通地图 - - - 卫星地图 - -
-
- - -
-
选择绘制类型:
-
- - 多边形 - - - 矩形 - - - 圆形 - -
-
- - -
-
无人机状态
-
- 连接状态: - - {{ wsConnected ? '已连接' : '未连接' }} - -
-
- 位置: - {{ droneData.latitude?.toFixed(6) }}, {{ droneData.longitude?.toFixed(6) }} -
-
- 高度: - {{ droneData.altitude?.toFixed(1) }}m -
-
- 速度: - {{ droneData.speed?.toFixed(1) }}m/s -
-
- 电量: - {{ droneData.battery?.toFixed(0) }}% -
-
- 围栏状态: - - {{ isInFence ? '围栏内' : '围栏外' }} - -
- - {{ isFlying ? '飞行中' : '起飞' }} - - - {{ wsConnected ? '断开连接' : '开始连接' }} - -
+
电子围栏控制
- -
-
已绘制围栏 ({{ fences.length }})
-
- - {{ fence.name || '未命名围栏' }} - -
- - 上传 - - - 删除 - +
+ +
+
地图类型:
+
+ + 普通地图 + + + 卫星地图 + +
+
+ + +
+
选择绘制类型:
+
+ + 多边形 + + + 矩形 + + + 圆形 + +
+
+ + +
+
无人机状态
+
+ 连接状态: + + {{ wsConnected ? '已连接' : '未连接' }} + +
+
+ 位置: + {{ droneData.latitude?.toFixed(6) }}, {{ droneData.longitude?.toFixed(6) + }} +
+
+ 高度: + {{ droneData.altitude?.toFixed(1) }}m +
+
+ 速度: + {{ droneData.speed?.toFixed(1) }}m/s +
+
+ 电量: + {{ droneData.battery?.toFixed(0) }}% +
+
+ 围栏状态: + + {{ isInFence ? '围栏内' : '围栏外' }} + +
+ + {{ isFlying ? '飞行中' : '起飞' }} + + + {{ wsConnected ? '断开连接' : '开始连接' }} + +
+ + +
+
已绘制围栏 ({{ fences.length }})
+
+ + {{ fence.name || '未命名围栏' }} + +
+ + 上传 + + + 删除 + +
+
+ + 清除所有围栏 + +
- - 清除所有围栏 - -
-
- +
@@ -368,15 +282,6 @@ import { ref, onMounted, onUnmounted, computed } from 'vue' import AMapLoader from '@amap/amap-jsapi-loader' import { ElMessage, ElMessageBox } from 'element-plus' -import { - Upload, - Connection, - Folder, - Download, - ChatLineRound, - Link, - VideoPlay -} from '@element-plus/icons-vue' import { WebSocketClient, MockWebSocketDataGenerator } from './utils/websocket.js' import droneImage from './assets/image/wrj.png' import icon1 from './assets/image/1.png' @@ -387,7 +292,7 @@ import icon5 from './assets/image/5.png' import icon6 from './assets/image/6.png' import icon7 from './assets/image/7.png' import { getConfig } from ".//utils/request"; -import gcoord from 'gcoord'; +import gcoord from 'gcoord'; import DroneCtrl, { UploadAreaReq } from 'DroneCtrl'; @@ -453,12 +358,12 @@ const initMap = async () => { // center: [116.397428, 39.90923], // 默认北京天安门 mapStyle: 'amap://styles/normal' // 默认普通地图 }) - + // 初始化卫星图层(默认显示,因为mapType默认是satellite) const satelliteLayer = new AMap.TileLayer.Satellite() map.add(satelliteLayer) satelliteLayer.show() // 默认显示卫星图层 - + // 保存图层引用以便切换 window.satelliteLayer = satelliteLayer @@ -474,9 +379,9 @@ const initMap = async () => { convert: true, showButton: false }); - + map.addControl(geolocation); - + // 获取当前位置 geolocation.getCurrentPosition(function (status, result) { if (status === 'complete') { @@ -501,7 +406,7 @@ const initMap = async () => { // 地图加载完成后初始化WebSocket // initWebSocket() }) - + console.log('地图初始化成功') } catch (error) { console.error('地图初始化失败:', error) @@ -511,9 +416,9 @@ const initMap = async () => { // 切换地图类型 const switchMapType = (type) => { if (!map) return - + mapType.value = type - + if (type === 'satellite') { // 切换到卫星地图 map.setMapStyle('amap://styles/normal') @@ -571,7 +476,7 @@ const initWebSocket = () => { // const now = Date.now() // // 只更新数据状态,不触发地图更新 // droneData.value = data - + // // 节流:降低地图更新频率 // if (now - lastUpdateTime >= UPDATE_INTERVAL) { // lastUpdateTime = now @@ -590,13 +495,13 @@ const handleTakeoff = () => { // ElMessage.warning('请先绘制电子围栏后再起飞') // return // } - + // // 如果未连接,先连接 // if (!wsConnected.value) { // initWebSocket() // } ctrl.TakeoffAndAutoExecTask({}); - + // 设置飞行状态 isFlying.value = true ElMessage.success('无人机已起飞') @@ -628,15 +533,15 @@ const toggleWebSocket = () => { const drone1 = data.drone_1; const drone2 = data.drone_2; const point = gcoord.transform( - [drone1.longitude, drone1.latitude], - gcoord.WGS84, // 当前坐标系 - gcoord.GCJ02, // 目标坐标系 - ); + [drone1.longitude, drone1.latitude], + gcoord.WGS84, // 当前坐标系 + gcoord.GCJ02, // 目标坐标系 + ); const point2 = gcoord.transform( - [drone2.longitude, drone2.latitude], - gcoord.WGS84, // 当前坐标系 - gcoord.GCJ02, // 目标坐标系 - ); + [drone2.longitude, drone2.latitude], + gcoord.WGS84, // 当前坐标系 + gcoord.GCJ02, // 目标坐标系 + ); console.log(point, point2); // updateDroneMarker(point[0], point[1], drone1.heading); // updateDrone2Marker(point2[0], point2[1], drone2.heading); @@ -694,7 +599,7 @@ const updateDroneMarker = (lng, lat, heading = 0) => { } else { // 更新位置 droneMarker.value.setPosition([lng, lat]) - + // 更新旋转角度(如果有heading数据) if (heading !== undefined) { droneMarker.value.setAngle(heading) @@ -780,9 +685,9 @@ const isPointInRectangle = (point, bounds) => { const [lng, lat] = point const sw = bounds.getSouthWest() const ne = bounds.getNorthEast() - - return lng >= sw.getLng() && lng <= ne.getLng() && - lat >= sw.getLat() && lat <= ne.getLat() + + return lng >= sw.getLng() && lng <= ne.getLng() && + lat >= sw.getLat() && lat <= ne.getLat() } // 检测点是否在圆形内 @@ -793,7 +698,7 @@ const isPointInCircle = (point, center, radius) => { // 计算距离(使用简单的欧几里得距离,对于小范围足够准确) const distance = Math.sqrt( - Math.pow((lng - centerLng) * 111320, 2) + + Math.pow((lng - centerLng) * 111320, 2) + Math.pow((lat - centerLat) * 110540, 2) ) @@ -867,14 +772,14 @@ const WARNING_INTERVAL = 10000 // 10秒内只显示一次警告,避免频繁 const showFenceWarning = () => { const now = Date.now() - + // 防抖:避免频繁警告 if (now - lastWarningTime < WARNING_INTERVAL) { return } - + lastWarningTime = now - + // 使用非阻塞的消息提示,不阻塞UI ElMessage({ message: '警告:无人机已飞出围栏范围,请立即采取措施!', @@ -885,7 +790,7 @@ const showFenceWarning = () => { // 避免重复消息 grouping: true }) - + // 在控制台输出详细警告(可选) console.warn('⚠️ 无人机已飞出围栏范围!', { timestamp: new Date().toLocaleString(), @@ -949,26 +854,26 @@ const handleDrawComplete = (event) => { if (!fence.shape.getMap()) { map.add(fence.shape) } - + // 先设置默认名称,确保列表能立即显示 const defaultName = `${getTypeName(fence.type)}_${fences.value.length + 1}` fence.name = defaultName - + // 保存围栏到列表(立即显示) fences.value.push(fence) - + // 关闭绘制工具,确保不能再继续绘制 // 注意:使用close()而不是close(true),因为true会删除已绘制的图形 if (mouseTool) { mouseTool.close() // 关闭绘制工具,但不删除已绘制的图形 } - + // 先更新样式和标签(使用默认名称) updateFenceStyleAndLabel(fence) - + // 获取当前围栏在数组中的索引,用于后续更新 const fenceIndex = fences.value.length - 1 - + // 弹出输入框让用户输入围栏名称(异步,不阻塞列表显示) ElMessageBox.prompt('请输入围栏名称', '围栏命名', { confirmButtonText: '确定', @@ -1011,11 +916,11 @@ const handleDrawComplete = (event) => { fences.value.splice(fenceIndex, 1) } }) - + // 重置绘制状态 isDrawing.value = false currentDrawType.value = null - + console.log('围栏绘制完成:', fence) } } @@ -1039,7 +944,7 @@ const updateFenceStyleAndLabel = (fence) => { if (!fence.shape.getMap()) { map.add(fence.shape) } - + // 添加围栏名称标签到地图上 addFenceLabel(fence) } @@ -1047,15 +952,15 @@ const updateFenceStyleAndLabel = (fence) => { // 添加围栏名称标签 const addFenceLabel = (fence) => { if (!map || !AMap || !fence.name) return - + // 移除旧的标签(如果存在) if (fence.label) { map.remove(fence.label) } - + // 计算标签位置 let labelPosition = null - + if (fence.type === 'polygon') { // 多边形:使用bounds的右上角(东北角) const bounds = fence.shape.getBounds ? fence.shape.getBounds() : null @@ -1101,7 +1006,7 @@ const addFenceLabel = (fence) => { labelPosition = [centerLng + offset, centerLat + offset] } } - + if (labelPosition) { // 创建文本标签,位置在右上角 const label = new AMap.Text({ @@ -1120,7 +1025,7 @@ const addFenceLabel = (fence) => { }, zIndex: 100 }) - + map.add(label) fence.label = label } @@ -1129,15 +1034,15 @@ const addFenceLabel = (fence) => { // 开始绘制多边形 const startDrawPolygon = () => { if (!mouseTool) return - + // 如果已经在绘制,先关闭之前的绘制工具 if (isDrawing.value && mouseTool) { mouseTool.close(true) } - + isDrawing.value = true currentDrawType.value = 'polygon' - + // 使用高德地图内置工具绘制多边形 mouseTool.polygon({ strokeColor: '#FF0000', @@ -1151,15 +1056,15 @@ const startDrawPolygon = () => { // 开始绘制矩形 const startDrawRectangle = () => { if (!mouseTool) return - + // 如果已经在绘制,先关闭之前的绘制工具 if (isDrawing.value && mouseTool) { mouseTool.close(true) } - + isDrawing.value = true currentDrawType.value = 'rectangle' - + // 使用高德地图内置工具绘制矩形 mouseTool.rectangle({ strokeColor: '#FF0000', @@ -1173,15 +1078,15 @@ const startDrawRectangle = () => { // 开始绘制圆形 const startDrawCircle = () => { if (!mouseTool) return - + // 如果已经在绘制,先关闭之前的绘制工具 if (isDrawing.value && mouseTool) { mouseTool.close(true) } - + isDrawing.value = true currentDrawType.value = 'circle' - + // 使用高德地图内置工具绘制圆形 mouseTool.circle({ strokeColor: '#FF0000', @@ -1276,11 +1181,11 @@ const uploadFence = (fenceId) => { // 圆形:获取圆心和半径 const center = fence.shape.getCenter ? fence.shape.getCenter() : fence.center const radius = fence.shape.getRadius ? fence.shape.getRadius() : fence.radius - + if (center) { const centerLng = center.getLng ? center.getLng() : (center.lng || center[0]) const centerLat = center.getLat ? center.getLat() : (center.lat || center[1]) - + pointsData = { type: 'circle', id: fence.id, @@ -1293,7 +1198,7 @@ const uploadFence = (fenceId) => { } if (pointsData) { - const points = pointsData.points.map(point=> { + const points = pointsData.points.map(point => { const wgsPoint = gcoord.transform( point, // 原始坐标 gcoord.GCJ02, // 当前坐标系 @@ -1303,28 +1208,28 @@ const uploadFence = (fenceId) => { }); console.log(points) - ctrl.UploadArea(new UploadAreaReq(points.map(point=>({ + ctrl.UploadArea(new UploadAreaReq(points.map(point => ({ longitude: point[0], latitude: point[1], })))); // 输出到控制台 console.log('围栏坐标数据:', pointsData) console.log('围栏坐标数据(JSON):', JSON.stringify(pointsData, null, 2)) - + // 可以在这里添加实际的上传逻辑,比如发送到服务器 // await uploadToServer(pointsData) - + // 提示用户 - const message = pointsData.type === 'circle' + const message = pointsData.type === 'circle' ? `围栏坐标数据已获取!\n类型: ${getTypeName(pointsData.type)}\n圆心: [${pointsData.center[0]}, ${pointsData.center[1]}]\n半径: ${pointsData.radius}米` : `围栏坐标数据已获取!\n类型: ${getTypeName(pointsData.type)}\n顶点数量: ${pointsData.pointCount}\n请查看控制台获取完整数据` - + ElMessage.success({ message: message, duration: 3000, showClose: true }) - + return pointsData } else { console.error('无法获取围栏坐标数据') @@ -1354,9 +1259,9 @@ const generateCirclePoints = (centerLng, centerLat, radius, segments = 32) => { const removeFence = (fenceId) => { const index = fences.value.findIndex(f => f.id === fenceId) if (index === -1) return - + const fence = fences.value[index] - + // 直接从地图上移除(同步操作,快速完成) if (fence && fence.shape) { try { @@ -1373,17 +1278,17 @@ const removeFence = (fenceId) => { } } ctrl.ClearArea({}); - + // 从列表中移除 fences.value.splice(index, 1) - + console.log('围栏已删除:', fenceId, '剩余围栏数量:', fences.value.length) } // 从地图上移除围栏(优化版本:只使用最有效的方法) const removeFenceFromMap = (fence) => { if (!fence || !fence.shape) return - + try { // 只使用最有效的方法:map.remove const currentMap = fence.shape.getMap ? fence.shape.getMap() : null @@ -1411,7 +1316,7 @@ const clearAllFences = async () => { } ) await ctrl.ClearArea({}); - + // 先清除地图上的所有图形 const fencesToRemove = [...fences.value] // 创建副本避免遍历时修改数组 fencesToRemove.forEach(fence => { @@ -1430,13 +1335,13 @@ const clearAllFences = async () => { } } }) - + // 清空围栏列表 fences.value = [] - + // 清除无人机轨迹 clearDroneTrack() - + console.log('所有围栏已清除,当前围栏数量:', fences.value.length) ElMessage.success('所有围栏已清除') } catch (error) { @@ -1477,7 +1382,7 @@ onUnmounted(() => { wsClient.close() wsClient = null } - + // 清理地图 if (droneMarker.value) { map?.remove(droneMarker.value) @@ -1487,7 +1392,7 @@ onUnmounted(() => { map?.remove(drone2Marker.value) drone2Marker.value = null } - + if (mouseTool) { mouseTool.close() } @@ -1583,17 +1488,35 @@ onUnmounted(() => { /* 左侧面板(覆盖层) */ .left-panel { + /* background: url('./assets/image/z1.png') no-repeat center center; */ position: absolute; left: 0; top: 0; bottom: 0; - width: 320px; padding: 20px; overflow-y: auto; z-index: 100; display: flex; flex-direction: column; justify-content: center; + + :nth-child(1) { + background: url('./assets/image/z1.png') no-repeat center center; + width: 320px; + height: 270px; + } + + :nth-child(2) { + background: url('./assets/image/z2.png') no-repeat center center; + width: 320px; + height: 270px; + } + + :nth-child(3) { + background: url('./assets/image/z3.png') no-repeat center center; + width: 320px; + height: 270px; + } } /* 右侧面板(覆盖层) */ @@ -1609,11 +1532,29 @@ onUnmounted(() => { display: flex; flex-direction: column; justify-content: center; + + :nth-child(1) { + background: url('./assets/image/y1.png') no-repeat center center; + width: 320px; + height: 270px; + } + + :nth-child(2) { + background: url('./assets/image/y2.png') no-repeat center center; + width: 320px; + height: 270px; + } + + :nth-child(3) { + background: url('./assets/image/y3.png') no-repeat center center; + width: 320px; + height: 270px; + } } /* 信息面板 */ .info-panel { - background: rgba(36, 39, 56, 0.7); + background: rgba(36, 39, 56, 0.7); border-radius: 8px; padding: 16px; margin-bottom: 16px; @@ -1983,14 +1924,12 @@ onUnmounted(() => { /* 底部导航栏 */ .bottom-footer { - height: 55px; - background:#0a0e27; + background: #0a0e27; backdrop-filter: blur(15px); border-top: 1px solid rgba(255, 255, 255, 0.15); display: flex; align-items: center; justify-content: space-between; - padding: 0 40px; z-index: 1000; position: relative; box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1); @@ -2124,4 +2063,3 @@ onUnmounted(() => { background: rgba(255, 255, 255, 0.5); } - diff --git a/src/assets/image/d1.png b/src/assets/image/d1.png new file mode 100644 index 0000000..5c640ce Binary files /dev/null and b/src/assets/image/d1.png differ diff --git a/src/assets/image/d2.png b/src/assets/image/d2.png new file mode 100644 index 0000000..9c791c6 Binary files /dev/null and b/src/assets/image/d2.png differ diff --git a/src/assets/image/i1.png b/src/assets/image/i1.png new file mode 100644 index 0000000..bfe9a56 Binary files /dev/null and b/src/assets/image/i1.png differ diff --git a/src/assets/image/i2.png b/src/assets/image/i2.png new file mode 100644 index 0000000..e732aa7 Binary files /dev/null and b/src/assets/image/i2.png differ diff --git a/src/assets/image/i3.png b/src/assets/image/i3.png new file mode 100644 index 0000000..03e08a3 Binary files /dev/null and b/src/assets/image/i3.png differ diff --git a/src/assets/image/i4.png b/src/assets/image/i4.png new file mode 100644 index 0000000..12e657f Binary files /dev/null and b/src/assets/image/i4.png differ diff --git a/src/assets/image/i5.png b/src/assets/image/i5.png new file mode 100644 index 0000000..44f4ed1 Binary files /dev/null and b/src/assets/image/i5.png differ diff --git a/src/assets/image/wrj2.png b/src/assets/image/wrj2.png new file mode 100644 index 0000000..8f02f7b Binary files /dev/null and b/src/assets/image/wrj2.png differ diff --git a/src/assets/image/y1.png b/src/assets/image/y1.png new file mode 100644 index 0000000..546e0bd Binary files /dev/null and b/src/assets/image/y1.png differ diff --git a/src/assets/image/y2.png b/src/assets/image/y2.png new file mode 100644 index 0000000..cacdbb5 Binary files /dev/null and b/src/assets/image/y2.png differ diff --git a/src/assets/image/y3.png b/src/assets/image/y3.png new file mode 100644 index 0000000..00f4bc5 Binary files /dev/null and b/src/assets/image/y3.png differ diff --git a/src/assets/image/z1.png b/src/assets/image/z1.png new file mode 100644 index 0000000..87f7d4f Binary files /dev/null and b/src/assets/image/z1.png differ diff --git a/src/assets/image/z2.png b/src/assets/image/z2.png new file mode 100644 index 0000000..d6e15ba Binary files /dev/null and b/src/assets/image/z2.png differ diff --git a/src/assets/image/z3.png b/src/assets/image/z3.png new file mode 100644 index 0000000..1cf476f Binary files /dev/null and b/src/assets/image/z3.png differ