From ae2d9b631ffc9bd22d4553badc7493f98e8b7020 Mon Sep 17 00:00:00 2001 From: caill <815519168@qq.com> Date: Thu, 24 Jul 2025 19:08:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9C=B0=E5=9B=BE=E5=92=8C=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config/canvasZoomDrag.js | 128 +++++++++++++++++++++++++ src/config/getData.js | 30 +----- src/config/http.js | 45 ++++++--- src/config/mork.js | 78 ++++++++++++++++ src/pages/modules/device.vue | 33 ++++++- src/pages/modules/map.vue | 176 ++++++++++++++++------------------- src/pages/shells/index.vue | 23 ++++- 7 files changed, 376 insertions(+), 137 deletions(-) create mode 100644 src/config/canvasZoomDrag.js diff --git a/src/config/canvasZoomDrag.js b/src/config/canvasZoomDrag.js new file mode 100644 index 0000000..54a6d0c --- /dev/null +++ b/src/config/canvasZoomDrag.js @@ -0,0 +1,128 @@ +export default { + data () { + return { + touchStart: null, // 触摸起点 + scale: 1, // 缩放比例 + zoomPercentage: 100, // 当前缩放百分比 + isDragging: false, // 是否正在拖动 + lastX: 0, // 上一次鼠标/触摸X位置 + lastY: 0, // 上一次鼠标/触摸Y位置 + offsetX: 0, // Canvas偏移X + offsetY: 0 // Canvas偏移Y + } + }, + methods: { + zoom (step) { + this.scale = Math.min(2, Math.max(0.02, this.scale + step / 100)) + this.zoomPercentage = Math.round(this.scale * 100) + this.applyTransform() + }, + applyTransform () { + this.canvas.style.transform = `translate(${this.offsetX}px, ${this.offsetY}px) scale(${this.scale})` + }, + // 鼠标滚动缩放 + handleZoom (event) { + event.preventDefault() + const delta = event.deltaY + const step = delta > 0 ? -1 : 1 + this.zoom(step) + }, + // 触摸事件修改:支持单指拖动和双指缩放 + handleTouchStart (event) { + // 记录触摸点 + const touches = Array.from(event.touches) + if (touches.length === 1) { + // 单指:准备拖动 + this.isDragging = true + this.lastX = touches[0].clientX + this.lastY = touches[0].clientY + } else if (touches.length === 2) { + // 双指:准备缩放(禁用拖动) + this.isDragging = false + this.touchStart = touches.map(touch => ({ + x: touch.clientX, + y: touch.clientY + })) + } + }, + handleTouchMove (event) { + event.preventDefault() // 阻止页面滚动 + const touches = Array.from(event.touches) + if (this.isDragging && touches.length === 1) { + // 单指拖动 + const currentX = touches[0].clientX + const currentY = touches[0].clientY + // 计算移动距离(考虑缩放影响,拖动速度与缩放比例成反比) + const moveX = (currentX - this.lastX) / this.scale + const moveY = (currentY - this.lastY) / this.scale + // 更新偏移量 + this.offsetX += moveX + this.offsetY += moveY + // 更新上一次位置 + this.lastX = currentX + this.lastY = currentY + // 应用变换 + this.applyTransform() + } else if (this.touchStart && touches.length === 2) { + // 双指缩放(原有逻辑) + const startDist = this.getDistance(this.touchStart[0].x, this.touchStart[0].y, this.touchStart[1].x, this.touchStart[1].y) + const currentDist = this.getDistance(touches[0].clientX, touches[0].clientY, touches[1].clientX, touches[1].clientY) + const step = (currentDist - startDist) / startDist * 10 + this.zoom(step) + // 更新触摸起点 + this.touchStart = touches.map(touch => ({ + x: touch.clientX, + y: touch.clientY + })) + } + }, + // 鼠标按下(开始拖动) + handleMouseDown (event) { + event.preventDefault() + this.isDragging = true + // 记录初始鼠标位置 + this.lastX = event.clientX + this.lastY = event.clientY + // 鼠标样式变为抓手 + this.canvas.style.cursor = 'grabbing' + }, + // 鼠标移动(拖动中) + handleMouseMove (event) { + if (!this.isDragging) return + event.preventDefault() + // 计算移动距离(考虑缩放影响) + const currentX = event.clientX + const currentY = event.clientY + const moveX = (currentX - this.lastX) / this.scale + const moveY = (currentY - this.lastY) / this.scale + // 更新偏移量 + this.offsetX += moveX + this.offsetY += moveY + // 更新上一次位置 + this.lastX = currentX + this.lastY = currentY + // 应用变换 + this.applyTransform() + }, + // 鼠标松开(结束拖动) + handleMouseUp () { + this.isDragging = false + // 恢复鼠标样式 + this.canvas.style.cursor = 'default' + }, + // 计算两点之间的距离 + getDistance (x1, y1, x2, y2) { + return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) + }, + zoomIn () { + if (this.scale < 2) { + this.zoom(8) // 每次放大8% + } + }, + zoomOut () { + if (this.scale > 0.02) { + this.zoom(-8) // 每次缩小8% + } + } + } +} diff --git a/src/config/getData.js b/src/config/getData.js index 48931a2..e0eb070 100644 --- a/src/config/getData.js +++ b/src/config/getData.js @@ -1,4 +1,4 @@ -import {post} from '@config/http.js' +import {post, get} from '@config/http.js' // 登录 export const authlogin = (username, password) => post('auth/login', { @@ -33,29 +33,7 @@ export const updateStation = (code, st) => post('api/operate/updateStation', { station_code: code, station_name: st }) - -export const imageUrl = require('../images/new/apt_map.png') - // 地图 -export const fetchMapData = () => { - let res = { - code: 200, - message: 'success', - data: { - image: imageUrl, - width: 400, - height: 300, - pixelRatio: 1, - leftBottomCoordinate: {x: -100, y: -300} - } - } - return res -} -export const fetchPathData = () => { - let res = { - code: 200, - message: 'success', - data: [{id: 'A', x: '0', y: '-200'}, {id: 'B', x: '100', y: '-250'}] - } - return res -} +export const getMapInfoByCode = () => get('mapInfo/getMapInfoByCode', {}) +export const queryMapAllStation = () => get('station/queryMapAllStation', {}) +export const getRouteInfo = () => get('routeInfo/getRouteInfo', {}) diff --git a/src/config/http.js b/src/config/http.js index 6038160..2d6c863 100644 --- a/src/config/http.js +++ b/src/config/http.js @@ -4,6 +4,10 @@ import i18n from '../i18n/i18n' axios.defaults.timeout = 50000 axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8' +// 补充GET请求默认Content-Type(可选,GET请求通常无需此配置,但部分后端可能需要) +axios.defaults.headers.get['Content-Type'] = 'application/json;charset=UTF-8' + +// 请求拦截器 axios.interceptors.request.use( config => { let token = '' @@ -12,21 +16,17 @@ axios.interceptors.request.use( } token && (config.headers.Authorization = token) if (config.method === 'post') { - if (!config.data.flag) { - config.data = config.data - } else { - config.data = config.data.formData - } + config.data = config.data } - config.headers.post['Accept-Language'] = i18n.locale === 'en-us' ? 'en' : 'zh' + config.headers['Accept-Language'] = i18n.locale === 'en-us' ? 'en' : 'zh' return config }, error => { - // Dialog('错误的传参') return Promise.reject(error) } ) +// 响应拦截器 axios.interceptors.response.use( response => { return Promise.resolve(response) @@ -35,27 +35,48 @@ axios.interceptors.response.use( if (error && error.response) { switch (error.response.status) { case 400: + console.error('请求参数错误') + this.$message.error('请求参数错误') break case 401: + console.error('身份验证失败,即将跳转登录页') break + case 404: + console.error('请求资源不存在') + break + case 500: + console.error('服务器内部错误') + break + default: + console.error('请求失败:', error.response.status) } - return Promise.reject(error.response.data) } else { - return Promise.reject(error) + console.error('网络错误或服务器无响应') } + return Promise.reject(error.response.data || error.message) } ) export const post = (sevmethod, params) => { return new Promise((resolve, reject) => { - axios.post(`${store.getters.baseUrl}/` + sevmethod, params) + axios.post(`${store.getters.baseUrl}/${sevmethod}`, params) .then(response => { resolve(response.data) - }, error => { - reject(error.message) }) .catch((error) => { reject(error) }) }) } + +export const get = (sevmethod, params = {}) => { + return new Promise((resolve, reject) => { + axios.get(`${store.getters.baseUrl}/${sevmethod}`, { params }) + .then(response => { + resolve(response.data) + }) + .catch(error => { + reject(error) + }) + }) +} diff --git a/src/config/mork.js b/src/config/mork.js index 6d3bab4..804cfc2 100644 --- a/src/config/mork.js +++ b/src/config/mork.js @@ -1,3 +1,4 @@ +/* eslint-disable */ export const queryStation = () => { let res = { message: 'ok', @@ -18,3 +19,80 @@ export const updateStation = () => { } return res } +export const queryMapAllStation = () => { + let res = [ + { + "station_id": 1, + "station_code": "A", + "station_name": "A", + "station_type": "STATION", + "action_type": "Customize", + "x": 0.0, + "y": 0.0, + "angle": 0.014406 + }, + { + "station_id": 2, + "station_code": "Goal_21", + "station_name": "Goal_21", + "station_type": "SYSTEM", + "action_type": "Move", + "x": 100.30318, + "y": 0.123685, + "angle": 0.0959 + }, + { + "station_id": 3, + "station_code": "C", + "station_name": "C", + "station_type": "STATION", + "action_type": "Customize", + "x": 200.0227, + "y": 0.316379, + "angle": 0.136773 + } +] + return res +} +export const getRouteInfo = () => { + let res = [ + { + "route_id": 1, + "start_id": 1, + "end_id": 2, + "start_x": 0.0, + "start_y": 0.0, + "end_x": 100.30318, + "end_y": 0.123685, + "navigation_mode": "1", + "route_type": "1" + }, + { + "route_id": 2, + "start_id": 2, + "end_id": 3, + "start_x": -100.30318, + "start_y": 0.123685, + "end_x": 200.0227, + "end_y": 0.316379, + "navigation_mode": "0", + "route_type": "1" + } + ] + return res +} +export const imageUrl = require('../images/new/apt_map.png') +export const getMapInfoByCode = () => { + let res = { + "mapCode": "apt_map_1752651599720.png", + "mapName": "apt_map_1752651599720.png", + "mapImageAddress": imageUrl, + "width": 359.0, + "height": 287.0, + "resolution": 1, + "x": -13.7, + "y": -7.1, + "angle": 0.0 + } + return res +} diff --git a/src/pages/modules/device.vue b/src/pages/modules/device.vue index c5c5a29..063c381 100644 --- a/src/pages/modules/device.vue +++ b/src/pages/modules/device.vue @@ -65,7 +65,8 @@