gongxiangp2/components/MaintenanceBanner.tsx
chenpei 0ce59be34e 备份:组织架构设计方案讨论前的代码快照
- 包含所有当前修改和新功能
- 准备开始组织架构优化实施方案
2025-12-30 13:20:26 +08:00

109 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client'
import { useEffect, useState } from 'react'
interface MaintenanceInfo {
enabled: boolean
message: string | null
startTime: string | null
endTime: string | null
}
export default function MaintenanceBanner() {
const [maintenance, setMaintenance] = useState<MaintenanceInfo | null>(null)
const [dismissed, setDismissed] = useState(false)
useEffect(() => {
const fetchMaintenance = async () => {
try {
const response = await fetch('/api/system-settings')
if (response.ok) {
const data = await response.json()
if (data.maintenanceEnabled && data.maintenanceMessage) {
// 检查维护时间范围
const now = new Date()
const startTime = data.maintenanceStartTime ? new Date(data.maintenanceStartTime) : null
const endTime = data.maintenanceEndTime ? new Date(data.maintenanceEndTime) : null
// 如果设置了时间范围,检查是否在范围内
if (startTime && endTime) {
if (now < startTime || now > endTime) {
return // 不在维护时间范围内,不显示
}
} else if (startTime && now < startTime) {
return // 维护还未开始
} else if (endTime && now > endTime) {
return // 维护已结束
}
setMaintenance({
enabled: true,
message: data.maintenanceMessage,
startTime: data.maintenanceStartTime,
endTime: data.maintenanceEndTime,
})
}
}
} catch (error) {
console.error('获取维护通知失败:', error)
}
}
fetchMaintenance()
// 每5分钟检查一次
const interval = setInterval(fetchMaintenance, 5 * 60 * 1000)
return () => clearInterval(interval)
}, [])
// 检查是否已关闭
useEffect(() => {
if (maintenance?.enabled) {
const dismissedKey = `maintenance_dismissed_${maintenance.startTime || 'default'}`
const isDismissed = sessionStorage.getItem(dismissedKey) === 'true'
setDismissed(isDismissed)
}
}, [maintenance])
if (!maintenance?.enabled || !maintenance.message || dismissed) {
return null
}
const handleDismiss = () => {
const dismissedKey = `maintenance_dismissed_${maintenance.startTime || 'default'}`
sessionStorage.setItem(dismissedKey, 'true')
setDismissed(true)
}
return (
<div className="fixed top-0 left-0 right-0 z-50 bg-gradient-to-r from-orange-500 to-red-500 text-white shadow-lg">
<div className="container mx-auto px-4 py-3 max-w-7xl">
<div className="flex items-center justify-between gap-4">
<div className="flex items-center gap-3 flex-1">
<svg className="w-6 h-6 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
<div className="flex-1">
<p className="font-medium text-sm sm:text-base">
⚠️ 系统维护通知
</p>
<p className="text-xs sm:text-sm opacity-90 mt-0.5">
{maintenance.message}
</p>
</div>
</div>
<button
onClick={handleDismiss}
className="px-3 py-2 hover:bg-orange-600 rounded-lg transition-colors flex-shrink-0"
title="关闭通知"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
</div>
)
}