From 25466d83b5c8dc2db3589f6b2cbe90aab5a4ccfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= Date: Thu, 28 May 2026 13:50:58 +0800 Subject: [PATCH] =?UTF-8?q?ai=E6=A8=A1=E5=9D=97=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yuthon_wechat/__manifest__.py | 1 + yuthon_wechat/models/__init__.py | 1 + yuthon_wechat/models/wecom_ai_chat.py | 25 ++++ yuthon_wechat/models/wecom_ai_message_log.py | 28 +++++ yuthon_wechat/security/ir.model.access.csv | 1 + yuthon_wechat/views/wecom_ai_views.xml | 126 +++++++++++++++++++ 6 files changed, 182 insertions(+) create mode 100644 yuthon_wechat/models/wecom_ai_message_log.py create mode 100644 yuthon_wechat/views/wecom_ai_views.xml diff --git a/yuthon_wechat/__manifest__.py b/yuthon_wechat/__manifest__.py index 7aae307ab..89eeeb11e 100644 --- a/yuthon_wechat/__manifest__.py +++ b/yuthon_wechat/__manifest__.py @@ -27,6 +27,7 @@ 'views/res_users_views.xml', 'wizard/wecom_api_sync_wizard.xml', 'views/wx_work_views.xml', + 'views/wecom_ai_views.xml', ], # "assets": { # "web.assets_frontend": [ diff --git a/yuthon_wechat/models/__init__.py b/yuthon_wechat/models/__init__.py index f62ee8d2e..b4282cae6 100644 --- a/yuthon_wechat/models/__init__.py +++ b/yuthon_wechat/models/__init__.py @@ -7,6 +7,7 @@ from . import res_users from . import wecom_apps_config from . import wx_work from . import wecom_ai_chat +from . import wecom_ai_message_log diff --git a/yuthon_wechat/models/wecom_ai_chat.py b/yuthon_wechat/models/wecom_ai_chat.py index 9702992cf..b641fdfe5 100644 --- a/yuthon_wechat/models/wecom_ai_chat.py +++ b/yuthon_wechat/models/wecom_ai_chat.py @@ -21,11 +21,18 @@ class WecomAiChat(models.Model): user_id = fields.Many2one('res.users', string='关联用户', index=True) conversation_id = fields.Many2one('ai.conversation', string='AI对话', index=True) last_message_time = fields.Datetime(string='最后消息时间') + log_ids = fields.One2many('wecom.ai.message.log', 'chat_id', string='消息日志') + log_count = fields.Integer(string='消息数', compute='_compute_log_count') _sql_constraints = [ ('wecom_userid_unique', 'UNIQUE(wecom_userid)', '每个企业微信用户只能有一条AI对话记录'), ] + @api.depends('log_ids') + def _compute_log_count(self): + for rec in self: + rec.log_count = len(rec.log_ids) + @api.model def process_ai_message(self, wecom_userid, content): """ @@ -98,6 +105,9 @@ class WecomAiChat(models.Model): self._send_wecom_reply(wecom_userid, reply_text) + # 6. 记录消息日志 + self._log_message(chat_record, wecom_userid, content, reply_text) + # 更新最后消息时间 chat_record.write({'last_message_time': fields.Datetime.now()}) _logger.info("企业微信AI消息处理完成: user=%s", wecom_userid) @@ -180,6 +190,21 @@ class WecomAiChat(models.Model): except Exception as e: _logger.exception("企业微信AI回复推送失败 [user=%s]: %s", wecom_userid, e) + def _log_message(self, chat_record, wecom_userid, user_content, ai_reply): + """记录企业微信AI消息日志""" + try: + self.env['wecom.ai.message.log'].sudo().create({ + 'chat_id': chat_record.id if chat_record else False, + 'wecom_userid': wecom_userid, + 'user_id': chat_record.user_id.id if chat_record and chat_record.user_id else False, + 'user_message': user_content, + 'ai_reply': ai_reply, + 'message_time': fields.Datetime.now(), + 'status': 'success', + }) + except Exception as e: + _logger.warning("记录消息日志失败: %s", e) + @api.model def reset_conversation(self, wecom_userid): """ diff --git a/yuthon_wechat/models/wecom_ai_message_log.py b/yuthon_wechat/models/wecom_ai_message_log.py new file mode 100644 index 000000000..abed137ff --- /dev/null +++ b/yuthon_wechat/models/wecom_ai_message_log.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +""" +企业微信 AI 消息日志 +记录通过企业微信与 AI 交互的每条消息 +""" + +from odoo import models, fields + + +class WecomAiMessageLog(models.Model): + """企业微信AI消息日志""" + _name = 'wecom.ai.message.log' + _description = '企业微信AI消息日志' + _order = 'message_time desc' + + chat_id = fields.Many2one('wecom.ai.chat', string='对话记录', index=True, ondelete='set null') + wecom_userid = fields.Char(string='企业微信UserID', index=True) + user_id = fields.Many2one('res.users', string='用户') + user_name = fields.Char(string='用户名称', related='user_id.name', store=True) + user_message = fields.Text(string='用户消息') + ai_reply = fields.Text(string='AI回复') + message_time = fields.Datetime(string='消息时间', default=fields.Datetime.now, index=True) + status = fields.Selection([ + ('success', '成功'), + ('error', '失败'), + ('timeout', '超时'), + ], string='状态', default='success') + error_message = fields.Char(string='错误信息') diff --git a/yuthon_wechat/security/ir.model.access.csv b/yuthon_wechat/security/ir.model.access.csv index 2dc991a49..5466c8882 100644 --- a/yuthon_wechat/security/ir.model.access.csv +++ b/yuthon_wechat/security/ir.model.access.csv @@ -3,5 +3,6 @@ access_wecom_api,wecom.api.user,model_wecom_api,,1,1,0,1 access_wecom_apps,wecom.apps.user,model_wecom_apps,,1,1,1,1 access__wecom_apps_config,wecom.app.config.user,model_wecom_apps_config,,1,1,1,1 access_wecom_ai_chat,wecom.ai.chat.user,model_wecom_ai_chat,,1,1,1,1 +access_wecom_ai_message_log,wecom.ai.message.log.user,model_wecom_ai_message_log,,1,1,1,1 access_wecom_api_sync_wizard_manager,wecom.api.sync.wizard,model_wecom_api_sync_wizard,,1,1,1,1 diff --git a/yuthon_wechat/views/wecom_ai_views.xml b/yuthon_wechat/views/wecom_ai_views.xml new file mode 100644 index 000000000..d704220cd --- /dev/null +++ b/yuthon_wechat/views/wecom_ai_views.xml @@ -0,0 +1,126 @@ + + + + + + + wecom.ai.message.log.tree + wecom.ai.message.log + + + + + + + + + + + + + + + + + wecom.ai.message.log.form + wecom.ai.message.log + +
+ + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + + + wecom.ai.message.log.search + wecom.ai.message.log + + + + + + + + + + + + + + + + + + + + + + + + 企业微信消息日志 + wecom.ai.message.log + tree,form + {'search_default_today': 1} + + + + + + + + + wecom.ai.chat.tree + wecom.ai.chat + + + + + + + + + + + + + 企业微信AI对话 + wecom.ai.chat + tree,form + + + +