2424from backend .core .notify .exceptions import NotifyBaseException
2525from backend .core .notify .template import FAILED_TEMPLATE , FINISHED_TEMPLATE , TERMINATE_TEMPLATE , TODO_TEMPLATE
2626from backend .db_meta .models import AppCache
27+ from backend .exceptions import ApiResultError
2728from backend .ticket .builders import BuilderFactory
28- from backend .ticket .constants import TicketStatus , TicketType
29+ from backend .ticket .constants import TicketStatus , TicketType , TodoStatus
2930from backend .ticket .models import Flow , Ticket
3031from backend .ticket .todos import ActionType
3132from backend .utils .cache import func_cache_decorator
32- from backend .utils .time import datetime2str
3333
3434logger = logging .getLogger ("root" )
3535
@@ -78,20 +78,25 @@ def get_actions(msg_type, ticket):
7878 """获取bkchat操作按钮"""
7979 if ticket .status not in [TicketStatus .APPROVE , TicketStatus .TODO ]:
8080 return []
81+
82+ todo = ticket .todo_of_ticket .filter (status = TodoStatus .TODO ).first ()
83+ if not todo :
84+ return []
85+
8186 # 增加回调按钮,执行和终止
8287 agree_action = {
8388 "name" : _ ("同意" ) if ticket .status == TicketStatus .APPROVE else _ ("确认执行" ),
8489 "color" : "green" ,
85- "callback_url" : f"{ env .BK_DBM_APIGATEWAY } /tickets/batch_process_ticket /" ,
86- "callback_data" : {"action" : ActionType .APPROVE .value , "ticket_ids " : [ ticket .id ] },
90+ "callback_url" : f"{ env .BK_DBM_APIGATEWAY } /tickets/bkchat_process_todo /" ,
91+ "callback_data" : {"action" : ActionType .APPROVE .value , "todo_id " : todo .id , "params" : {} },
8792 }
8893 refuse_action = {
8994 "name" : _ ("拒绝" ) if ticket .status == TicketStatus .APPROVE else _ ("终止单据" ),
9095 "color" : "red" ,
91- "callback_url" : f"{ env .BK_DBM_APIGATEWAY } /tickets/batch_process_ticket /" ,
96+ "callback_url" : f"{ env .BK_DBM_APIGATEWAY } /tickets/bkchat_process_todo /" ,
9297 "callback_data" : {
9398 "action" : ActionType .TERMINATE .value ,
94- "ticket_ids " : [ ticket .id ] ,
99+ "todo_id " : todo .id ,
95100 "params" : {"remark" : _ ("使用「蓝鲸审批助手」终止单据" )},
96101 },
97102 }
@@ -178,6 +183,8 @@ def send_mail(self, sender: str = None, cc: list = None):
178183 kwargs .update (sender = sender )
179184 if cc :
180185 kwargs .update (cc__username = "," .join (cc ))
186+ # 邮件的换行要用<br>的html
187+ self .content = self .content .replace ("\n " , "<br>" )
181188 self ._cmsi_send_msg (MsgType .MAIL , ** kwargs )
182189
183190 def send_voice (self ):
@@ -193,7 +200,9 @@ def send_rtx(self):
193200 self ._cmsi_send_msg (MsgType .RTX .value )
194201
195202 def send_sms (self ):
196- """发送企微消息"""
203+ """发送短信消息"""
204+ # 短信消息没有标题参数,直接把标题和内容放在一起
205+ self .content = f"{ self .title } \n { self .content } "
197206 self ._cmsi_send_msg (MsgType .SMS .value )
198207
199208 def send_wecom_robot (self ):
@@ -238,7 +247,11 @@ def __init__(self, ticket_id: int, flow_id: int = None):
238247 def get_support_msg_types (cls ):
239248 # 获取当前环境下支持的通知类型
240249 # 所有的拓展方式都需要接入CMSI,所以直接返回CMSI支持方式即可
241- return CmsiApi .get_msg_type ()
250+ # 暂不暴露微信的通知方式
251+ msg_types = CmsiApi .get_msg_type ()
252+ msg_type_map = {msg ["type" ]: msg for msg in msg_types }
253+ msg_type_map [MsgType .WEIXIN .value ]["is_active" ] = False
254+ return list (msg_type_map .values ())
242255
243256 def get_notify_class (self , msg_type : str ):
244257 # 根据通知类型获取通知类,以及通知所需的上下文
@@ -253,15 +266,17 @@ def get_receivers(self):
253266 biz_helpers = BizSettings .get_assistance (self .bk_biz_id )
254267 creator = [self .ticket .creator ]
255268 # 待审批:审批人
256- # 待执行、待补货、待确认、已失败、已完成、已终止: 提单人、协助人
269+ # 待执行、待补货、待确认、已失败、已完成、已终止:提单人、协助人
257270 # 暂不通知DBA
258271 if self .phase in [TicketStatus .PENDING ]:
259- return creator
272+ receivers = creator
260273 elif self .phase in [TicketStatus .APPROVE ]:
261274 itsm_builder = BuilderFactory .get_builder_cls (self .ticket .ticket_type ).itsm_flow_builder (self .ticket )
262- return itsm_builder .get_approvers ().split ("," )
275+ receivers = itsm_builder .get_approvers ().split ("," )
263276 else :
264- return creator + biz_helpers
277+ receivers = creator + biz_helpers
278+ # 去重后返回
279+ return list (dict .fromkeys (receivers ))
265280
266281 def render_msg_template (self , msg_type : str ):
267282 # 获取标题,在群机器人通知则加上@人
@@ -289,8 +304,8 @@ def render_msg_template(self, msg_type: str):
289304 "cluster_domains" : "," .join (self .clusters ),
290305 "remark" : self .ticket .remark ,
291306 "creator" : self .ticket .creator ,
292- "submit_time" : datetime2str ( self .ticket .create_at ),
293- "update_time" : datetime2str ( self .ticket .update_at ),
307+ "submit_time" : self .ticket .create_at . astimezone (). strftime ( "%Y-%m-%d %H:%M:%S%z" ),
308+ "update_time" : self .ticket .update_at . astimezone (). strftime ( "%Y-%m-%d %H:%M:%S%z" ),
294309 "status" : TicketStatus .get_choice_label (self .phase ),
295310 "operators" : "," .join (self .ticket .get_current_operators ()),
296311 "detail_address" : self .ticket .url ,
@@ -325,17 +340,13 @@ def send_msg(self):
325340 if msg_type == MsgType .WECOM_ROBOT :
326341 self .receivers = send_msg_config .get (MsgType .WECOM_ROBOT .value , [])
327342
328- notify_class (title , content , self .receivers ).send_msg (msg_type , context = context )
343+ try :
344+ notify_class (title , content , self .receivers ).send_msg (msg_type , context = context )
345+ except (ApiResultError , Exception ) as e :
346+ logger .error (_ ("[{}]消息发送失败,错误信息: {}" ).format (MsgType .get_choice_label (msg_type ), e ))
329347
330348
331349@shared_task
332- def send_msg (ticket_id : int , flow_id : int = None , raise_exception : bool = False ):
350+ def send_msg (ticket_id : int , flow_id : int = None ):
333351 # 可异步发送消息,非阻塞路径默认不抛出异常
334- try :
335- NotifyAdapter (ticket_id , flow_id ).send_msg ()
336- except Exception as e :
337- err_msg = _ ("消息发送失败,错误信息:{}" ).format (e )
338- if not raise_exception :
339- logger .error (err_msg )
340- else :
341- raise NotifyBaseException (err_msg )
352+ NotifyAdapter (ticket_id , flow_id ).send_msg ()
0 commit comments