5 changed files with 193 additions and 12 deletions
@ -0,0 +1,3 @@ |
|||
VITE_API_HOST=window.location.hostname |
|||
VITE_API_PORT=80 |
|||
VITE_WS_PATH=/api/v1/app/ws/state |
@ -1,17 +1,20 @@ |
|||
import './style.css' |
|||
import './assets/main.css' |
|||
import "./style.css"; |
|||
import "./assets/main.css"; |
|||
|
|||
import { createApp } from 'vue' |
|||
import { createPinia } from 'pinia' |
|||
import Vant from 'vant' |
|||
import App from './App.vue' |
|||
import router from './router' |
|||
import 'vant/lib/index.css'; |
|||
import { createApp } from "vue"; |
|||
import { createPinia } from "pinia"; |
|||
import Vant from "vant"; |
|||
import App from "./App.vue"; |
|||
import router from "./router"; |
|||
import "vant/lib/index.css"; |
|||
|
|||
const app = createApp(App) |
|||
const app = createApp(App); |
|||
|
|||
app.use(createPinia()) |
|||
app.use(router) |
|||
app.use(createPinia()); |
|||
app.use(router); |
|||
app.use(Vant); |
|||
|
|||
app.mount('#app') |
|||
app.mount("#app"); |
|||
|
|||
console.log("API HOST:", import.meta.env.VITE_API_HOST); |
|||
console.log("API PORT:", import.meta.env.VITE_API_PORT); |
@ -0,0 +1,58 @@ |
|||
import axios from "axios"; |
|||
|
|||
const url = `${window.location.protocol}://${import.meta.env.VITE_API_HOST}:${import.meta.env.VITE_API_PORT}`; |
|||
|
|||
const apiClient = axios.create({ |
|||
baseURL: url, // 设置请求的根路径
|
|||
timeout: 60000, |
|||
headers: { |
|||
"Content-Type": "application/json", |
|||
}, |
|||
}); |
|||
|
|||
// 请求拦截器
|
|||
// apiClient.interceptors.request.use(
|
|||
// (config) => {
|
|||
// const token = sessionStorage.getItem("token");
|
|||
// if (!config.headers) {
|
|||
// config.headers = AxiosHeaders.from({}); // 确保 config.headers 是 AxiosHeaders 类型
|
|||
// }
|
|||
|
|||
// if (token) {
|
|||
// config.headers.set("Authorization", `Bearer ${encodeURIComponent(token)}`); // 使用 set 方法设置 Authorization
|
|||
// }
|
|||
|
|||
// return config;
|
|||
// },
|
|||
// error => {
|
|||
// return Promise.reject(error);
|
|||
// }
|
|||
// );
|
|||
|
|||
// 响应拦截器
|
|||
apiClient.interceptors.response.use( |
|||
(response) => { |
|||
if (response.data && response.data.dataType === "ZAppPromopt") { |
|||
if (response.data.ecode === "USR_NOT_EXIT") { |
|||
return Promise.resolve(response.data); |
|||
} else if (response.data.ecode === "USR_PASSWORD_ERROR") { |
|||
return Promise.resolve(response.data); |
|||
} else { |
|||
console.log("接口出错", response.data); |
|||
// eventBus.emit("show-error-modal", response.data.data);
|
|||
return Promise.reject(response.data); |
|||
} |
|||
} |
|||
return response; |
|||
}, |
|||
error => { |
|||
// eventBus.emit("show-error-modal", {
|
|||
// messageLevel: "Error",
|
|||
// title: "网络请求失败",
|
|||
// info: error.message,
|
|||
// });
|
|||
return Promise.reject(error); |
|||
} |
|||
); |
|||
|
|||
export default apiClient; |
@ -0,0 +1,108 @@ |
|||
import { Subject } from "rxjs"; |
|||
|
|||
export type SocketState = 'open' | 'close' | 'error' |
|||
|
|||
class WebSocketClient { |
|||
private ws: WebSocket | null = null; |
|||
private url: string; |
|||
private reconnectAttempts: number = -1; |
|||
private maxReconnectAttempts: number = 5; |
|||
private reconnectInterval: number = 3000; |
|||
|
|||
readonly dataOb = new Subject() |
|||
readonly stateOb = new Subject<SocketState>() |
|||
|
|||
constructor(url: string) { |
|||
this.url = url; |
|||
} |
|||
|
|||
// 连接 WebSocket
|
|||
connect(): void { |
|||
try { |
|||
// WebSocket.CONNECTING (0) WebSocket.OPEN (1)
|
|||
if (this.ws && this.ws.readyState <= 1) { |
|||
// 已连接
|
|||
console.log(`${this.url} 正在连接或已连接,无需重复连接`); |
|||
} else { |
|||
this.ws = new WebSocket(this.url); |
|||
this.bindEvents(); |
|||
} |
|||
} catch (error) { |
|||
console.error("WebSocket 连接失败:", error); |
|||
this.reconnect(); |
|||
} |
|||
} |
|||
|
|||
// 绑定事件
|
|||
private bindEvents(): void { |
|||
if (!this.ws) return; |
|||
|
|||
// 连接建立时的处理
|
|||
this.ws.onopen = () => { |
|||
console.log("WebSocket 连接已建立"); |
|||
this.reconnectAttempts = -1; // 重置重连次数
|
|||
this.stateOb.next('open') |
|||
}; |
|||
|
|||
// 接收消息的处理
|
|||
this.ws.onmessage = (event: MessageEvent) => { |
|||
try { |
|||
const data = JSON.parse(event.data); |
|||
// console.log('🚀 ~ WebSocketClient ~ bindEvents ~ data:', data)
|
|||
this.dataOb.next(data) |
|||
} catch (error) { |
|||
console.error("消息解析错误:", error); |
|||
} |
|||
}; |
|||
|
|||
this.ws.onclose = () => { |
|||
this.stateOb.next('close') |
|||
console.log("WebSocket 连接已关闭"); |
|||
this.reconnect(); |
|||
}; |
|||
|
|||
this.ws.onerror = error => { |
|||
this.stateOb.next('error') |
|||
console.error("WebSocket 错误:", error); |
|||
}; |
|||
} |
|||
|
|||
// 重连机制
|
|||
private reconnect(): void { |
|||
if (this.reconnectAttempts === -1) { |
|||
this.reconnectAttempts = 0; |
|||
} |
|||
if (this.reconnectAttempts >= this.maxReconnectAttempts) { |
|||
console.log("达到最大重连次数,停止重连"); |
|||
this.reconnectAttempts = -1; |
|||
return; |
|||
} |
|||
|
|||
setTimeout(() => { |
|||
console.log(`尝试第 ${this.reconnectAttempts + 1} 次重连...`); |
|||
this.reconnectAttempts++; |
|||
this.connect(); |
|||
}, this.reconnectInterval); |
|||
} |
|||
|
|||
// 关闭连接
|
|||
disconnect(): void { |
|||
if (this.ws) { |
|||
this.ws.close(); |
|||
this.ws = null; |
|||
} |
|||
} |
|||
} |
|||
|
|||
const urlSocketMap = new Map<string, WebSocketClient>(); |
|||
|
|||
// 导出 WebSocket 客户端
|
|||
export const createWebSocket = (url: string): WebSocketClient => { |
|||
if (urlSocketMap.has(url)) { |
|||
return urlSocketMap.get(url)!; |
|||
} else { |
|||
const client = new WebSocketClient(url); |
|||
urlSocketMap.set(url, client); |
|||
return client; |
|||
} |
|||
}; |
@ -0,0 +1,9 @@ |
|||
export function isValidIPv4(ip: string) { |
|||
const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; |
|||
return ipv4Regex.test(ip); |
|||
} |
|||
export function formatRemainTime(seconds: number) { |
|||
const min = Math.floor(seconds / 60).toFixed(); |
|||
const sec = (seconds % 60).toFixed(); |
|||
return min.padStart(2, "0") + ":" + sec.padStart(2, "0"); |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue