mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-08-28 19:47:49 +08:00
fix(connection): hide reconnecting notification
This commit is contained in:
@@ -9,49 +9,35 @@ const { connectionStatus, connectionReason } = useGlobalOfflineStatus()
|
|||||||
const { isRestarting } = useSystemRestartStatus()
|
const { isRestarting } = useSystemRestartStatus()
|
||||||
const shownConnectionPromptKeys = new Set<string>()
|
const shownConnectionPromptKeys = new Set<string>()
|
||||||
|
|
||||||
const isChecking = computed(() => connectionStatus.value === 'checking')
|
|
||||||
const statusTitle = computed(() => (isChecking.value ? t('app.connectionChecking') : t('app.serviceUnavailable')))
|
|
||||||
const statusMessage = computed(() => {
|
const statusMessage = computed(() => {
|
||||||
if (connectionReason.value === 'browser-offline') return t('app.browserOfflineMessage')
|
if (connectionReason.value === 'browser-offline') return t('app.browserOfflineMessage')
|
||||||
if (connectionReason.value === 'timeout') return t('app.serviceTimeoutMessage')
|
if (connectionReason.value === 'timeout') return t('app.serviceTimeoutMessage')
|
||||||
if (isChecking.value) return t('app.connectionCheckingMessage')
|
|
||||||
return t('app.serviceUnavailableMessage')
|
return t('app.serviceUnavailableMessage')
|
||||||
})
|
})
|
||||||
|
|
||||||
/** 拼接离线状态提示文案,供 Toast 或 Agent 助手气泡展示。 */
|
/** 拼接离线状态提示文案,供 Toast 或 Agent 助手气泡展示。 */
|
||||||
function buildConnectionPromptMessage() {
|
function buildConnectionPromptMessage() {
|
||||||
return `${statusTitle.value}:${statusMessage.value}`
|
return `${t('app.serviceUnavailable')}:${statusMessage.value}`
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 根据当前连接状态选择 Toast 级别,Agent 助手可用时会由全局 Toast 路由接管。 */
|
/** 显示连接失败 Toast,Agent 助手可用时会由全局 Toast 路由接管。 */
|
||||||
function showConnectionPrompt() {
|
function showConnectionPrompt() {
|
||||||
const message = buildConnectionPromptMessage()
|
toast.error(buildConnectionPromptMessage(), { timeout: 7000 })
|
||||||
const options = {
|
|
||||||
timeout: isChecking.value ? 5000 : 7000,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isChecking.value) {
|
|
||||||
toast.warning(message, options)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
toast.error(message, options)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 在同一轮连接异常内按状态去重提示,并在恢复在线后允许下一轮提示重新出现。 */
|
/** 仅在确认连接失败后提示,并在恢复在线后允许下一轮提示重新出现。 */
|
||||||
function handleConnectionStatusChange() {
|
function handleConnectionStatusChange() {
|
||||||
if (connectionStatus.value === 'online') {
|
if (connectionStatus.value === 'online') {
|
||||||
shownConnectionPromptKeys.clear()
|
shownConnectionPromptKeys.clear()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (connectionStatus.value !== 'offline') return
|
||||||
|
|
||||||
// 重启期间由重启进度弹窗承载反馈,避免离线提示与进度提示叠加。
|
// 重启期间由重启进度弹窗承载反馈,避免离线提示与进度提示叠加。
|
||||||
if (isRestarting.value) return
|
if (isRestarting.value) return
|
||||||
|
|
||||||
const promptKey =
|
const promptKey = `${connectionStatus.value}:${connectionReason.value || 'unknown'}`
|
||||||
connectionStatus.value === 'checking'
|
|
||||||
? connectionStatus.value
|
|
||||||
: `${connectionStatus.value}:${connectionReason.value || 'unknown'}`
|
|
||||||
|
|
||||||
if (shownConnectionPromptKeys.has(promptKey)) return
|
if (shownConnectionPromptKeys.has(promptKey)) return
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|||||||
const mocks = vi.hoisted(() => ({
|
const mocks = vi.hoisted(() => ({
|
||||||
error: vi.fn(),
|
error: vi.fn(),
|
||||||
isRestarting: { value: false },
|
isRestarting: { value: false },
|
||||||
warning: vi.fn(),
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock('@/composables/useSystemRestart', () => ({
|
vi.mock('@/composables/useSystemRestart', () => ({
|
||||||
@@ -20,7 +19,7 @@ vi.mock('vue-i18n', async importOriginal => ({
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock('vue-toastification', () => ({
|
vi.mock('vue-toastification', () => ({
|
||||||
useToast: () => ({ error: mocks.error, warning: mocks.warning }),
|
useToast: () => ({ error: mocks.error }),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
describe('OfflinePage', () => {
|
describe('OfflinePage', () => {
|
||||||
@@ -29,7 +28,6 @@ describe('OfflinePage', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mocks.error.mockReset()
|
mocks.error.mockReset()
|
||||||
mocks.warning.mockReset()
|
|
||||||
mocks.isRestarting.value = false
|
mocks.isRestarting.value = false
|
||||||
status.markServerOnline()
|
status.markServerOnline()
|
||||||
wrapper = mount(OfflinePage)
|
wrapper = mount(OfflinePage)
|
||||||
@@ -40,19 +38,23 @@ describe('OfflinePage', () => {
|
|||||||
status.markServerOnline()
|
status.markServerOnline()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('同一轮 checking 状态只提示一次,并使用非阻断警告', async () => {
|
it('连接检查期间保持静默,确认离线后才显示错误', async () => {
|
||||||
status.markConnectionChecking('network-error')
|
status.markConnectionChecking('network-error')
|
||||||
await nextTick()
|
await nextTick()
|
||||||
|
|
||||||
expect(mocks.warning).toHaveBeenCalledWith('app.connectionChecking:app.connectionCheckingMessage', {
|
expect(mocks.error).not.toHaveBeenCalled()
|
||||||
timeout: 5000,
|
|
||||||
})
|
|
||||||
|
|
||||||
status.markConnectionChecking('timeout')
|
status.markConnectionChecking('timeout')
|
||||||
await nextTick()
|
await nextTick()
|
||||||
|
|
||||||
expect(mocks.warning).toHaveBeenCalledTimes(1)
|
|
||||||
expect(mocks.error).not.toHaveBeenCalled()
|
expect(mocks.error).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
status.markServerOffline('timeout')
|
||||||
|
await nextTick()
|
||||||
|
|
||||||
|
expect(mocks.error).toHaveBeenCalledWith('app.serviceUnavailable:app.serviceTimeoutMessage', {
|
||||||
|
timeout: 7000,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('按离线原因显示错误,并允许不同离线状态分别提示', async () => {
|
it('按离线原因显示错误,并允许不同离线状态分别提示', async () => {
|
||||||
@@ -76,42 +78,39 @@ describe('OfflinePage', () => {
|
|||||||
expect(mocks.error).toHaveBeenNthCalledWith(3, 'app.serviceUnavailable:app.serviceUnavailableMessage', {
|
expect(mocks.error).toHaveBeenNthCalledWith(3, 'app.serviceUnavailable:app.serviceUnavailableMessage', {
|
||||||
timeout: 7000,
|
timeout: 7000,
|
||||||
})
|
})
|
||||||
expect(mocks.warning).not.toHaveBeenCalled()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('在线恢复后允许下一轮 checking 再次提示', async () => {
|
it('在线恢复后允许下一轮离线提示重新出现', async () => {
|
||||||
status.markConnectionChecking()
|
status.markServerOffline()
|
||||||
await nextTick()
|
await nextTick()
|
||||||
expect(mocks.warning).toHaveBeenCalledTimes(1)
|
expect(mocks.error).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
status.markServerOnline()
|
status.markServerOnline()
|
||||||
await nextTick()
|
await nextTick()
|
||||||
status.markConnectionChecking()
|
status.markServerOffline()
|
||||||
await nextTick()
|
await nextTick()
|
||||||
|
|
||||||
expect(mocks.warning).toHaveBeenCalledTimes(2)
|
expect(mocks.error).toHaveBeenCalledTimes(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('重启期间不提示,但在线恢复仍清空上一轮去重状态', async () => {
|
it('重启期间不提示,但在线恢复仍清空上一轮去重状态', async () => {
|
||||||
status.markConnectionChecking()
|
status.markServerOffline()
|
||||||
await nextTick()
|
await nextTick()
|
||||||
expect(mocks.warning).toHaveBeenCalledTimes(1)
|
expect(mocks.error).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
mocks.isRestarting.value = true
|
mocks.isRestarting.value = true
|
||||||
status.markServerOffline('timeout')
|
status.markServerOffline('timeout')
|
||||||
await nextTick()
|
await nextTick()
|
||||||
expect(mocks.error).not.toHaveBeenCalled()
|
expect(mocks.error).toHaveBeenCalledTimes(1)
|
||||||
expect(mocks.warning).toHaveBeenCalledTimes(1)
|
|
||||||
|
|
||||||
status.markServerOnline()
|
status.markServerOnline()
|
||||||
await nextTick()
|
await nextTick()
|
||||||
expect(mocks.error).not.toHaveBeenCalled()
|
expect(mocks.error).toHaveBeenCalledTimes(1)
|
||||||
expect(mocks.warning).toHaveBeenCalledTimes(1)
|
|
||||||
|
|
||||||
mocks.isRestarting.value = false
|
mocks.isRestarting.value = false
|
||||||
status.markConnectionChecking()
|
status.markServerOffline()
|
||||||
await nextTick()
|
await nextTick()
|
||||||
|
|
||||||
expect(mocks.warning).toHaveBeenCalledTimes(2)
|
expect(mocks.error).toHaveBeenCalledTimes(2)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user