diff --git a/.env.test b/.env.test
index 687478a3..688df37c 100644
--- a/.env.test
+++ b/.env.test
@@ -1,15 +1,16 @@
# backend service base url, test environment
-VITE_SERVICE_BASE_URL=http://127.0.0.1:8080
+VITE_SERVICE_BASE_URL=http://154.44.10.176:8080
VITE_APP_BASE_API=/dev-api
-VITE_APP_WEBSOCKET=true
+VITE_APP_WEBSOCKET=N
+VITE_APP_SSE=Y
# app client id
VITE_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
-VITE_APP_ENCRYPT=true
+VITE_APP_ENCRYPT=Y
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
VITE_APP_RSA_PUBLIC_KEY='MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
diff --git a/src/hooks/common/table.ts b/src/hooks/common/table.ts
index 297bdfaf..f583029f 100644
--- a/src/hooks/common/table.ts
+++ b/src/hooks/common/table.ts
@@ -38,7 +38,10 @@ export function useTable(config: NaiveUI.NaiveTabl
apiParams,
columns: config.columns,
transformer: res => {
- const { rows: records = [], pageNum: current = 1, pageSize: size = 10, total = 0 } = res.data || {};
+ const { rows: records = [], total = 0 } = res.data || {};
+
+ const current = searchParams.pageNum as number;
+ const size = (searchParams.pageSize || 0) as number;
// Ensure that the size is greater than 0, If it is less than 0, it will cause paging calculation errors.
const pageSize = size <= 0 ? 10 : size;
@@ -124,8 +127,8 @@ export function useTable(config: NaiveUI.NaiveTabl
pagination.page = page;
updateSearchParams({
- current: page,
- size: pagination.pageSize!
+ pageNum: page,
+ pageSize: pagination.pageSize!
});
getData();
@@ -135,8 +138,8 @@ export function useTable(config: NaiveUI.NaiveTabl
pagination.page = 1;
updateSearchParams({
- current: pagination.page,
- size: pageSize
+ pageNum: pagination.page,
+ pageSize
});
getData();
@@ -174,8 +177,8 @@ export function useTable(config: NaiveUI.NaiveTabl
});
updateSearchParams({
- current: pageNum,
- size: pagination.pageSize!
+ pageNum,
+ pageSize: pagination.pageSize!
});
await getData();
diff --git a/src/layouts/base-layout/index.vue b/src/layouts/base-layout/index.vue
index f7f05859..3e58cd4e 100644
--- a/src/layouts/base-layout/index.vue
+++ b/src/layouts/base-layout/index.vue
@@ -5,6 +5,7 @@ import type { LayoutMode } from '@sa/materials';
import { useAppStore } from '@/store/modules/app';
import { useThemeStore } from '@/store/modules/theme';
import { initWebSocket } from '@/utils/websocket';
+import { initSSE } from '@/utils/sse';
import GlobalHeader from '../modules/global-header/index.vue';
import GlobalSider from '../modules/global-sider/index.vue';
import GlobalTab from '../modules/global-tab/index.vue';
@@ -105,6 +106,7 @@ function getSiderCollapsedWidth() {
onMounted(() => {
const protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
initWebSocket(`${protocol + window.location.host + import.meta.env.VITE_APP_BASE_API}/resource/websocket`);
+ initSSE(`${import.meta.env.VITE_APP_BASE_API}/resource/sse`);
});
diff --git a/src/layouts/modules/global-header/components/user-avatar.vue b/src/layouts/modules/global-header/components/user-avatar.vue
index a1668afb..5766f345 100644
--- a/src/layouts/modules/global-header/components/user-avatar.vue
+++ b/src/layouts/modules/global-header/components/user-avatar.vue
@@ -50,7 +50,7 @@ function logout() {
positiveText: $t('common.confirm'),
negativeText: $t('common.cancel'),
onPositiveClick: () => {
- authStore.resetStore();
+ authStore.logout();
}
});
}
diff --git a/src/service/api/auth.ts b/src/service/api/auth.ts
index e4f78d77..664faa03 100644
--- a/src/service/api/auth.ts
+++ b/src/service/api/auth.ts
@@ -39,3 +39,17 @@ export function fetchLogin(data: Api.Auth.LoginData) {
export function fetchGetUserInfo() {
return request({ url: '/system/user/getInfo' });
}
+
+/** Logout */
+export function fetchLogout() {
+ if (import.meta.env.VITE_APP_SSE === 'Y') {
+ request({
+ url: '/resource/sse/close',
+ method: 'get'
+ });
+ }
+ return request({
+ url: '/auth/logout',
+ method: 'post'
+ });
+}
diff --git a/src/service/request/index.ts b/src/service/request/index.ts
index 1b942eb0..b338a5a7 100644
--- a/src/service/request/index.ts
+++ b/src/service/request/index.ts
@@ -58,7 +58,7 @@ export const request = createFlatRequest {
routeStore.resetStore();
}
+ async function logout() {
+ await fetchLogout();
+ resetStore();
+ }
+
/**
* Login
*
@@ -147,6 +152,7 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
loginLoading,
resetStore,
login,
+ logout,
initUserInfo
};
});
diff --git a/src/store/modules/route/index.ts b/src/store/modules/route/index.ts
index dca1452d..fa90ffd5 100644
--- a/src/store/modules/route/index.ts
+++ b/src/store/modules/route/index.ts
@@ -264,7 +264,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
setIsInitAuthRoute(true);
} else {
// if fetch user routes failed, reset store
- authStore.resetStore();
+ authStore.logout();
}
}
diff --git a/src/typings/api/api.d.ts b/src/typings/api/api.d.ts
index 80bdf7b3..ed06f877 100644
--- a/src/typings/api/api.d.ts
+++ b/src/typings/api/api.d.ts
@@ -21,7 +21,7 @@ declare namespace Api {
}
/** common search params of table */
- type CommonSearchParams = Pick;
+ type CommonSearchParams = Pick;
/**
* enable status
diff --git a/src/typings/env.d.ts b/src/typings/env.d.ts
index 15550c4c..af918d6e 100644
--- a/src/typings/env.d.ts
+++ b/src/typings/env.d.ts
@@ -104,10 +104,11 @@ declare namespace Env {
/** Used to differentiate storage across different domains */
readonly VITE_STORAGE_PREFIX?: string;
readonly VITE_APP_CLIENT_ID?: string;
- readonly VITE_APP_ENCRYPT?: string;
+ readonly VITE_APP_ENCRYPT?: CommonType.YesOrNo;
readonly VITE_APP_RSA_PUBLIC_KEY?: string;
readonly VITE_APP_RSA_PRIVATE_KEY?: string;
- readonly VITE_APP_WEBSOCKET: string;
+ readonly VITE_APP_WEBSOCKET: CommonType.YesOrNo;
+ readonly VITE_APP_SSE: CommonType.YesOrNo;
}
}
diff --git a/src/utils/service.ts b/src/utils/service.ts
index 651c1179..ed7bbdd9 100644
--- a/src/utils/service.ts
+++ b/src/utils/service.ts
@@ -36,7 +36,7 @@ export function createServiceConfig(env: Env.ImportMeta) {
const config: App.Service.ServiceConfig = {
baseURL: httpConfig.baseURL,
- ws: VITE_APP_WEBSOCKET === 'true',
+ ws: VITE_APP_WEBSOCKET === 'Y',
proxyPattern: VITE_APP_BASE_API,
other: otherConfig
};
diff --git a/src/utils/sse.ts b/src/utils/sse.ts
new file mode 100644
index 00000000..3c9b803f
--- /dev/null
+++ b/src/utils/sse.ts
@@ -0,0 +1,45 @@
+import { useEventSource } from '@vueuse/core';
+import { watch } from 'vue';
+import useNoticeStore from '@/store/modules/notice';
+import { localStg } from './storage';
+
+// 初始化
+export const initSSE = (url: any) => {
+ if (import.meta.env.VITE_APP_SSE === 'N') {
+ return;
+ }
+ const token = localStg.get('token');
+ const sseUrl = `${url}?Authorization=Bearer ${token}&clientid=${import.meta.env.VITE_APP_CLIENT_ID}`;
+ const { data, error } = useEventSource(sseUrl, [], {
+ autoReconnect: {
+ retries: 10,
+ delay: 3000,
+ onFailed() {
+ // eslint-disable-next-line no-console
+ console.error('Failed to connect after 10 retries');
+ }
+ }
+ });
+
+ watch(error, () => {
+ // eslint-disable-next-line no-console
+ console.error('SSE connection error:', error.value);
+ error.value = null;
+ });
+
+ watch(data, () => {
+ if (!data.value) return;
+ useNoticeStore().addNotice({
+ message: data.value,
+ read: false,
+ time: new Date().toLocaleString()
+ });
+ window.$notification?.create({
+ title: '消息',
+ content: data.value,
+ type: 'success',
+ duration: 3000
+ });
+ data.value = null;
+ });
+};
diff --git a/src/utils/websocket.ts b/src/utils/websocket.ts
index 09251b7a..3e63a28a 100644
--- a/src/utils/websocket.ts
+++ b/src/utils/websocket.ts
@@ -32,7 +32,7 @@ let socketError = 0; // 错误次数
// 初始化socket
export function initWebSocket(url: any) {
- if (import.meta.env.VITE_APP_WEBSOCKET === 'false') {
+ if (import.meta.env.VITE_APP_WEBSOCKET === 'N') {
return null;
}
socketUrl = url;
@@ -50,6 +50,7 @@ export function initWebSocket(url: any) {
// socket 连接成功
export function websocketonopen() {
websocket.onopen = () => {
+ // eslint-disable-next-line no-console
console.log('连接 websocket 成功');
resetHeart();
};
@@ -58,14 +59,16 @@ export function websocketonopen() {
// socket 连接失败
export function websocketonerror() {
websocket.onerror = (e: any) => {
- console.log('连接 websocket 失败', e);
+ // eslint-disable-next-line no-console
+ console.error('连接 websocket 失败', e);
};
}
// socket 断开链接
export function websocketclose() {
websocket.onclose = (e: any) => {
- console.log('断开连接', e);
+ // eslint-disable-next-line no-console
+ console.warn('断开连接', e);
};
}
@@ -102,9 +105,11 @@ export function reconnect() {
clearInterval(heartTime);
initWebSocket(socketUrl);
socketError += 1;
+ // eslint-disable-next-line no-console
console.log('socket重连', socketError);
} else {
- console.log('重试次数已用完');
+ // eslint-disable-next-line no-console
+ console.warn('重试次数已用完');
clearInterval(heartTime);
}
}
diff --git a/src/views/_builtin/iframe-page/[url].vue b/src/views/_builtin/iframe-page/[url].vue
index b28c952c..4b10da27 100644
--- a/src/views/_builtin/iframe-page/[url].vue
+++ b/src/views/_builtin/iframe-page/[url].vue
@@ -8,10 +8,12 @@ interface Props {
defineProps();
onMounted(() => {
+ // eslint-disable-next-line no-console
console.log('mounted');
});
onActivated(() => {
+ // eslint-disable-next-line no-console
console.log('activated');
});
diff --git a/src/views/_builtin/login/modules/pwd-login.vue b/src/views/_builtin/login/modules/pwd-login.vue
index bad732e0..0db3ce8d 100644
--- a/src/views/_builtin/login/modules/pwd-login.vue
+++ b/src/views/_builtin/login/modules/pwd-login.vue
@@ -92,7 +92,7 @@ handleFetchCaptchaCode();
-
+