feat: AI预测分析接入真实后端数据 + 修复CloudBilling文件损坏
- AIPredictiveAnalytics: 替换3组硬编码mock为实时数据驱动预测 - 指标预测: 基于dashboard metrics时序数据(cpu/memory/disk)线性回归计算斜率与R² - 容量规划: 基于日均增长率推算阈值触及时间(天),动态生成AI扩容建议 - 异常预测: 基于告警规则阈值+当前趋势+事件频率计算异常触发概率 - 概览卡片数据驱动化(置信度基于R²拟合度,高风险/容量预警计数实时计算) - CloudBilling.tsx: 修复read_file导致的行号前缀损坏(501行全部含N|前缀)
This commit is contained in:
1 parent
0ebe22d142
commit
2da4f52209
17 files changed
+2299
-322
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useConfirm } from '@/components/ui/confirm-dialog';
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
@@ -93,6 +94,7 @@ function resolveChannelRef(value: string, channels: any[]): { type: string; name
|
||||
}
|
||||
|
||||
export function AlertManager() {
|
||||
const _confirm = useConfirm();
|
||||
const [activeTab, setActiveTab] = useState('events');
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [severityFilter, setSeverityFilter] = useState<string>('all');
|
||||
@@ -164,7 +166,7 @@ export function AlertManager() {
|
||||
};
|
||||
|
||||
const handleDeleteRule = async (id: any) => {
|
||||
if (!window.confirm('确定删除此告警规则?')) return;
|
||||
{ const ok = await _confirm({ title: '删除告警规则', description: '确定删除此告警规则?', confirmText: '删除', variant: 'destructive' }); if (!ok) return; }
|
||||
try {
|
||||
await alertApi.deleteRule(id);
|
||||
loadData();
|
||||
@@ -275,7 +277,7 @@ export function AlertManager() {
|
||||
};
|
||||
|
||||
const handleDeleteChannel = async (id: any) => {
|
||||
if (!window.confirm('确定删除此通知渠道?')) return;
|
||||
{ const ok = await _confirm({ title: '删除通知渠道', description: '确定删除此通知渠道?', confirmText: '删除', variant: 'destructive' }); if (!ok) return; }
|
||||
try {
|
||||
await alertApi.deleteNotifyChannel(id);
|
||||
if (editingChannel && editingChannel.id === id) resetChannelForm();
|
||||
|
||||
@@ -22,6 +22,7 @@ import { Switch } from '@/components/ui/switch';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||
import { toast } from 'sonner';
|
||||
import { useConfirm } from '@/components/ui/confirm-dialog';
|
||||
import { alertCenterApi, alertApi } from '@/services/api';
|
||||
|
||||
interface Alert {
|
||||
@@ -68,6 +69,7 @@ interface NotificationChannel {
|
||||
}
|
||||
|
||||
const AlertCenter: React.FC = () => {
|
||||
const _confirm = useConfirm();
|
||||
const [alerts, setAlerts] = useState<Alert[]>([]);
|
||||
const [rules, setRules] = useState<AlertRule[]>([]);
|
||||
const [channels, setChannels] = useState<NotificationChannel[]>([]);
|
||||
@@ -215,7 +217,7 @@ const AlertCenter: React.FC = () => {
|
||||
};
|
||||
|
||||
const handleDeleteChannel = async (id: number) => {
|
||||
if (!window.confirm('确定删除此通知渠道?')) return;
|
||||
{ const ok = await _confirm({ title: '删除通知渠道', description: '确定删除此通知渠道?', confirmText: '删除', variant: 'destructive' }); if (!ok) return; }
|
||||
try {
|
||||
await alertApi.deleteNotifyChannel(id);
|
||||
toast.success('渠道已删除');
|
||||
@@ -407,10 +409,6 @@ const AlertCenter: React.FC = () => {
|
||||
<RefreshCw className="w-4 h-4 mr-2" />
|
||||
刷新
|
||||
</Button>
|
||||
<Button variant="outline" onClick={() => toast.info('批量操作功能开发中')}>
|
||||
<Check className="w-4 h-4 mr-2" />
|
||||
批量确认
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -516,10 +514,6 @@ const AlertCenter: React.FC = () => {
|
||||
刷新
|
||||
</Button>
|
||||
</div>
|
||||
<Button onClick={() => toast.info('创建规则功能开发中')}>
|
||||
<Plus className="w-4 h-4 mr-2" />
|
||||
新建规则
|
||||
</Button>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-4">
|
||||
{rules.map((rule) => (
|
||||
|
||||
@@ -20,6 +20,7 @@ import { Label } from '@/components/ui/label';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { toast } from 'sonner';
|
||||
import { useConfirm } from '@/components/ui/confirm-dialog';
|
||||
import { dashboardApi } from '@/services/api';
|
||||
|
||||
interface Dashboard {
|
||||
@@ -73,6 +74,7 @@ interface Datasource {
|
||||
}
|
||||
|
||||
const GrafanaDashboard: React.FC = () => {
|
||||
const _confirm = useConfirm();
|
||||
const [dashboards, setDashboards] = useState<Dashboard[]>([]);
|
||||
const [datasources, setDatasources] = useState<Datasource[]>([]);
|
||||
const [activeDashboard, setActiveDashboard] = useState<Dashboard | null>(null);
|
||||
@@ -201,7 +203,7 @@ const GrafanaDashboard: React.FC = () => {
|
||||
};
|
||||
|
||||
const handleDeleteDashboard = async (id: string) => {
|
||||
if (!confirm('确定删除此仪表盘吗?')) return;
|
||||
{ const ok = await _confirm({ title: '删除仪表盘', description: '确定删除此仪表盘吗?', confirmText: '删除', variant: 'destructive' }); if (!ok) return; }
|
||||
try {
|
||||
await dashboardApi.deleteDashboard(id);
|
||||
toast.success('删除成功');
|
||||
|
||||
Reference in new issue
Block a user