mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 02:15:48 +02:00
refactor: improve SSE connection handling and clean up notification component
This commit is contained in:
parent
5aaf8cc36f
commit
a39ec77992
6 changed files with 24 additions and 38 deletions
|
@ -1,17 +1,16 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Notification } from '@/api/notification'
|
import type { Notification } from '@/api/notification'
|
||||||
import type { CustomRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
import type { CustomRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||||
import type { SSEvent } from 'sse.js'
|
|
||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
import notificationApi from '@/api/notification'
|
import notificationApi from '@/api/notification'
|
||||||
import { detailRender } from '@/components/Notification/detailRender'
|
import { detailRender } from '@/components/Notification/detailRender'
|
||||||
|
import { useSSE } from '@/composables/useSSE'
|
||||||
import { NotificationTypeT } from '@/constants'
|
import { NotificationTypeT } from '@/constants'
|
||||||
import { useUserStore } from '@/pinia'
|
import { useUserStore } from '@/pinia'
|
||||||
import { BellOutlined, CheckCircleOutlined, CloseCircleOutlined, DeleteOutlined, InfoCircleOutlined, WarningOutlined } from '@ant-design/icons-vue'
|
import { BellOutlined, CheckCircleOutlined, CloseCircleOutlined, DeleteOutlined, InfoCircleOutlined, WarningOutlined } from '@ant-design/icons-vue'
|
||||||
import { message, notification } from 'ant-design-vue'
|
import { message, notification } from 'ant-design-vue'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||||
import { SSE } from 'sse.js'
|
|
||||||
import notifications from './notifications'
|
import notifications from './notifications'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
@ -22,32 +21,15 @@ dayjs.extend(relativeTime)
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
const { token, unreadCount } = storeToRefs(useUserStore())
|
const { unreadCount } = storeToRefs(useUserStore())
|
||||||
|
|
||||||
const data = ref([]) as Ref<Notification[]>
|
const data = ref([]) as Ref<Notification[]>
|
||||||
|
|
||||||
const sse = shallowRef(newSSE())
|
const { connect } = useSSE()
|
||||||
|
|
||||||
function reconnect() {
|
|
||||||
setTimeout(() => {
|
|
||||||
sse.value = newSSE()
|
|
||||||
}, 5000)
|
|
||||||
}
|
|
||||||
|
|
||||||
function newSSE() {
|
|
||||||
const s = new SSE('api/notifications/live', {
|
|
||||||
headers: {
|
|
||||||
Authorization: token.value,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
s.onmessage = (e: SSEvent) => {
|
|
||||||
const data = JSON.parse(e.data)
|
|
||||||
// data.type may be 0
|
|
||||||
if (data.type === undefined || data.type === null || data.type === '') {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
connect({
|
||||||
|
url: '/api/notifications/live',
|
||||||
|
onMessage: (data: Notification) => {
|
||||||
const typeTrans = {
|
const typeTrans = {
|
||||||
0: 'error',
|
0: 'error',
|
||||||
1: 'warning',
|
1: 'warning',
|
||||||
|
@ -59,13 +41,8 @@ function newSSE() {
|
||||||
message: $gettext(data.title),
|
message: $gettext(data.title),
|
||||||
description: detailRender({ text: data.details, record: data } as CustomRender),
|
description: detailRender({ text: data.details, record: data } as CustomRender),
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
|
})
|
||||||
// reconnect
|
|
||||||
s.onerror = reconnect
|
|
||||||
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
|
@ -6,7 +6,6 @@ import frontendTasks from './tasks/frontend'
|
||||||
export const useSelfCheckStore = defineStore('selfCheck', () => {
|
export const useSelfCheckStore = defineStore('selfCheck', () => {
|
||||||
const data = ref<TaskReport[]>([])
|
const data = ref<TaskReport[]>([])
|
||||||
|
|
||||||
const requestError = ref(false)
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
async function __check() {
|
async function __check() {
|
||||||
|
@ -42,7 +41,6 @@ export const useSelfCheckStore = defineStore('selfCheck', () => {
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
requestError.value = true
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
|
@ -72,7 +70,7 @@ export const useSelfCheckStore = defineStore('selfCheck', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasError = computed(() => {
|
const hasError = computed(() => {
|
||||||
return requestError.value || data.value?.some(item => item.status === ReportStatus.Error)
|
return data.value?.some(item => item.status === ReportStatus.Error)
|
||||||
})
|
})
|
||||||
|
|
||||||
return { data, loading, fixing, hasError, check, fix }
|
return { data, loading, fixing, hasError, check, fix }
|
||||||
|
|
|
@ -25,7 +25,9 @@ export function useSSE() {
|
||||||
* Connect to SSE service
|
* Connect to SSE service
|
||||||
*/
|
*/
|
||||||
function connect(options: SSEOptions) {
|
function connect(options: SSEOptions) {
|
||||||
disconnect()
|
if (token.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
url,
|
url,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import settings from '@/api/settings'
|
import settings from '@/api/settings'
|
||||||
import PageHeader from '@/components/PageHeader/PageHeader.vue'
|
import PageHeader from '@/components/PageHeader/PageHeader.vue'
|
||||||
import { useSettingsStore } from '@/pinia'
|
import { useSettingsStore, useUserStore } from '@/pinia'
|
||||||
import { throttle } from 'lodash'
|
import { throttle } from 'lodash'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import FooterLayout from './FooterLayout.vue'
|
import FooterLayout from './FooterLayout.vue'
|
||||||
|
@ -44,10 +44,13 @@ settings.get_server_name().then(r => {
|
||||||
const breadList = ref([])
|
const breadList = ref([])
|
||||||
|
|
||||||
provide('breadList', breadList)
|
provide('breadList', breadList)
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const { token } = storeToRefs(userStore)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ALayout class="full-screen-wrapper min-h-screen">
|
<ALayout :key="token" class="full-screen-wrapper min-h-screen">
|
||||||
<div class="drawer-sidebar">
|
<div class="drawer-sidebar">
|
||||||
<ADrawer
|
<ADrawer
|
||||||
v-model:open="drawerVisible"
|
v-model:open="drawerVisible"
|
||||||
|
|
|
@ -131,7 +131,7 @@ export function setupResponseInterceptor() {
|
||||||
case 403:
|
case 403:
|
||||||
user.logout()
|
user.logout()
|
||||||
await router.push('/login')
|
await router.push('/login')
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script setup lang="tsx">
|
<script setup lang="tsx">
|
||||||
import cert from '@/api/cert'
|
import cert from '@/api/cert'
|
||||||
import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||||
|
import { useGlobalStore } from '@/pinia'
|
||||||
import { CloudUploadOutlined, SafetyCertificateOutlined } from '@ant-design/icons-vue'
|
import { CloudUploadOutlined, SafetyCertificateOutlined } from '@ant-design/icons-vue'
|
||||||
import RemoveCert from '../components/RemoveCert.vue'
|
import RemoveCert from '../components/RemoveCert.vue'
|
||||||
import WildcardCertificate from '../components/WildcardCertificate.vue'
|
import WildcardCertificate from '../components/WildcardCertificate.vue'
|
||||||
|
@ -8,6 +9,10 @@ import certColumns from './certColumns'
|
||||||
|
|
||||||
const refWildcard = ref()
|
const refWildcard = ref()
|
||||||
const refTable = ref()
|
const refTable = ref()
|
||||||
|
|
||||||
|
const globalStore = useGlobalStore()
|
||||||
|
|
||||||
|
const { processingStatus } = storeToRefs(globalStore)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -25,6 +30,7 @@ const refTable = ref()
|
||||||
<AButton
|
<AButton
|
||||||
type="link"
|
type="link"
|
||||||
size="small"
|
size="small"
|
||||||
|
:disabled="processingStatus.auto_cert_processing"
|
||||||
@click="() => refWildcard.open()"
|
@click="() => refWildcard.open()"
|
||||||
>
|
>
|
||||||
<SafetyCertificateOutlined />
|
<SafetyCertificateOutlined />
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue