导出方法为sse
This commit is contained in:
parent
199dd3ddb4
commit
800c93602e
@ -13,6 +13,9 @@ VUE_APP_API_DEV = https://dev.api.linkwing.com/api/v1
|
||||
VUE_APP_WS_URL = wss://dev.api.linkwing.com/wss
|
||||
VUE_APP_WSS_URL = wss://dev.api.linkwing.com/wss
|
||||
|
||||
# SSE地址
|
||||
VUE_APP_SSE_URL = https://dev.api.linkwing.com/sse/stream
|
||||
|
||||
# 本地端口
|
||||
VUE_APP_PORT = 2801
|
||||
|
||||
|
||||
@ -5,15 +5,15 @@ NODE_ENV = production
|
||||
VUE_APP_TITLE = 象纬云科
|
||||
|
||||
# 测试环境
|
||||
VUE_APP_API_BASEURL = https://dev.api.linkwing.com/api/v1
|
||||
VUE_APP_API_DEV = https://dev.api.linkwing.com/api/v1
|
||||
VUE_APP_WS_URL = wss://dev.api.linkwing.com/wss
|
||||
VUE_APP_WSS_URL = wss://dev.api.linkwing.com/wss
|
||||
# VUE_APP_API_BASEURL = https://dev.api.linkwing.com/api/v1
|
||||
# VUE_APP_API_DEV = https://dev.api.linkwing.com/api/v1
|
||||
# VUE_APP_WS_URL = wss://dev.api.linkwing.com/wss
|
||||
# VUE_APP_WSS_URL = wss://dev.api.linkwing.com/wss
|
||||
|
||||
# 线上环境
|
||||
# 接口地址 # WS地址
|
||||
# VUE_APP_API_BASEURL = https://prod.api.linkwing.com/api/v1
|
||||
# VUE_APP_API_DEV = https://prod.api.linkwing.com/api/v1
|
||||
# VUE_APP_WS_URL = wss://prod.api.linkwing.com/wss
|
||||
# VUE_APP_WSS_URL = wss://prod.api.linkwing.com/wss
|
||||
VUE_APP_API_BASEURL = https://prod.api.linkwing.com/api/v1
|
||||
VUE_APP_API_DEV = https://prod.api.linkwing.com/api/v1
|
||||
VUE_APP_WS_URL = wss://prod.api.linkwing.com/wss
|
||||
VUE_APP_WSS_URL = wss://prod.api.linkwing.com/wss
|
||||
|
||||
|
||||
@ -16,7 +16,11 @@
|
||||
<div :class="list.length-1==index?'':'exportItem'" v-if="list.length>0 && type == item.type">
|
||||
<div class="exportHeader">
|
||||
<div class="name">{{item.type_desc}}</div>
|
||||
<div class="status" v-if="item.status==0">{{item.msg}}</div>
|
||||
<div class="status" v-if="item.status==0">
|
||||
<el-tooltip effect="dark" :content="item.msg">
|
||||
<span size="mini">{{item.msg}}</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="finish" v-if="item.status==1"><i class="icon"><sc-icon-Finish/></i> 文件生成完成</div>
|
||||
</div>
|
||||
<el-progress class="exportPopover" :text-inside="true" :stroke-width="12" :percentage="item.rate" />
|
||||
@ -24,27 +28,6 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-popover>
|
||||
|
||||
<!-- <div class="customerPopover">-->
|
||||
<!-- <div class="btnBox">-->
|
||||
<!-- <slot></slot>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="contentPopover" v-if="show">-->
|
||||
<!-- <div class="bodyMain">-->
|
||||
<!-- <span class="arrow"></span>-->
|
||||
<!-- <div v-for="(item,index) in list" :key="item">-->
|
||||
<!-- <div :class="list.length-1==index?'':'exportItem'" v-if="list.length>0 && type == item.type">-->
|
||||
<!-- <div class="exportHeader">-->
|
||||
<!-- <div class="name">{{item.type_desc}}</div>-->
|
||||
<!-- <div class="status" v-if="item.status==0">{{item.msg}}</div>-->
|
||||
<!-- <div class="finish" v-if="item.status==1"><i class="icon"><sc-icon-Finish/></i> 文件生成完成</div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <el-progress class="exportPopover" :text-inside="true" :stroke-width="12" :percentage="item.rate" />-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -77,10 +60,14 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
// 获取新消息
|
||||
eventBus.$on('sockBack', this.getWsResult);
|
||||
// eventBus.$on('sockBack', this.getWsResult);
|
||||
|
||||
eventBus.$on('sseBack', this.getWsResult);
|
||||
},
|
||||
unmounted() {
|
||||
eventBus.$off('sockBack', this.getWsResult);
|
||||
// eventBus.$off('sockBack', this.getWsResult);
|
||||
|
||||
eventBus.$off('sseBack', this.getWsResult);
|
||||
},
|
||||
methods:{
|
||||
getWsResult(res){
|
||||
|
||||
@ -10,7 +10,11 @@
|
||||
<div v-if="list.length>0 && type == item.type">
|
||||
<div class="exportHeader">
|
||||
<div class="exportName">{{item.type_desc}}</div>
|
||||
<div class="status" v-if="item.status==0">{{item.msg}}</div>
|
||||
<div class="status" v-if="item.status==0">
|
||||
<el-tooltip effect="dark" :content="item.msg">
|
||||
<span size="mini">{{item.msg}}</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="finish" v-if="item.status==1"><i class="icon"><sc-icon-Finish/></i> 文件生成完成</div>
|
||||
</div>
|
||||
<el-progress class="exportPopover" :text-inside="true" :stroke-width="12" :percentage="item.rate" />
|
||||
@ -40,10 +44,14 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
// 获取新消息
|
||||
eventBus.$on('sockBack', this.getWsResult);
|
||||
// eventBus.$on('sockBack', this.getWsResult);
|
||||
// sse 获取新消息
|
||||
eventBus.$on('sseBack', this.getWsResult);
|
||||
},
|
||||
unmounted() {
|
||||
eventBus.$off('sockBack', this.getWsResult);
|
||||
// eventBus.$off('sockBack', this.getWsResult);
|
||||
|
||||
eventBus.$off('sseBack', this.getWsResult);
|
||||
},
|
||||
methods:{
|
||||
getWsResult(res){
|
||||
|
||||
@ -107,9 +107,13 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
eventBus.$on('sockBack', this.getWsResult);
|
||||
|
||||
// eventBus.$on('sseBack', this.getWsResult);
|
||||
},
|
||||
unmounted() {
|
||||
eventBus.$off('sockBack', this.getWsResult);
|
||||
|
||||
// eventBus.$off('sseBack', this.getWsResult);
|
||||
},
|
||||
methods:{
|
||||
getWsResult(res){
|
||||
|
||||
@ -23,6 +23,8 @@ const DEFAULT_CONFIG = {
|
||||
? process.env.VUE_APP_WS_URL
|
||||
: process.env.VUE_APP_WSS_URL,
|
||||
|
||||
// SSE接口地址
|
||||
SSE_URL:process.env.VUE_APP_SSE_URL,
|
||||
//请求超时
|
||||
TIMEOUT: 10000000,
|
||||
|
||||
|
||||
@ -262,9 +262,14 @@
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
let token = this.$TOOL.cookie.get('TOKEN');
|
||||
if(token && token !== null){
|
||||
this.$seeApi.default.connect();
|
||||
}
|
||||
},
|
||||
unmounted() {
|
||||
this.$seeApi.default.close();
|
||||
|
||||
eventBus.$off('sockBack', this.getWsResult);
|
||||
},
|
||||
watch: {
|
||||
|
||||
@ -51,6 +51,7 @@ import errorHandler from './utils/errorHandler'
|
||||
import * as elIcons from '@element-plus/icons-vue'
|
||||
import * as scIcons from './assets/icons'
|
||||
import * as socketApi from "@/utils/websocket";
|
||||
import * as sseApi from "@/utils/sseService";
|
||||
|
||||
export default {
|
||||
install(app) {
|
||||
@ -62,6 +63,7 @@ export default {
|
||||
app.config.globalProperties.$AUTH = permission;
|
||||
app.config.globalProperties.$ROLE = rolePermission;
|
||||
app.config.globalProperties.$socketApi = socketApi;
|
||||
app.config.globalProperties.$seeApi = sseApi;
|
||||
|
||||
//注册全局组件
|
||||
app.component('scTable', scTable);
|
||||
|
||||
133
src/utils/sseService.js
Normal file
133
src/utils/sseService.js
Normal file
@ -0,0 +1,133 @@
|
||||
// src/utils/sse.js
|
||||
// import store from "../store";
|
||||
import tool from "@/utils/tool";
|
||||
import systemConfig from '@/config';
|
||||
import {eventBus} from "@/utils/eventBus";
|
||||
|
||||
let eventSource = null;
|
||||
let reconnectTimer = null;
|
||||
const reconnectDelay = 5000;
|
||||
let isConnected = false;
|
||||
let lockReconnect = false;
|
||||
const callbacks = new Map();
|
||||
const url = systemConfig.SSE_URL;
|
||||
|
||||
// 改进的连接管理
|
||||
function createSSE(token) {
|
||||
if (isConnected && eventSource) return;
|
||||
|
||||
closeSSE();
|
||||
|
||||
try {
|
||||
let reToken = token === undefined ? tool.cookie.get('TOKEN') : token;
|
||||
if(!reToken) return;
|
||||
eventSource = new EventSource(`${url}?token=${reToken}`);
|
||||
|
||||
// 使用具名函数以便于移除监听器
|
||||
eventSource.onopen = onOpen;
|
||||
eventSource.onmessage = onMessage;
|
||||
eventSource.onerror = onError;
|
||||
|
||||
} catch (error) {
|
||||
console.error('创建SSE连接失败:', error);
|
||||
handleDisconnect();
|
||||
}
|
||||
}
|
||||
|
||||
// 具名事件处理函数
|
||||
function onOpen() {
|
||||
isConnected = true;
|
||||
console.log('SSE连接已建立');
|
||||
}
|
||||
|
||||
function onMessage(event) {
|
||||
try {
|
||||
const res = JSON.parse(event.data);
|
||||
// store.commit('set_sse_msg', data);
|
||||
if(res && res.data){
|
||||
eventBus.$emit('sseBack',res.data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('解析SSE数据失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function onError() {
|
||||
// error
|
||||
// console.error('SSE连接错误:', error);
|
||||
handleDisconnect();
|
||||
}
|
||||
|
||||
// 改进的注册方法
|
||||
function registerCallback(callback, identifier = 'default') {
|
||||
// 清理同名的旧回调
|
||||
if (callbacks.has(identifier)) {
|
||||
callbacks.delete(identifier);
|
||||
}
|
||||
|
||||
callbacks.set(identifier, {
|
||||
fn: callback,
|
||||
// 存储调用栈信息便于调试
|
||||
_debug: new Error().stack.split('\n').slice(1, 4).join('\n')
|
||||
});
|
||||
|
||||
return () => {
|
||||
callbacks.delete(identifier);
|
||||
console.log(`SSE回调 ${identifier} 已取消注册`);
|
||||
};
|
||||
}
|
||||
|
||||
function handleDisconnect() {
|
||||
if (!isConnected) return;
|
||||
|
||||
isConnected = false;
|
||||
// console.log('SSE连接断开,尝试重连...');
|
||||
|
||||
if (!lockReconnect) {
|
||||
lockReconnect = true;
|
||||
clearTimeout(reconnectTimer);
|
||||
reconnectTimer = setTimeout(() => {
|
||||
lockReconnect = false;
|
||||
// 重连时保留现有回调
|
||||
createSSE();
|
||||
}, reconnectDelay);
|
||||
}
|
||||
}
|
||||
function restartSSE(token) {
|
||||
closeSSE();
|
||||
createSSE(token);
|
||||
}
|
||||
|
||||
function closeSSE() {
|
||||
if (eventSource) {
|
||||
// 移除所有监听器
|
||||
eventSource.onopen = null;
|
||||
eventSource.onmessage = null;
|
||||
eventSource.onerror = null;
|
||||
|
||||
eventSource.close();
|
||||
eventSource = null;
|
||||
}
|
||||
isConnected = false;
|
||||
clearTimeout(reconnectTimer);
|
||||
console.log('SSE连接已关闭');
|
||||
}
|
||||
|
||||
// 添加调试方法
|
||||
function debugCallbacks() {
|
||||
callbacks.forEach((value, key) => {
|
||||
console.log(`回调标识: ${key}`);
|
||||
});
|
||||
console.groupEnd();
|
||||
}
|
||||
|
||||
export default {
|
||||
connect: createSSE,
|
||||
onMessage: registerCallback,
|
||||
close: closeSSE,
|
||||
restart: restartSSE,
|
||||
debug: debugCallbacks,
|
||||
get isConnected() {
|
||||
return isConnected;
|
||||
}
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user