diff --git a/package.json b/package.json index 5401225..c0adada 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "@amap/amap-jsapi-loader": "^1.0.1", + "DroneCtrl": "1.0.0", "axios": "^1.13.2", "element-plus": "^2.12.0", "vue": "^3.5.24" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 212e405..48d3bcd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@amap/amap-jsapi-loader': specifier: ^1.0.1 version: 1.0.1 + DroneCtrl: + specifier: 1.0.0 + version: 1.0.0 axios: specifier: ^1.13.2 version: 1.13.2 @@ -128,28 +131,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==} @@ -202,7 +201,7 @@ packages: resolution: {integrity: sha512-iHmwV3QcVGGvSC1BG5bZ4z6iwa1SOpAPWmnjOErd4Ske+lZua5K9TtAVdx0gMBClJ28DViCbSmZitjWZsWO3LA==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: - vite: npm:rolldown-vite@7.2.5 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 vue: ^3.2.25 '@vue/compiler-core@3.5.25': @@ -243,6 +242,9 @@ packages: '@vueuse/shared@9.13.0': resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==} + DroneCtrl@1.0.0: + resolution: {integrity: sha512-V3WFJas+oJEv1tG41pbHg3gnG5KdSG7VmL6V3xB+G0PtztHwekTHdNAHcx10rR2mbIFB5ITYGIU3HskOAGvkbA==} + async-validator@4.2.5: resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} @@ -395,28 +397,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==} @@ -765,6 +763,8 @@ snapshots: - '@vue/composition-api' - vue + DroneCtrl@1.0.0: {} + async-validator@4.2.5: {} asynckit@0.4.0: {} diff --git a/src/App.vue b/src/App.vue index e0e1122..ccd60b2 100644 --- a/src/App.vue +++ b/src/App.vue @@ -127,6 +127,12 @@ import AMapLoader from '@amap/amap-jsapi-loader' import { ElMessage, ElMessageBox } from 'element-plus' import { WebSocketClient, MockWebSocketDataGenerator } from './utils/websocket.js' import droneImage from './assets/wrj.jpg' +import { getConfig } from ".//utils/request"; +import DroneCtrl, { + UploadAreaReq +} from 'DroneCtrl'; + +const ctrl = new DroneCtrl.default(getConfig()); // 地图相关 const mapContainer = ref(null) @@ -193,7 +199,7 @@ const initMap = async () => { // 性能优化:节流处理数据更新 let lastUpdateTime = 0 const UPDATE_INTERVAL = 1000 // 3秒更新一次,大幅降低更新频率 - +let conn = null; // 初始化WebSocket连接 const initWebSocket = () => { // 使用模拟数据生成器(因为目前没有真实WebSocket服务器) @@ -235,9 +241,14 @@ const toggleWebSocket = () => { } wsConnected.value = false ElMessage.info('已断开连接') + conn.close(); } else { // 连接 initWebSocket() + conn = ctrl.Message(); + conn.onDroneGPS = (data) => { + console.log(data); + }; } } @@ -709,6 +720,11 @@ const uploadFence = (fenceId) => { } if (pointsData) { + const points = pointsData.points; + ctrl.UploadArea(new UploadAreaReq(points.map(point=>({ + longitude: point[0], + latitude: point[1], + })))); // 输出到控制台 console.log('围栏坐标数据:', pointsData) console.log('围栏坐标数据(JSON):', JSON.stringify(pointsData, null, 2)) diff --git a/src/utils/request.js b/src/utils/request.js index f3c1249..e67a9c9 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -1,125 +1,112 @@ -import axios from 'axios' -import { Notification, MessageBox, Message, Loading } from 'element-ui' -import store from '@/store' -import { getToken } from '@/utils/auth' -import errorCode from '@/utils/errorCode' -import { tansParams, blobValidate } from "@/utils/ruoyi" -import cache from '@/plugins/cache' +import axios from "axios"; +import { ElMessage } from "element-plus"; -// 是否显示重新登录 -export let isRelogin = { show: false } - -axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' -// 创建axios实例 +// 创建 axios 实例 const service = axios.create({ - // axios中请求配置有baseURL选项,表示请求URL公共部分 - baseURL: process.env.VUE_APP_BASE_API, - // 超时 - timeout: 10000 -}) + baseURL: import.meta.env.VITE_APP_BASE_API, + timeout: 50000, + // headers: { "Content-Type": "application/json;charset=utf-8" }, +}); -// request拦截器 -service.interceptors.request.use(config => { - // 是否需要设置 token - const isToken = (config.headers || {}).isToken === false - // 是否需要防止数据重复提交 - const isRepeatSubmit = (config.headers || {}).repeatSubmit === false - // if (getToken() && !isToken) { - // config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改 - // } - // get请求映射params参数 - if (config.method === 'get' && config.params) { - let url = config.url + '?' + tansParams(config.params) - url = url.slice(0, -1) - config.params = {} - config.url = url +const useUserStoreHook = () => { + return { }; +}; + +// 请求拦截器 +service.interceptors.request.use( + (config) => { + return config; + }, + (error) => { + return Promise.reject(error); } - if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) { - const requestObj = { - url: config.url, - data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data, - time: new Date().getTime() - } - const requestSize = Object.keys(JSON.stringify(requestObj)).length // 请求数据大小 - const limitSize = 5 * 1024 * 1024 // 限制存放数据5M - if (requestSize >= limitSize) { - console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制,无法进行防重复提交验证。') - return config - } - const sessionObj = cache.session.getJSON('sessionObj') - if (sessionObj === undefined || sessionObj === null || sessionObj === '') { - cache.session.setJSON('sessionObj', requestObj) - } else { - const s_url = sessionObj.url // 请求地址 - const s_data = sessionObj.data // 请求数据 - const s_time = sessionObj.time // 请求时间 - const interval = 1000 // 间隔时间(ms),小于此时间视为重复提交 - if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) { - const message = '数据正在处理,请勿重复提交' - console.warn(`[${s_url}]: ` + message) - return Promise.reject(new Error(message)) - } else { - cache.session.setJSON('sessionObj', requestObj) - } - } - } - return config -}, error => { - console.log(error) - Promise.reject(error) -}) +); // 响应拦截器 -service.interceptors.response.use(res => { - // 未设置状态码则默认成功状态 - const code = res.data.code || 200 - // 获取错误信息 - const msg = errorCode[code] || res.data.msg || errorCode['default'] - // 二进制数据则直接返回 - if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') { - return res.data - } - if (code === 401) { - if (!isRelogin.show) { - isRelogin.show = true - MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { - isRelogin.show = false - store.dispatch('LogOut').then(() => { - location.href = '/index' - }) - }).catch(() => { - isRelogin.show = false - }) - } - return Promise.reject('无效的会话,或者会话已过期,请重新登录。') - } else if (code === 500) { - Message({ message: msg, type: 'error' }) - return Promise.reject(new Error(msg)) - } else if (code === 601) { - Message({ message: msg, type: 'warning' }) - return Promise.reject('error') - } else if (code !== 200) { - Notification.error({ title: msg }) - return Promise.reject('error') - } else { - return res.data +service.interceptors.response.use( + (response) => { + // 响应数据为二进制流处理(Excel导出) + if (response.data instanceof ArrayBuffer) { + return response; } + + return response.data; }, - error => { - console.log('err' + error) - let { message } = error - if (message == "Network Error") { - message = "后端接口连接异常" - } else if (message.includes("timeout")) { - message = "系统接口请求超时" - } else if (message.includes("Request failed with status code")) { - message = "系统接口" + message.substr(message.length - 3) + "异常" + (error) => { + if (error.response && error.response.data) { + // token 过期,重新登录 + if (error.response.status == 401) { + localStorage.clear(); + ElMessageBox.confirm("当前页面已失效,请重新登录", "提示", { + confirmButtonText: "确定", + type: "warning", + }).then(async () => { + const ipms = new Ipms(getConfig()); + const resp = await ipms.GetAuthAddr(new GetAuthAddrReq()); + window.location.href = + resp.addr + `&redirect=${window.location.origin}/web/login`; + }); + } } - Message({ message: message, type: 'error', duration: 5 * 1000 }) - return Promise.reject(error) + ElMessage.error(error.response.data.msg); + return Promise.reject(error.message); } -) +); +function fetchsomething(url, params) { + return service({ + url: url, + method: params.method, + params: params.method == "GET" ? params.data : null, + responseType: params.responseType, + data: params.data, + headers: params.headers, + }); +} +function upload(url, params) { + const req = new FormData(); + Object.entries(params.data).map((x) => { + const key = x[0]; + const value = x[1]; + if (value == null || value == undefined) { + console.log(key, value); + return; + } + if (typeof value == "string") { + req.append(key, value); + } else if (value instanceof Blob) { + req.append(key, value, "avatar"); + } else if (Array.isArray(value)) { + for (let i = 0; i < value.length; i++) { + req.append(key, value[i]); + } + } else if (value instanceof Object) { + req.append(key, JSON.stringify(value)); + } else { + req.append(key, String(value)); + } + }); + return service({ + url: url, + method: params.method, + params: params.query, + responseType: params.responseType, + data: req, + headers: params.headers, + }); +} -export default service +// export let host = `${window.location.protocol}//${window.location.host}`; +export let host = "http://192.168.3.81:5678"; + +export const getConfig = () => { + return { + host: host, + http_request: fetchsomething, + upload: upload, + }; +}; + +// 导出 axios 实例 +export default service; \ No newline at end of file