feat: 替换 OpenBridge 组件并实现航海规范主题系统
- 使用 shadcn/ui 重新实现 TopBar、ThemeSidebar、AlertBadge 组件 - 解决 @oicl/openbridge-webcomponents ESM 模块解析问题 - 添加 OpenBridge 四种主题 CSS 变量 (day/bright/dusk/night) - Night 主题使用暗黄色文字保护夜视能力 - 更新 API 端点适配新的按模型分组数据结构
This commit is contained in:
140
src/components/ui/AlertBadge.tsx
Normal file
140
src/components/ui/AlertBadge.tsx
Normal file
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* AlertBadge 组件
|
||||
*
|
||||
* 告警徽章组件,显示告警数量和状态。
|
||||
* 支持三种告警类型:Alarm(紧急)、Warning(警告)、Caution(注意)
|
||||
*/
|
||||
import { AlertTriangle, Bell, BellOff, XCircle } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
/** 告警类型枚举 */
|
||||
export enum AlertType {
|
||||
Caution = 'caution',
|
||||
Warning = 'warning',
|
||||
Alarm = 'alarm',
|
||||
}
|
||||
|
||||
export interface AlertBadgeProps {
|
||||
/** 告警数量 */
|
||||
count: number
|
||||
/** 告警类型 */
|
||||
alertType: AlertType
|
||||
/** 是否静音 */
|
||||
muted?: boolean
|
||||
/** 静音按钮点击事件 */
|
||||
onMuteClick?: () => void
|
||||
/** 额外的 className */
|
||||
className?: string
|
||||
}
|
||||
|
||||
/** 告警类型对应的颜色配置 - 使用 OpenBridge CSS 变量 */
|
||||
const ALERT_COLORS: Record<
|
||||
AlertType,
|
||||
{ bgVar: string; textClass: string; icon: typeof AlertTriangle }
|
||||
> = {
|
||||
[AlertType.Alarm]: {
|
||||
bgVar: 'var(--alert-alarm-color, rgb(227, 0, 25))',
|
||||
textClass: 'text-white',
|
||||
icon: XCircle,
|
||||
},
|
||||
[AlertType.Warning]: {
|
||||
bgVar: 'var(--alert-warning-color, rgb(254, 148, 19))',
|
||||
textClass: 'text-white',
|
||||
icon: AlertTriangle,
|
||||
},
|
||||
[AlertType.Caution]: {
|
||||
bgVar: 'var(--alert-caution-color, rgb(255, 219, 55))',
|
||||
textClass: 'text-gray-900',
|
||||
icon: AlertTriangle,
|
||||
},
|
||||
}
|
||||
|
||||
export const AlertBadge = ({
|
||||
count,
|
||||
alertType,
|
||||
muted = false,
|
||||
onMuteClick,
|
||||
className,
|
||||
}: AlertBadgeProps) => {
|
||||
const { bgVar, textClass, icon: Icon } = ALERT_COLORS[alertType]
|
||||
|
||||
if (count === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn('flex items-center gap-1', className)}>
|
||||
{/* 告警徽章 */}
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center gap-1.5 px-2.5 py-1 rounded-full',
|
||||
textClass,
|
||||
)}
|
||||
style={{ backgroundColor: bgVar }}
|
||||
>
|
||||
<Icon className="size-4" />
|
||||
<span className="text-sm font-medium">{count}</span>
|
||||
</div>
|
||||
|
||||
{/* 静音按钮 */}
|
||||
{onMuteClick && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
onClick={onMuteClick}
|
||||
className={cn(
|
||||
'hover:bg-[var(--element-hover-color,rgba(0,0,0,0.12))]',
|
||||
muted && 'opacity-50',
|
||||
)}
|
||||
aria-label={muted ? '取消静音' : '静音告警'}
|
||||
>
|
||||
{muted ? (
|
||||
<BellOff className="size-4 text-[var(--element-inactive-color,#707070)]" />
|
||||
) : (
|
||||
<Bell className="size-4 text-[var(--element-active-color,#3d3d3d)]" />
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export interface AlertNotificationProps {
|
||||
/** 账户名 */
|
||||
account: string
|
||||
/** 剩余百分比 */
|
||||
remainingPercent: number
|
||||
/** 告警类型 */
|
||||
alertType: AlertType
|
||||
}
|
||||
|
||||
/** 获取告警类型对应的 CSS 变量颜色 */
|
||||
const getAlertColor = (alertType: AlertType): string => {
|
||||
switch (alertType) {
|
||||
case AlertType.Alarm:
|
||||
return 'var(--alert-alarm-color, rgb(227, 0, 25))'
|
||||
case AlertType.Warning:
|
||||
return 'var(--alert-warning-color, rgb(254, 148, 19))'
|
||||
case AlertType.Caution:
|
||||
return 'var(--alert-caution-color, rgb(255, 219, 55))'
|
||||
}
|
||||
}
|
||||
|
||||
export const AlertNotification = ({
|
||||
account,
|
||||
remainingPercent,
|
||||
alertType,
|
||||
}: AlertNotificationProps) => {
|
||||
const { icon: Icon } = ALERT_COLORS[alertType]
|
||||
const alertColor = getAlertColor(alertType)
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2 px-3 py-2 text-sm">
|
||||
<Icon className="size-4 shrink-0" style={{ color: alertColor }} />
|
||||
<span className="text-[var(--element-active-color,#3d3d3d)]">
|
||||
{account}: 剩余 {remainingPercent}%
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user