alert_panel.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. import os
  2. import time
  3. from datetime import datetime
  4. from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton,
  5. QTableWidget, QTableWidgetItem, QHeaderView, QComboBox,
  6. QGroupBox, QToolBar, QAction, QMenu, QAbstractItemView, QMessageBox, QDialog, QProgressBar)
  7. from PyQt5.QtCore import Qt, pyqtSlot, QSize, QTimer, QDateTime, pyqtSignal
  8. from PyQt5.QtGui import QIcon, QColor, QBrush, QFont, QPixmap
  9. import random
  10. class AlertPanel(QWidget):
  11. """告警面板组件,显示各类灾害告警信息"""
  12. # 添加信号用于通知统计面板
  13. alert_added = pyqtSignal(str, str) # 参数: alert_type, region
  14. alert_processed = pyqtSignal(str, str) # 参数: alert_type, region - 新增信号用于通知告警已处理
  15. def __init__(self, config):
  16. super().__init__()
  17. self.config = config
  18. self.alerts = [] # 保存所有告警
  19. self.current_filter = "all" # 当前过滤类型
  20. self.current_severity = "all" # 当前严重程度过滤
  21. # 从配置文件获取随机告警设置
  22. self.random_alert_config = config.get('random_alert', {
  23. 'enabled': False,
  24. 'interval': 5,
  25. 'probability': 0.3,
  26. 'types': ['fire', 'animal', 'landslide', 'forest_degradation', 'pest'],
  27. 'locations': ['北部山区', '南部林区', '东部山脊', '西部谷地', '中央林场']
  28. })
  29. self.init_ui()
  30. # 设置自动更新定时器
  31. self.update_timer = QTimer(self)
  32. self.update_timer.timeout.connect(self.update_alerts)
  33. self.update_timer.start(self.random_alert_config['interval'] * 1000) # 转换为毫秒
  34. def init_ui(self):
  35. """初始化UI"""
  36. # 创建主布局
  37. layout = QVBoxLayout(self)
  38. layout.setContentsMargins(0, 0, 0, 0)
  39. # 创建工具栏
  40. toolbar = QHBoxLayout()
  41. # 添加标题
  42. title_label = QLabel("告警信息")
  43. title_label.setFont(QFont("Microsoft YaHei", 12, QFont.Bold))
  44. title_label.setStyleSheet("color: #00e6e6; margin: 5px;")
  45. toolbar.addWidget(title_label)
  46. # 添加分隔符
  47. toolbar.addStretch(1)
  48. # 添加随机告警开关
  49. self.random_alert_btn = QPushButton(f"随机告警: {'开' if self.random_alert_config['enabled'] else '关'}")
  50. self.random_alert_btn.setCheckable(True) # 使按钮可切换
  51. self.random_alert_btn.setChecked(self.random_alert_config['enabled']) # 设置初始状态
  52. self.random_alert_btn.setFixedWidth(100)
  53. self.random_alert_btn.clicked.connect(self.toggle_random_alerts)
  54. self.random_alert_btn.setStyleSheet("""
  55. QPushButton {
  56. background-color: #666666;
  57. color: white;
  58. border: none;
  59. border-radius: 4px;
  60. padding: 5px;
  61. }
  62. QPushButton:checked {
  63. background-color: #4CAF50;
  64. }
  65. """)
  66. toolbar.addWidget(self.random_alert_btn)
  67. # 添加过滤下拉框
  68. self.filter_combo = QComboBox()
  69. self.filter_combo.addItem("全部告警", "all")
  70. self.filter_combo.addItem("火灾告警", "fire")
  71. self.filter_combo.addItem("动物告警", "animal")
  72. self.filter_combo.addItem("滑坡告警", "landslide")
  73. self.filter_combo.addItem("森林退化告警", "forest")
  74. self.filter_combo.addItem("病虫害告警", "pest")
  75. self.filter_combo.currentIndexChanged.connect(self.filter_alerts)
  76. toolbar.addWidget(QLabel("过滤: "))
  77. toolbar.addWidget(self.filter_combo)
  78. # 添加严重程度过滤下拉框
  79. self.severity_combo = QComboBox()
  80. self.severity_combo.addItem("所有等级", "all")
  81. self.severity_combo.addItem("高", "high")
  82. self.severity_combo.addItem("中", "medium")
  83. self.severity_combo.addItem("低", "low")
  84. self.severity_combo.currentIndexChanged.connect(self.filter_alerts)
  85. toolbar.addWidget(QLabel("严重程度: "))
  86. toolbar.addWidget(self.severity_combo)
  87. # 添加按钮
  88. self.clear_btn = QPushButton("清空")
  89. self.clear_btn.setIcon(QIcon(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'assets', 'clear.png')))
  90. self.clear_btn.clicked.connect(self.clear_alerts)
  91. toolbar.addWidget(self.clear_btn)
  92. # 添加工具栏到布局
  93. layout.addLayout(toolbar)
  94. # 创建表格
  95. self.alert_table = QTableWidget()
  96. self.alert_table.setColumnCount(6)
  97. self.alert_table.setHorizontalHeaderLabels(["时间", "类型", "位置", "详情", "等级", "操作"])
  98. self.alert_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
  99. self.alert_table.setSelectionBehavior(QAbstractItemView.SelectRows)
  100. self.alert_table.setAlternatingRowColors(True)
  101. self.alert_table.setStyleSheet("alternate-background-color: #0c1e32; background-color: #081a2e; color: white; "
  102. "QHeaderView::section { background-color: #15253a; color: white; padding: 4px; "
  103. "border: 1px solid #1e3a5a; font-weight: bold; }"
  104. "QTableView { gridline-color: #1e3a5a; border: 1px solid #1e3a5a; }"
  105. "QTableView::item:selected { background-color: #2a4a6a; }")
  106. # 设置列宽
  107. self.alert_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)
  108. self.alert_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeToContents)
  109. self.alert_table.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeToContents)
  110. self.alert_table.horizontalHeader().setSectionResizeMode(3, QHeaderView.Stretch)
  111. self.alert_table.horizontalHeader().setSectionResizeMode(4, QHeaderView.ResizeToContents)
  112. self.alert_table.horizontalHeader().setSectionResizeMode(5, QHeaderView.ResizeToContents)
  113. # 双击行处理
  114. self.alert_table.cellDoubleClicked.connect(self.show_alert_detail)
  115. # 添加表格到布局
  116. layout.addWidget(self.alert_table)
  117. # 设置最小高度
  118. self.setMinimumHeight(150)
  119. def add_alert(self, alert):
  120. """添加告警到列表和表格"""
  121. # 添加到告警列表
  122. self.alerts.append(alert)
  123. # 发出信号通知统计面板
  124. print(f"发送告警信号: 类型={alert['type']}, 区域={alert['location']}")
  125. self.alert_added.emit(alert['type'], alert['location'])
  126. # 检查是否符合当前过滤条件
  127. type_match = self.current_filter == "all" or alert['type'] == self.current_filter
  128. severity_match = self.current_severity == "all" or alert['level'] == self.current_severity
  129. if type_match and severity_match:
  130. self.add_filtered_alert(alert)
  131. def get_alert_type_name(self, alert_type):
  132. """获取告警类型的中文名称
  133. Args:
  134. alert_type (str): 告警类型
  135. Returns:
  136. str: 告警类型的中文名称
  137. """
  138. type_names = {
  139. "fire": "森林火灾",
  140. "animal": "野生动物异常",
  141. "landslide": "山体滑坡",
  142. "forest_degradation": "森林退化",
  143. "pest": "病虫害"
  144. }
  145. return type_names.get(alert_type, "未知类型")
  146. def get_alert_type_color(self, alert_type):
  147. """获取告警类型显示颜色"""
  148. type_colors = {
  149. 'fire': QColor(255, 200, 200), # 红色
  150. 'animal': QColor(200, 255, 200), # 绿色
  151. 'landslide': QColor(200, 200, 255), # 蓝色
  152. 'pest': QColor(230, 190, 255) # 紫色
  153. }
  154. return type_colors.get(alert_type, QColor(240, 240, 240))
  155. def get_alert_level_name(self, level):
  156. """获取告警等级的中文名称
  157. Args:
  158. level (int): 告警等级
  159. Returns:
  160. str: 告警等级的中文名称
  161. """
  162. level_names = {
  163. 1: "一级 (紧急)",
  164. 2: "二级 (高危)",
  165. 3: "三级 (中危)",
  166. 4: "四级 (低危)",
  167. 5: "五级 (提示)"
  168. }
  169. return level_names.get(level, "未知等级")
  170. def get_alert_level_color(self, level):
  171. """获取告警等级显示颜色"""
  172. level_colors = {
  173. 'high': QColor(255, 100, 100), # 红色
  174. 'medium': QColor(255, 200, 100), # 橙色
  175. 'low': QColor(200, 200, 200), # 灰色
  176. 'processed': QColor(100, 220, 100) # 绿色,表示已处理
  177. }
  178. return level_colors.get(level, QColor(240, 240, 240))
  179. @pyqtSlot(int)
  180. def filter_alerts(self, index):
  181. """过滤告警"""
  182. # 获取当前过滤类型
  183. self.current_filter = self.filter_combo.currentData()
  184. self.current_severity = self.severity_combo.currentData()
  185. # 清空表格
  186. self.alert_table.setRowCount(0)
  187. # 重新添加符合条件的告警
  188. for alert in self.alerts:
  189. type_match = self.current_filter == "all" or alert['type'] == self.current_filter
  190. severity_match = self.current_severity == "all" or alert['level'] == self.current_severity
  191. if type_match and severity_match:
  192. self.add_filtered_alert(alert)
  193. def add_filtered_alert(self, alert):
  194. """添加过滤后的告警到表格(不添加到告警列表)"""
  195. row = self.alert_table.rowCount()
  196. self.alert_table.insertRow(row)
  197. # 设置单元格内容
  198. self.alert_table.setItem(row, 0, QTableWidgetItem(alert['time']))
  199. # 根据类型设置显示名称和颜色
  200. type_item = QTableWidgetItem(self.get_alert_type_name(alert['type']))
  201. type_item.setData(Qt.UserRole, alert['type'])
  202. type_item.setBackground(self.get_alert_type_color(alert['type']))
  203. self.alert_table.setItem(row, 1, type_item)
  204. self.alert_table.setItem(row, 2, QTableWidgetItem(alert['location']))
  205. self.alert_table.setItem(row, 3, QTableWidgetItem(alert['detail']))
  206. # 根据等级设置显示名称和颜色
  207. level_item = QTableWidgetItem(self.get_alert_level_name(alert['level']))
  208. level_item.setBackground(self.get_alert_level_color(alert['level']))
  209. self.alert_table.setItem(row, 4, level_item)
  210. # 操作按钮
  211. btn_cell = QWidget()
  212. btn_layout = QHBoxLayout(btn_cell)
  213. btn_layout.setContentsMargins(2, 2, 2, 2)
  214. details_btn = QPushButton("详情")
  215. details_btn.setFixedWidth(60)
  216. details_btn.clicked.connect(lambda _, a=alert: self.show_alert_details(a))
  217. handle_btn = QPushButton("处理")
  218. handle_btn.setFixedWidth(60)
  219. if alert['level'] == 'high':
  220. handle_btn.setEnabled(False)
  221. handle_btn.clicked.connect(lambda _, r=row: self.handle_alert(r))
  222. btn_layout.addWidget(details_btn)
  223. btn_layout.addWidget(handle_btn)
  224. btn_cell.setLayout(btn_layout)
  225. self.alert_table.setCellWidget(row, 5, btn_cell)
  226. # 自动滚动到最新行
  227. self.alert_table.scrollToItem(self.alert_table.item(row, 0))
  228. @pyqtSlot()
  229. def clear_alerts(self):
  230. """清空告警"""
  231. self.alerts = []
  232. self.alert_table.setRowCount(0)
  233. @pyqtSlot(int, int)
  234. def show_alert_detail(self, row, column):
  235. """显示告警详情(双击行时触发)"""
  236. # 实际项目中可以打开告警详情对话框
  237. print(f"显示第 {row} 行告警详情")
  238. def show_alert_details(self, alert):
  239. """显示告警详情"""
  240. # 防止重复触发
  241. current_time = datetime.now()
  242. if hasattr(self, 'last_detail_time'):
  243. if (current_time - self.last_detail_time).total_seconds() < 1:
  244. return
  245. self.last_detail_time = current_time
  246. msg = QMessageBox()
  247. msg.setWindowTitle("预警详情")
  248. details = f"""
  249. 时间:{alert['time']}
  250. 类型:{self.get_alert_type_name(alert['type'])}
  251. 位置:{alert['location']}
  252. 严重程度:{alert['level']}
  253. 详细信息:{alert['detail']}
  254. """
  255. msg.setText(details)
  256. msg.setIcon(QMessageBox.Information)
  257. msg.exec_()
  258. def handle_alert(self, row):
  259. """处理告警"""
  260. # 防止重复处理
  261. current_time = datetime.now()
  262. if hasattr(self, 'last_handle_time'):
  263. if (current_time - self.last_handle_time).total_seconds() < 1:
  264. return
  265. self.last_handle_time = current_time
  266. # 获取告警数据
  267. alert = self.alerts[row]
  268. # 向护林员发送通知
  269. self.send_notification_to_ranger(alert)
  270. # 降低告警等级
  271. original_level = alert['level']
  272. if alert['level'] == 'high':
  273. alert['level'] = 'medium'
  274. elif alert['level'] == 'medium':
  275. alert['level'] = 'low'
  276. elif alert['level'] == 'low':
  277. alert['level'] = 'processed' # 添加'processed'状态表示已完全处理
  278. # 更新UI显示
  279. level_name = self.get_alert_level_name(alert['level'])
  280. level_color = self.get_alert_level_color(alert['level'])
  281. level_item = QTableWidgetItem(level_name)
  282. level_item.setBackground(level_color)
  283. self.alert_table.setItem(row, 4, level_item)
  284. # 如果已完全处理,禁用处理按钮
  285. if alert['level'] == 'processed':
  286. cell_widget = self.alert_table.cellWidget(row, 5)
  287. if cell_widget:
  288. for child in cell_widget.children():
  289. if isinstance(child, QPushButton) and child.text() == "处理":
  290. child.setEnabled(False)
  291. child.setText("已处理")
  292. break
  293. # 发送告警已处理信号
  294. print(f"发送告警处理信号: 类型={alert['type']}, 区域={alert['location']}")
  295. self.alert_processed.emit(alert['type'], alert['location'])
  296. # 滚动到当前行
  297. self.alert_table.scrollToItem(self.alert_table.item(row, 0))
  298. def send_notification_to_ranger(self, alert):
  299. """向护林员发送通知
  300. Args:
  301. alert (dict): 告警信息
  302. """
  303. from PyQt5.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton,
  304. QFrame, QSpacerItem, QSizePolicy, QProgressBar)
  305. from PyQt5.QtGui import QFont, QPixmap, QIcon
  306. from PyQt5.QtCore import Qt, QTimer
  307. import os
  308. # 根据告警类型确定应联系的组织
  309. alert_type = alert['type']
  310. organization = self.get_responsible_organization(alert_type)
  311. # 创建自定义对话框
  312. dialog = QDialog(self)
  313. dialog.setWindowTitle(f"通知{organization}")
  314. dialog.setMinimumWidth(500)
  315. dialog.setStyleSheet("""
  316. QDialog {
  317. background-color: #f5f5f5;
  318. border: 1px solid #e0e0e0;
  319. border-radius: 5px;
  320. }
  321. QLabel {
  322. color: #333333;
  323. }
  324. QPushButton {
  325. background-color: #2196f3;
  326. color: white;
  327. border: none;
  328. padding: 8px 16px;
  329. border-radius: 4px;
  330. }
  331. QPushButton:hover {
  332. background-color: #0d8bf2;
  333. }
  334. QPushButton:pressed {
  335. background-color: #0a75cf;
  336. }
  337. QFrame {
  338. border: 1px solid #e0e0e0;
  339. border-radius: 4px;
  340. background-color: white;
  341. }
  342. QProgressBar {
  343. border: 1px solid #e0e0e0;
  344. border-radius: 4px;
  345. background-color: #f0f0f0;
  346. text-align: center;
  347. }
  348. QProgressBar::chunk {
  349. background-color: #4caf50;
  350. border-radius: 3px;
  351. }
  352. """)
  353. # 创建布局
  354. layout = QVBoxLayout(dialog)
  355. # 标题区域
  356. title_layout = QHBoxLayout()
  357. # 尝试根据告警类型添加图标
  358. icon_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'assets', f"{alert_type}.png")
  359. icon_label = QLabel()
  360. if os.path.exists(icon_path):
  361. pixmap = QPixmap(icon_path).scaled(48, 48, Qt.KeepAspectRatio, Qt.SmoothTransformation)
  362. icon_label.setPixmap(pixmap)
  363. else:
  364. # 使用默认警告图标
  365. icon_label.setText("⚠️")
  366. icon_label.setFont(QFont("Arial", 24))
  367. icon_label.setFixedSize(60, 60)
  368. icon_label.setAlignment(Qt.AlignCenter)
  369. title_layout.addWidget(icon_label)
  370. # 标题文本
  371. title_text = QLabel("正在发送告警通知...")
  372. title_text.setFont(QFont("Microsoft YaHei", 14, QFont.Bold))
  373. title_layout.addWidget(title_text, 1)
  374. layout.addLayout(title_layout)
  375. # 进度条
  376. progress_bar = QProgressBar()
  377. progress_bar.setRange(0, 100)
  378. progress_bar.setValue(0)
  379. progress_bar.setFixedHeight(20)
  380. layout.addWidget(progress_bar)
  381. # 状态标签
  382. status_label = QLabel("正在连接通信系统...")
  383. status_label.setAlignment(Qt.AlignCenter)
  384. layout.addWidget(status_label)
  385. # 分隔线
  386. separator = QFrame()
  387. separator.setFrameShape(QFrame.HLine)
  388. separator.setFrameShadow(QFrame.Sunken)
  389. layout.addWidget(separator)
  390. # 信息面板
  391. info_frame = QFrame()
  392. info_layout = QVBoxLayout(info_frame)
  393. # 添加告警信息
  394. info_layout.addWidget(self.create_info_row("告警类型", self.get_alert_type_name(alert_type)))
  395. info_layout.addWidget(self.create_info_row("告警区域", alert['location']))
  396. info_layout.addWidget(self.create_info_row("告警等级", self.get_alert_level_name(alert['level'])))
  397. info_layout.addWidget(self.create_info_row("详细信息", alert['detail']))
  398. info_layout.addWidget(self.create_info_row("时间", alert['time']))
  399. info_layout.addWidget(self.create_info_row("接收组织", organization))
  400. layout.addWidget(info_frame)
  401. # 添加消息
  402. message_label = QLabel("")
  403. message_label.setWordWrap(True)
  404. message_label.setAlignment(Qt.AlignCenter)
  405. message_label.setFont(QFont("Microsoft YaHei", 10))
  406. message_label.setStyleSheet("color: #666666; margin: 10px;")
  407. layout.addWidget(message_label)
  408. # 按钮区域
  409. button_layout = QHBoxLayout()
  410. button_layout.addStretch()
  411. # 禁用关闭按钮,等待通知发送完成
  412. close_button = QPushButton("关闭")
  413. close_button.setFixedWidth(120)
  414. close_button.setEnabled(False) # 先禁用按钮
  415. close_button.clicked.connect(dialog.accept)
  416. button_layout.addWidget(close_button)
  417. layout.addLayout(button_layout)
  418. # 设置进度条更新的定时器
  419. progress = 0
  420. timer = QTimer(dialog)
  421. # 进度模拟阶段
  422. stages = [
  423. (10, "正在连接通信系统..."),
  424. (30, f"正在向{organization}发送告警信息..."),
  425. (60, f"等待{organization}确认接收..."),
  426. (90, f"{organization}已确认接收告警信息"),
  427. (100, f"通知流程完成,{organization}将立即处理")
  428. ]
  429. current_stage = 0
  430. def update_progress():
  431. nonlocal progress, current_stage
  432. # 更新进度条
  433. progress += 5
  434. if progress > 100:
  435. progress = 100
  436. progress_bar.setValue(progress)
  437. # 检查是否需要更新阶段
  438. if current_stage < len(stages) and progress >= stages[current_stage][0]:
  439. status_label.setText(stages[current_stage][1])
  440. current_stage += 1
  441. # 通知完成时
  442. if progress >= 100:
  443. timer.stop()
  444. title_text.setText(f"已向{organization}发送告警通知")
  445. message_label.setText(f"相关{organization}已接收通知,并将前往现场处理。\n系统会持续跟踪处理进度,直至告警解除。")
  446. close_button.setEnabled(True) # 启用关闭按钮
  447. # 在控制台打印日志
  448. print(f"已向{organization}发送告警通知: {alert_type} - {alert['location']}")
  449. # 启动定时器
  450. timer.timeout.connect(update_progress)
  451. timer.start(150) # 每150毫秒更新一次
  452. # 显示对话框
  453. dialog.exec_()
  454. def create_info_row(self, label_text, value_text):
  455. """创建信息行
  456. Args:
  457. label_text (str): 标签文本
  458. value_text (str): 值文本
  459. Returns:
  460. QWidget: 包含标签和值的行
  461. """
  462. from PyQt5.QtWidgets import QWidget, QHBoxLayout, QLabel
  463. from PyQt5.QtGui import QFont
  464. from PyQt5.QtCore import Qt
  465. row = QWidget()
  466. layout = QHBoxLayout(row)
  467. layout.setContentsMargins(0, 5, 0, 5)
  468. label = QLabel(label_text + ":")
  469. label.setFixedWidth(80)
  470. label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
  471. label.setFont(QFont("Microsoft YaHei", 10, QFont.Bold))
  472. value = QLabel(value_text)
  473. value.setWordWrap(True)
  474. value.setFont(QFont("Microsoft YaHei", 10))
  475. value.setStyleSheet("color: #333333;")
  476. layout.addWidget(label)
  477. layout.addWidget(value, 1)
  478. return row
  479. def get_responsible_organization(self, alert_type):
  480. """根据告警类型获取负责组织
  481. Args:
  482. alert_type (str): 告警类型
  483. Returns:
  484. str: 负责组织名称
  485. """
  486. organizations = {
  487. "fire": "森林消防队",
  488. "animal": "野生动物保护中心",
  489. "landslide": "地质灾害应急中心",
  490. "forest_degradation": "森林修复小组",
  491. "pest": "病虫害防治站"
  492. }
  493. return organizations.get(alert_type, "森林管理部门")
  494. def toggle_random_alerts(self):
  495. """切换随机告警功能"""
  496. self.random_alert_config['enabled'] = not self.random_alert_config['enabled']
  497. self.random_alert_btn.setText(f"随机告警: {'开' if self.random_alert_config['enabled'] else '关'}")
  498. # 立即生成一个告警作为反馈
  499. if self.random_alert_config['enabled']:
  500. self.generate_random_alert()
  501. def generate_random_alert(self):
  502. """生成一个随机告警"""
  503. # 根据当前过滤类型选择告警类型
  504. if self.current_filter != "all":
  505. alert_type = self.current_filter
  506. else:
  507. alert_type = random.choice(self.random_alert_config['types'])
  508. # 根据当前严重程度过滤选择告警等级
  509. if self.current_severity != "all":
  510. alert_level = self.current_severity
  511. else:
  512. alert_level = random.choice(['high', 'medium', 'low'])
  513. alert_location = random.choice(self.random_alert_config['locations'])
  514. print(f"告警面板生成新告警: 类型={alert_type}, 区域={alert_location}")
  515. # 为病虫害生成特殊的详情
  516. if alert_type == 'pest':
  517. pest_types = ['松毛虫', '美国白蛾', '落叶松毛虫', '杨树食叶害虫', '松材线虫病']
  518. pest_type = random.choice(pest_types)
  519. area = random.randint(10, 200)
  520. detail = f'检测到{pest_type}病虫害,受灾面积约{area}平方米'
  521. else:
  522. detail = f'新检测到的告警 #{len(self.alerts) + 1}'
  523. alert = {
  524. 'time': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
  525. 'type': alert_type,
  526. 'location': alert_location,
  527. 'detail': detail,
  528. 'level': alert_level
  529. }
  530. self.add_alert(alert)
  531. def update_alerts(self):
  532. """更新告警(由定时器调用)"""
  533. # 如果启用了随机告警,则有机会生成新告警
  534. if self.random_alert_config['enabled'] and random.random() < self.random_alert_config['probability']:
  535. self.generate_random_alert()
  536. # 更新UI显示
  537. self.alert_table.viewport().update()