| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478 |
- "use client"
- import {useEffect, useState} from "react"
- import {
- Alert,
- Button,
- Card,
- Col,
- Descriptions,
- Form,
- Input,
- Modal,
- Row,
- Select,
- Space,
- Table,
- Tag,
- Timeline,
- } from "antd"
- import {BellOutlined, CheckCircleOutlined, EditOutlined, EyeOutlined} from "@ant-design/icons"
- import {Line} from "@ant-design/plots"
- import globalMessage from "@/app/_modules/globalMessage";
- const { Option } = Select
- const { TextArea } = Input
- // 模拟报警数据
- const mockAlarmData = [
- {
- id: "A001",
- title: "解放路段压力异常报警",
- type: "压力异常",
- level: "高",
- location: "解放路调压站",
- deviceId: "D001",
- deviceName: "压力监测器001",
- value: 0.52,
- threshold: 0.45,
- unit: "MPa",
- status: "未处理",
- createTime: "2024-01-15 14:30:25",
- updateTime: "2024-01-15 14:30:25",
- handler: null,
- handleTime: null,
- description: "管网压力超出安全阈值,可能存在安全隐患",
- solution: null,
- },
- {
- id: "A002",
- title: "人民路段流量异常报警",
- type: "流量异常",
- level: "中",
- location: "人民路段",
- deviceId: "D002",
- deviceName: "流量监测器002",
- value: 4200,
- threshold: 3500,
- unit: "m³/h",
- status: "处理中",
- createTime: "2024-01-15 13:45:10",
- updateTime: "2024-01-15 14:15:30",
- handler: "张三",
- handleTime: "2024-01-15 14:15:30",
- description: "流量超出正常范围,需要检查管网状态",
- solution: "正在检查管网连接状态,预计30分钟内完成",
- },
- {
- id: "A003",
- title: "建设路段泄漏报警",
- type: "泄漏检测",
- level: "高",
- location: "建设路北段",
- deviceId: "D004",
- deviceName: "泄漏检测器004",
- value: 0.08,
- threshold: 0.05,
- unit: "ppm",
- status: "已处理",
- createTime: "2024-01-15 12:20:15",
- updateTime: "2024-01-15 13:45:20",
- handler: "李四",
- handleTime: "2024-01-15 12:25:15",
- description: "检测到燃气泄漏,浓度超标",
- solution: "已完成管线检修,泄漏点已修复,监测数据恢复正常",
- },
- ]
- // 模拟报警统计数据
- const mockAlarmStats = [
- { time: "00:00", count: 2 },
- { time: "04:00", count: 1 },
- { time: "08:00", count: 3 },
- { time: "12:00", count: 5 },
- { time: "16:00", count: 2 },
- { time: "20:00", count: 1 },
- ]
- export default function AbnormalAlarm() {
- const [isModalVisible, setIsModalVisible] = useState(false)
- const [isDetailModalVisible, setIsDetailModalVisible] = useState(false)
- const [selectedAlarm, setSelectedAlarm] = useState(null)
- const [form] = Form.useForm()
- const [alarmData, setAlarmData] = useState(mockAlarmData)
- // 模拟实时报警更新
- useEffect(() => {
- const interval = setInterval(() => {
- // 模拟新报警
- if (Math.random() < 0.1) {
- const newAlarm = {
- id: `A${Date.now()}`,
- title: "新报警事件",
- type: "压力异常",
- level: "中",
- location: "测试路段",
- deviceId: "D999",
- deviceName: "测试设备",
- value: 0.48,
- threshold: 0.45,
- unit: "MPa",
- status: "未处理",
- createTime: new Date().toLocaleString(),
- updateTime: new Date().toLocaleString(),
- handler: null,
- handleTime: null,
- description: "模拟报警事件",
- solution: null,
- }
- setAlarmData((prev) => [newAlarm, ...prev])
- globalMessage.warning("收到新报警!")
- }
- }, 30000) // 30秒检查一次
- return () => clearInterval(interval)
- }, [])
- const handleView = (record: any) => {
- setSelectedAlarm(record)
- setIsDetailModalVisible(true)
- }
- const handleProcess = (record: any) => {
- setSelectedAlarm(record)
- form.setFieldsValue({
- handler: "当前用户",
- solution: "",
- })
- setIsModalVisible(true)
- }
- const handleModalOk = () => {
- form.validateFields().then((values) => {
- const updatedData = alarmData.map((item) =>
- item.id === selectedAlarm?.id
- ? {
- ...item,
- status: "处理中",
- handler: values.handler,
- handleTime: new Date().toLocaleString(),
- updateTime: new Date().toLocaleString(),
- solution: values.solution,
- }
- : item,
- )
- setAlarmData(updatedData)
- globalMessage.success("报警处理成功")
- setIsModalVisible(false)
- form.resetFields()
- })
- }
- const handleComplete = (id: string) => {
- const updatedData = alarmData.map((item) =>
- item.id === id
- ? {
- ...item,
- status: "已处理",
- updateTime: new Date().toLocaleString(),
- }
- : item,
- )
- setAlarmData(updatedData)
- globalMessage.success("报警已标记为完成")
- }
- const getStatusColor = (status: string) => {
- switch (status) {
- case "未处理":
- return "red"
- case "处理中":
- return "orange"
- case "已处理":
- return "green"
- default:
- return "default"
- }
- }
- const getLevelColor = (level: string) => {
- switch (level) {
- case "高":
- return "red"
- case "中":
- return "orange"
- case "低":
- return "blue"
- default:
- return "default"
- }
- }
- const columns = [
- { title: "报警编号", dataIndex: "id", key: "id", width: 100 },
- { title: "报警标题", dataIndex: "title", key: "title", width: 200 },
- { title: "报警类型", dataIndex: "type", key: "type", width: 120 },
- {
- title: "报警等级",
- dataIndex: "level",
- key: "level",
- width: 100,
- render: (level: string) => <Tag color={getLevelColor(level)}>{level}</Tag>,
- },
- { title: "位置", dataIndex: "location", key: "location", width: 150 },
- { title: "设备名称", dataIndex: "deviceName", key: "deviceName", width: 150 },
- {
- title: "异常值",
- key: "value",
- width: 120,
- render: (_, record: any) => `${record.value} ${record.unit}`,
- },
- {
- title: "阈值",
- key: "threshold",
- width: 120,
- render: (_, record: any) => `${record.threshold} ${record.unit}`,
- },
- {
- title: "状态",
- dataIndex: "status",
- key: "status",
- width: 100,
- render: (status: string) => <Tag color={getStatusColor(status)}>{status}</Tag>,
- },
- { title: "创建时间", dataIndex: "createTime", key: "createTime", width: 180 },
- { title: "处理人", dataIndex: "handler", key: "handler", width: 100 },
- {
- title: "操作",
- key: "action",
- width: 200,
- fixed: "right",
- render: (_, record) => (
- <Space>
- <Button type="link" icon={<EyeOutlined />} onClick={() => handleView(record)}>
- 查看
- </Button>
- {record.status === "未处理" && (
- <Button type="link" icon={<EditOutlined />} onClick={() => handleProcess(record)}>
- 处理
- </Button>
- )}
- {record.status === "处理中" && (
- <Button type="link" onClick={() => handleComplete(record.id)}>
- 完成
- </Button>
- )}
- </Space>
- ),
- },
- ]
- const lineConfig = {
- data: mockAlarmStats,
- xField: "time",
- yField: "count",
- color: "#f5222d",
- point: {
- size: 5,
- shape: "diamond",
- },
- area: {
- style: {
- fill: "l(270) 0:#ffffff 0.5:#ffccc7 1:#f5222d",
- fillOpacity: 0.3,
- },
- },
- }
- const unhandledCount = alarmData.filter((item) => item.status === "未处理").length
- const processingCount = alarmData.filter((item) => item.status === "处理中").length
- const handledCount = alarmData.filter((item) => item.status === "已处理").length
- return (
- <div className="p-6">
- <Card title="异常报警管理">
- {/* 报警概览 */}
- <Row gutter={16} className="mb-6">
- <Col span={6}>
- <Card size="small">
- <div className="text-center">
- <div className="text-2xl font-bold text-red-600">{unhandledCount}</div>
- <div className="text-gray-600">未处理报警</div>
- </div>
- </Card>
- </Col>
- <Col span={6}>
- <Card size="small">
- <div className="text-center">
- <div className="text-2xl font-bold text-orange-600">{processingCount}</div>
- <div className="text-gray-600">处理中</div>
- </div>
- </Card>
- </Col>
- <Col span={6}>
- <Card size="small">
- <div className="text-center">
- <div className="text-2xl font-bold text-green-600">{handledCount}</div>
- <div className="text-gray-600">已处理</div>
- </div>
- </Card>
- </Col>
- <Col span={6}>
- <Card size="small">
- <div className="text-center">
- <div className="text-2xl font-bold text-blue-600">{alarmData.length}</div>
- <div className="text-gray-600">报警总数</div>
- </div>
- </Card>
- </Col>
- </Row>
- {/* 紧急报警提醒 */}
- {unhandledCount > 0 && (
- <Alert
- message={`当前有 ${unhandledCount} 个未处理报警`}
- description="请及时处理高等级报警,确保系统安全运行"
- type="error"
- icon={<BellOutlined />}
- showIcon
- className="mb-6"
- />
- )}
- {/* 报警趋势图 */}
- <Row gutter={16} className="mb-6">
- <Col span={24}>
- <Card title="24小时报警趋势" size="small">
- <Line {...lineConfig} height={200} />
- </Card>
- </Col>
- </Row>
- {/* 筛选控件 */}
- <div className="mb-4">
- <Space>
- <Select placeholder="报警类型" style={{ width: 120 }}>
- <Option value="pressure">压力异常</Option>
- <Option value="flow">流量异常</Option>
- <Option value="temperature">温度异常</Option>
- <Option value="leak">泄漏检测</Option>
- </Select>
- <Select placeholder="报警等级" style={{ width: 120 }}>
- <Option value="high">高</Option>
- <Option value="medium">中</Option>
- <Option value="low">低</Option>
- </Select>
- <Select placeholder="处理状态" style={{ width: 120 }}>
- <Option value="unhandled">未处理</Option>
- <Option value="processing">处理中</Option>
- <Option value="handled">已处理</Option>
- </Select>
- </Space>
- </div>
- {/* 报警列表 */}
- <Table
- columns={columns}
- dataSource={alarmData}
- rowKey="id"
- pagination={{ pageSize: 10 }}
- scroll={{ x: 1600 }}
- rowClassName={(record) => (record.status === "未处理" && record.level === "高" ? "bg-red-50" : "")}
- />
- {/* 处理模态框 */}
- <Modal
- title="处理报警"
- open={isModalVisible}
- onOk={handleModalOk}
- onCancel={() => setIsModalVisible(false)}
- width={600}
- >
- <Form form={form} layout="vertical">
- <Form.Item name="handler" label="处理人" rules={[{ required: true }]}>
- <Input />
- </Form.Item>
- <Form.Item name="solution" label="处理方案" rules={[{ required: true }]}>
- <TextArea rows={4} placeholder="请输入处理方案..." />
- </Form.Item>
- </Form>
- </Modal>
- {/* 详情查看模态框 */}
- <Modal
- title="报警详情"
- open={isDetailModalVisible}
- onCancel={() => setIsDetailModalVisible(false)}
- footer={[
- <Button key="close" onClick={() => setIsDetailModalVisible(false)}>
- 关闭
- </Button>,
- ]}
- width={800}
- >
- {selectedAlarm && (
- <div>
- <Descriptions column={2} bordered>
- <Descriptions.Item label="报警编号">{selectedAlarm.id}</Descriptions.Item>
- <Descriptions.Item label="报警标题">{selectedAlarm.title}</Descriptions.Item>
- <Descriptions.Item label="报警类型">{selectedAlarm.type}</Descriptions.Item>
- <Descriptions.Item label="报警等级">
- <Tag color={getLevelColor(selectedAlarm.level)}>{selectedAlarm.level}</Tag>
- </Descriptions.Item>
- <Descriptions.Item label="位置">{selectedAlarm.location}</Descriptions.Item>
- <Descriptions.Item label="设备名称">{selectedAlarm.deviceName}</Descriptions.Item>
- <Descriptions.Item label="异常值">
- {selectedAlarm.value} {selectedAlarm.unit}
- </Descriptions.Item>
- <Descriptions.Item label="阈值">
- {selectedAlarm.threshold} {selectedAlarm.unit}
- </Descriptions.Item>
- <Descriptions.Item label="状态">
- <Tag color={getStatusColor(selectedAlarm.status)}>{selectedAlarm.status}</Tag>
- </Descriptions.Item>
- <Descriptions.Item label="创建时间">{selectedAlarm.createTime}</Descriptions.Item>
- <Descriptions.Item label="处理人">{selectedAlarm.handler || "未分配"}</Descriptions.Item>
- <Descriptions.Item label="处理时间">{selectedAlarm.handleTime || "未处理"}</Descriptions.Item>
- </Descriptions>
- <div className="mt-4">
- <h4 className="font-medium mb-2">报警描述</h4>
- <div className="p-3 bg-gray-50 rounded">{selectedAlarm.description}</div>
- </div>
- {selectedAlarm.solution && (
- <div className="mt-4">
- <h4 className="font-medium mb-2">处理方案</h4>
- <div className="p-3 bg-blue-50 rounded">{selectedAlarm.solution}</div>
- </div>
- )}
- <div className="mt-4">
- <h4 className="font-medium mb-2">处理时间线</h4>
- <Timeline>
- <Timeline.Item color="red" dot={<BellOutlined />}>
- <div>报警触发</div>
- <div className="text-gray-500 text-sm">{selectedAlarm.createTime}</div>
- </Timeline.Item>
- {selectedAlarm.handleTime && (
- <Timeline.Item color="orange" dot={<EditOutlined />}>
- <div>开始处理 - {selectedAlarm.handler}</div>
- <div className="text-gray-500 text-sm">{selectedAlarm.handleTime}</div>
- </Timeline.Item>
- )}
- {selectedAlarm.status === "已处理" && (
- <Timeline.Item color="green" dot={<CheckCircleOutlined />}>
- <div>处理完成</div>
- <div className="text-gray-500 text-sm">{selectedAlarm.updateTime}</div>
- </Timeline.Item>
- )}
- </Timeline>
- </div>
- </div>
- )}
- </Modal>
- </Card>
- </div>
- )
- }
|