Commit d7899a86 authored by xinzhedeai's avatar xinzhedeai

add:401;token;axios;websocket;

parent 4aadfa22
import axios from "axios";
const tokenAxios = axios.create({
baseURL: '/api',
})
export const getTokenApi = ()=> tokenAxios.get('/token')
\ No newline at end of file
import Vue from 'vue' import Vue from 'vue'
import Router from 'vue-router' import Router from 'vue-router'
import { connect } from '@/utils/webSocket.js'
import {localStg} from '@/utils/storage.js'
Vue.use(Router) Vue.use(Router)
/* Layout */ /* Layout */
...@@ -189,8 +190,23 @@ Router.prototype.replace = function push(location) { ...@@ -189,8 +190,23 @@ Router.prototype.replace = function push(location) {
return routerReplace.call(this, location).catch(err => err) return routerReplace.call(this, location).catch(err => err)
} }
export default new Router({ const router = new Router({
mode: 'history', // 去掉url中的# mode: 'history', // 去掉url中的#
scrollBehavior: () => ({ y: 0 }), scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes routes: constantRoutes
}) })
// 路由守卫中初始化WebSocket连接
router.beforeEach((to, from, next) => {
console.log('路由守卫中初始化WebSocket连接', to, from, next )
// 只有在用户登录后才初始化WebSocket连接(根据实际情况调整条件)
// const token = localStg.get('token')
// if (token && !wsManager.isOpen()) {
// wsManager.init(wsUrl)
connect()
// }
next()
})
export default router
\ No newline at end of file
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 { saveAs } from 'file-saver'
import { sendMsg } from './webSocket'
let downloadLoadingInstance;
// 是否显示重新登录
export let isRelogin = { show: false };
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: process.env.VUE_APP_BASE_API,
// 超时
timeout: 60000
})
// 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;
}
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) {
sendMsg('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
}
},
error => {
sendMsg('401')
// 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) + "异常";
// }
// Message({ message: message, type: 'error', duration: 5 * 1000 })
// return Promise.reject(error)
}
)
// 通用下载方法
export function download(url, params, filename, config) {
downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
return service.post(url, params, {
transformRequest: [(params) => { return tansParams(params) }],
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
responseType: 'blob',
...config
}).then(async (data) => {
const isBlob = blobValidate(data);
if (isBlob) {
const blob = new Blob([data])
saveAs(blob, filename)
} else {
const resText = await data.text();
const rspObj = JSON.parse(resText);
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
Message.error(errMsg);
}
downloadLoadingInstance.close();
}).catch((r) => {
console.error(r)
Message.error('下载文件出现错误,请联系管理员!')
downloadLoadingInstance.close();
})
}
export default service
/**
* localStorage 操作工具库
* 提供完整的增删改查功能,支持类型转换、错误处理和过期时间设置
*/
/**
* 存储数据到 localStorage
* @param {string} key 存储键名
* @param {*} value 要存储的值
* @param {number} expire 过期时间(毫秒),0表示永不过期
* @returns {boolean} 是否存储成功
*/
export const set = (key, value) => {
localStorage.setItem(key, value);
};
/**
* 从 localStorage 获取数据
* @param {string} key 存储键名
* @param {*} defaultValue 默认值,当键不存在或已过期时返回
* @returns {*} 存储的值或默认值
*/
export const get = (key, defaultValue = null) => {
const itemStr = localStorage.getItem(key);
return itemStr;
};
// 默认导出所有方法
export const localStg = {
set,
get,
}
\ No newline at end of file
let severName = 'ai';
let ws = null;
// 定义WebSocket连接的URL
var webSocketUrl = `ws://192.168.2.53:8080/ws/${severName}`;
export function connect() {
if ('WebSocket' in window) {
ws = new WebSocket(webSocketUrl);
// 连接成功时触发
ws.onopen = function (event) {
console.log('WebSocket连接成功');
// 可以在这里发送消息给服务器
// websocket.send('消息内容');
};
// 接收到消息时触发
ws.onmessage = function (event) {
console.log('收到服务器消息:', event.data);
// 处理收到的消息
};
// 连接关闭时触发
ws.onclose = function (event) {
console.log('WebSocket连接关闭');
// 连接关闭后可以进行重连等操作
};
// 连接发生错误时触发
ws.onerror = function (event) {
console.error('WebSocket连接发生错误:', event);
};
} else {
console.error('当前浏览器不支持WebSocket');
}
}
export function sendMsg(msg) {
ws.send(msg);
}
// WebSocket 连接管理类
class WebSocketManager {
constructor() {
this.ws = null
this.reconnectAttempts = 0
this.maxReconnectAttempts = 5
this.reconnectInterval = 3000 // 3秒后重连
this.listeners = {}
this.isConnecting = false
this.severName = 'ai';
// 定义WebSocket连接的URL
this.webSocketUrl = `ws://192.168.2.53:8080/ws/${this.severName}`;
}
// 初始化WebSocket连接
init() {
const url = this.webSocketUrl
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
console.log('WebSocket连接已存在')
return
}
if (this.isConnecting) return
this.isConnecting = true
try {
this.ws = new WebSocket(url)
this.ws.onopen = () => {
console.log('WebSocket连接已建立')
this.isConnecting = false
this.reconnectAttempts = 0
this.emit('open')
}
this.ws.onmessage = (event) => {
try {
const data = JSON.parse(event.data)
this.emit('message', data)
// 可以根据消息类型分发到不同的监听器
if (data.type) {
this.emit(`message:${data.type}`, data)
}
} catch (error) {
console.error('WebSocket消息解析错误:', error)
this.emit('error', error)
}
}
this.ws.onclose = () => {
console.log('WebSocket连接已关闭')
this.isConnecting = false
this.emit('close')
this.attemptReconnect(url)
}
this.ws.onerror = (error) => {
console.error('WebSocket连接错误:', error)
this.isConnecting = false
this.emit('error', error)
}
} catch (error) {
console.error('WebSocket初始化失败:', error)
this.isConnecting = false
this.attemptReconnect(url)
}
}
// 重连机制
attemptReconnect(url) {
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
console.error('WebSocket重连次数已达上限')
return
}
this.reconnectAttempts++
console.log(`WebSocket将在${this.reconnectInterval}ms后尝试第${this.reconnectAttempts}次重连`)
setTimeout(() => {
this.init(url)
}, this.reconnectInterval)
}
// 发送消息
send(data) {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
const message = typeof data === 'string' ? data : JSON.stringify(data)
this.ws.send(message)
return true
}
console.error('WebSocket连接未建立,无法发送消息')
return false
}
// 关闭连接
close() {
if (this.ws) {
this.ws.close()
this.ws = null
}
}
// 事件监听相关方法
on(event, callback) {
if (!this.listeners[event]) {
this.listeners[event] = []
}
this.listeners[event].push(callback)
}
off(event, callback) {
if (this.listeners[event]) {
if (callback) {
this.listeners[event] = this.listeners[event].filter(cb => cb !== callback)
} else {
delete this.listeners[event]
}
}
}
emit(event, data) {
if (this.listeners[event]) {
this.listeners[event].forEach(callback => {
try {
callback(data)
} catch (error) {
console.error(`WebSocket事件${event}处理错误:`, error)
}
})
}
}
// 获取连接状态
getReadyState() {
return this.ws ? this.ws.readyState : WebSocket.CLOSED
}
// 连接是否打开
isOpen() {
return this.getReadyState() === WebSocket.OPEN
}
}
// 创建单例WebSocket管理器实例
const wsManager = new WebSocketManager()
// 将WebSocket管理器挂载到Vue原型上,使其在所有组件中可用
Vue.prototype.$ws = wsManager
// 导出WebSocket管理器实例供其他模块使用
export { wsManager }
\ No newline at end of file
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
</template> </template>
<script> <script>
import { getTokenApi } from "@/api/token";
import { localStg } from "@/utils/storage";
export default { export default {
name: "Index", name: "Index",
data() { data() {
...@@ -42,6 +44,18 @@ export default { ...@@ -42,6 +44,18 @@ export default {
// 组件挂载后初始化地图 // 组件挂载后初始化地图
this.initCesium(); this.initCesium();
}, },
beforeMount() {
localStg.set("token", 222233);
if (localStg.get("token")) {
return;
}
// 组件挂载前获取token
getTokenApi().then((res) => {
console.log("token", res);
localStg.set("token", res.data.data);
});
},
beforeDestroy() { beforeDestroy() {
// 组件销毁前清理地图资源 // 组件销毁前清理地图资源
if (this.viewer) { if (this.viewer) {
......
...@@ -46,6 +46,10 @@ module.exports = { ...@@ -46,6 +46,10 @@ module.exports = {
["^" + process.env.VUE_APP_BASE_API]: "", ["^" + process.env.VUE_APP_BASE_API]: "",
}, },
}, },
'/api': {
target: `http://192.168.2.53:8080`, // 中控平台
changeOrigin: true,
},
}, },
disableHostCheck: true, disableHostCheck: true,
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment