当前位置: 首页 > news >正文

Odoo12自定义弹窗实现与优化实践

1. 项目背景与需求分析

在Odoo12开发过程中,系统默认的消息提示机制存在几个明显痛点。最常见的就是使用raise抛出UserError或Warning异常时,会显示"Odoo Server Error"这样的系统错误标题,不仅视觉上不专业,更重要的是在Dialog弹窗场景下会导致表单数据丢失。这种体验对终端用户极不友好。

我在实际项目中就遇到过这样的案例:财务人员在审核付款单时,系统提示"供应商银行信息不完整",但由于使用了传统的异常抛出方式,导致已填写的20多个字段数据全部清空。这种设计缺陷直接影响了业务流程效率。

2. 技术方案设计思路

2.1 传统方案的局限性

Odoo原生提供的消息提示方式主要有:

  • raise UserError('message')
  • raise Warning('message')
  • return { 'warning': {'title': '提示', 'message': '内容'} }

这些方式共同的缺点是:

  1. 样式不可定制,始终带有错误警示标识
  2. 弹窗关闭后无法执行回调函数
  3. 在复杂表单中可能引发数据丢失

2.2 自定义弹窗的优势

我们采用TransientModel(临时模型)+ 自定义视图的方案,可以实现:

  1. 完全可控的UI样式
  2. 支持自定义按钮和回调事件
  3. 保持主表单数据不丢失
  4. 可扩展的交互逻辑

3. 完整实现步骤

3.1 创建消息向导模型

在models目录下新建my_message_wizard.py:

from odoo import models, fields, api class MyMessageWizard(models.TransientModel): _name = 'my.message.wizard' _description = '自定义消息弹窗' message = fields.Text( string='消息内容', required=True, readonly=True ) @api.multi def action_confirm(self): """确认按钮回调方法""" return {'type': 'ir.actions.act_window_close'}

关键点说明:

  1. 必须继承TransientModel而非Model
  2. 字段设置为readonly防止误修改
  3. 返回标准窗口关闭动作

3.2 设计弹窗视图

在views目录创建my_message_wizard.xml:

<odoo> <record id="my_message_wizard_form" model="ir.ui.view"> <field name="name">message.wizard.form</field> <field name="model">my.message.wizard</field> <field name="arch" type="xml"> <form string="系统提示"> <sheet> <div class="oe_title"> <h1><i class="fa fa-info-circle"/> 重要提示</h1> </div> <group> <field name="message" class="oe_inline" widget="html"/> </group> </sheet> <footer> <button name="action_confirm" string="确认" type="object" class="btn-primary" default_focus="1"/> </footer> </form> </field> </record> </odoo>

视图设计技巧:

  1. 使用sheet和group规范布局
  2. 添加Font Awesome图标增强视觉效果
  3. 采用html widget支持富文本内容
  4. 设置default_focus让按钮自动获得焦点

3.3 注册模块资源

在__manifest__.py中添加:

'data': [ 'views/my_message_wizard.xml', ],

3.4 业务逻辑调用示例

在需要提示的地方调用:

def button_validate(self): if not self.partner_id: message = self.env['my.message.wizard'].create({ 'message': ''' <p>请先选择业务伙伴!</p> <ul> <li>该提示不会中断业务流程</li> <li>表单数据将保持原状</li> </ul> ''' }) return { 'name': '缺失必填项', 'type': 'ir.actions.act_window', 'view_mode': 'form', 'res_model': 'my.message.wizard', 'res_id': message.id, 'target': 'new', 'context': self._context, 'flags': {'mode': 'readonly'} } # 正常业务逻辑...

4. 高级功能扩展

4.1 多按钮交互

改造action_confirm方法:

def action_choice(self, choice): if choice == 'confirm': self.env['res.partner'].search([...]).do_something() return {'type': 'ir.actions.act_window_close'} # 视图添加: <button name="action_choice" string="同意" type="object" args="('confirm',)"/> <button name="action_choice" string="拒绝" type="object" args="('reject',)"/>

4.2 自动关闭定时器

在js文件中添加:

setTimeout(function() { $('.modal').modal('hide'); }, 5000); // 5秒后自动关闭

4.3 响应式布局适配

添加CSS类:

<sheet class="msg-responsive"> <style> .msg-responsive { min-width: 300px; max-width: 80%; margin: 0 auto; } @media (max-width: 768px) { .msg-responsive { max-width: 95%; } } </style> ... </sheet>

5. 常见问题排查

5.1 弹窗不显示

检查步骤:

  1. 确认__manifest__.py已注册XML文件
  2. 检查视图record id是否唯一
  3. 查看浏览器控制台是否有JS错误

5.2 按钮无响应

调试方法:

  1. 在方法开始添加_logger.debug调试输出
  2. 检查是否缺少@api.multi装饰器
  3. 确认按钮type="object"而非type="action"

5.3 样式异常

解决方案:

  1. 检查是否与其他模块CSS冲突
  2. 确保正确加载了Font Awesome
  3. 使用浏览器开发者工具审查元素

6. 性能优化建议

  1. 对频繁调用的提示内容使用缓存:
@tools.ormcache('message_content') def get_message_id(self, message_content): return self.create({'message': message_content}).id
  1. 批量处理时避免N+1查询:
# 错误做法 for record in records: record.show_message(...) # 正确做法 message_ids = self.env['my.message.wizard'].create_batch([...])
  1. 使用web_ajax代替完整弹窗:
odoo.define('module', function (require) { "use strict"; var core = require('web.core'); var Widget = require('web.Widget'); var MyWidget = Widget.extend({ showToast: function(message) { this.do_notify(_t("提示"), message); } }); });

我在实际项目中发现,当需要连续显示多个提示时,采用通知(toast)样式比模态弹窗更合适。特别是在导出入库单这类批量操作场景下,可以显著改善用户体验。

http://www.jsqmd.com/news/1222215/

相关文章:

  • 如何识别真实项目价值:从数据陷阱到决策实践
  • 2026年7月最新爱彼大连普兰店万达广场维修保养服务电话 - 爱彼中国官方服务中心
  • WD-40化学原理与精准操作:从除锈润滑到十大隐藏用法实战手册
  • Android定时任务:Handler与Timer的深度对比与实践
  • 开源软件评估与商业化潜力分析
  • 宝珀中国官方售后服务中心服务电话及详细网点地址实地考察报告多信源验证(2026年7月最新) - 宝珀官方售后服务中心
  • 2026年7月最新福州鼓楼区鼓东街道亨得利官方名表服务中心电话公示 - 亨得利官方博客
  • STM8单片机ADC模块配置与精度优化指南
  • 广州企业财税行业GEO城市合伙人选型推荐哪家靠谱?7大维度帮你锁定源头技术合作方 - 企业新闻快传
  • Android开发框架全解析:从基础到高级实践
  • 芯片免责声明解读:嵌入式开发中的法律风险与设计避坑指南
  • PHP存储型XSS漏洞实战修复:从原理到代码的5分钟安全加固
  • 如何快速解决Reloaded-II游戏路径错误:3步搞定Mod管理器配置
  • MSPM03507驱动MPU6050:嵌入式运动传感器完整开发指南
  • 2026年7月最新天梭济南印象城维修保养服务电话 - 天梭服务中心
  • 2026年7月最新芝柏烟台莱山宝龙广场维修保养服务电话 - 亨得利官方服务中心
  • 2026年7月最新泰格豪雅太原龙湖万达广场维修保养服务电话 - 亨得利钟表维修中心
  • AI高效对话指南:从Prompt设计到工程实践
  • C#邮件发送方案:从基础实现到高级应用
  • 如何用Obsidian Image Toolkit插件彻底改变你的笔记图片管理体验
  • 电子成图大赛4分钟原理图模版:放大器与电源电路高效绘制指南
  • AM62L CBASS防火墙与中断控制:寄存器配置与嵌入式安全实战
  • 运城河东家宴:一个区域性餐饮服务商的「可验证服务架构」实测报告
  • 深入解析OMAP34xx PRCM时钟管理:DPLL与时钟门控实战指南
  • 2026南京购宠避坑全攻略|实体店才是硬道理!明轩双店连锁、CKU认证、本土好养猫狗,售后全程兜底 - 同城大型猫犬舍
  • AM62L DSI寄存器深度解析:从视频流控制到TVG测试与故障排查
  • 武汉三新职业技术学校2026年招生简章 - 武汉中职最新信息发布
  • Android内存泄漏检测与MAT工具实战指南
  • 2026年07月PPPC中空格子板模头制造厂家实力解析 - 甄选服务推荐
  • 2026年7月一物一码防伪溯源系统搭建品牌评价:哪个最好?TOP10推荐 - 品牌帮