11"""通知系统数据模型"""
22
3+ import logging
4+ from datetime import timedelta
5+
36from django .db import models
7+ from django .utils import timezone
8+
9+ from .types import NotificationCategory , NotificationLevel
410
5- from . types import NotificationLevel , NotificationCategory
11+ logger = logging . getLogger ( __name__ )
612
713
814class NotificationSettings (models .Model ):
915 """
1016 通知设置(单例模型)
1117 存储 Discord webhook 配置和各分类的通知开关
1218 """
13-
19+
1420 # Discord 配置
1521 discord_enabled = models .BooleanField (default = False , help_text = '是否启用 Discord 通知' )
1622 discord_webhook_url = models .URLField (blank = True , default = '' , help_text = 'Discord Webhook URL' )
17-
23+
24+ # 企业微信配置
25+ wecom_enabled = models .BooleanField (default = False , help_text = '是否启用企业微信通知' )
26+ wecom_webhook_url = models .URLField (blank = True , default = '' , help_text = '企业微信机器人 Webhook URL' )
27+
1828 # 分类开关(使用 JSONField 存储)
1929 categories = models .JSONField (
2030 default = dict ,
2131 help_text = '各分类通知开关,如 {"scan": true, "vulnerability": true, "asset": true, "system": false}'
2232 )
23-
33+
2434 # 时间信息
2535 created_at = models .DateTimeField (auto_now_add = True )
2636 updated_at = models .DateTimeField (auto_now = True )
27-
37+
2838 class Meta :
2939 db_table = 'notification_settings'
3040 verbose_name = '通知设置'
3141 verbose_name_plural = '通知设置'
32-
42+
3343 def save (self , * args , ** kwargs ):
34- # 单例模式:强制只有一条记录
35- self .pk = 1
44+ self .pk = 1 # 单例模式
3645 super ().save (* args , ** kwargs )
37-
46+
3847 @classmethod
3948 def get_instance (cls ) -> 'NotificationSettings' :
4049 """获取或创建单例实例"""
@@ -52,44 +61,41 @@ def get_instance(cls) -> 'NotificationSettings':
5261 }
5362 )
5463 return obj
55-
64+
5665 def is_category_enabled (self , category : str ) -> bool :
5766 """检查指定分类是否启用通知"""
5867 return self .categories .get (category , False )
5968
6069
6170class Notification (models .Model ):
6271 """通知模型"""
63-
72+
6473 id = models .AutoField (primary_key = True )
65-
66- # 通知分类
74+
6775 category = models .CharField (
6876 max_length = 20 ,
6977 choices = NotificationCategory .choices ,
7078 default = NotificationCategory .SYSTEM ,
7179 db_index = True ,
7280 help_text = '通知分类'
7381 )
74-
75- # 通知级别
82+
7683 level = models .CharField (
7784 max_length = 20 ,
7885 choices = NotificationLevel .choices ,
7986 default = NotificationLevel .LOW ,
8087 db_index = True ,
8188 help_text = '通知级别'
8289 )
83-
90+
8491 title = models .CharField (max_length = 200 , help_text = '通知标题' )
8592 message = models .CharField (max_length = 2000 , help_text = '通知内容' )
86-
87- # 时间信息
93+
8894 created_at = models .DateTimeField (auto_now_add = True , help_text = '创建时间' )
89-
95+
9096 is_read = models .BooleanField (default = False , help_text = '是否已读' )
9197 read_at = models .DateTimeField (null = True , blank = True , help_text = '阅读时间' )
92-
98+
9399 class Meta :
94100 db_table = 'notification'
95101 verbose_name = '通知'
@@ -101,44 +107,26 @@ class Meta:
101107 models .Index (fields = ['level' , '-created_at' ]),
102108 models .Index (fields = ['is_read' , '-created_at' ]),
103109 ]
104-
110+
105111 def __str__ (self ):
106112 return f"{ self .get_level_display ()} - { self .title } "
107-
113+
108114 @classmethod
109- def cleanup_old_notifications (cls ):
110- """
111- 清理超过15天的旧通知(硬编码)
112-
113- Returns:
114- int: 删除的通知数量
115- """
116- from datetime import timedelta
117- from django .utils import timezone
118-
119- # 硬编码:只保留最近15天的通知
115+ def cleanup_old_notifications (cls ) -> int :
116+ """清理超过15天的旧通知"""
120117 cutoff_date = timezone .now () - timedelta (days = 15 )
121- delete_result = cls .objects .filter (created_at__lt = cutoff_date ).delete ()
122-
123- return delete_result [0 ] if delete_result [0 ] else 0
124-
118+ deleted_count , _ = cls .objects .filter (created_at__lt = cutoff_date ).delete ()
119+ return deleted_count or 0
120+
125121 def save (self , * args , ** kwargs ):
126- """
127- 重写save方法,在创建新通知时自动清理旧通知
128- """
122+ """重写save方法,在创建新通知时自动清理旧通知"""
129123 is_new = self .pk is None
130124 super ().save (* args , ** kwargs )
131-
132- # 只在创建新通知时执行清理(自动清理超过15天的通知)
125+
133126 if is_new :
134127 try :
135128 deleted_count = self .__class__ .cleanup_old_notifications ()
136129 if deleted_count > 0 :
137- import logging
138- logger = logging .getLogger (__name__ )
139- logger .info (f"自动清理了 { deleted_count } 条超过15天的旧通知" )
140- except Exception as e :
141- # 清理失败不应影响通知创建
142- import logging
143- logger = logging .getLogger (__name__ )
144- logger .warning (f"通知自动清理失败: { e } " )
130+ logger .info ("自动清理了 %d 条超过15天的旧通知" , deleted_count )
131+ except Exception :
132+ logger .warning ("通知自动清理失败" , exc_info = True )
0 commit comments