Odoo 12:sale.order模型保存按钮触发非阻塞弹窗实现咨询
嘿,卡3小时确实够折磨人的,我来帮你把这个问题捋清楚,顺便给你靠谱的解决方案!
首先直接回答你的疑问:直接绑定o_form_button_edit的点击事件是可行,但绝对不推荐——这个按钮是Odoo所有表单视图通用的,你全局绑定事件的话,所有模型的编辑按钮都会受影响,完全不符合你只想针对sale.order的需求。
最优方案:精准继承FormController,仅针对销售订单扩展
Odoo的前端框架支持对特定模型的控制器进行继承扩展,这样只会影响sale.order的表单视图,不会波及其他模型。核心思路是:在保存动作完全完成(数据库已更新)后,校验条件并触发弹窗,弹窗的两个按钮分别执行对应逻辑。
步骤1:编写前端JS代码(核心逻辑)
创建一个自定义JS模块,继承FormController并重写保存相关逻辑:
odoo.define('sale_custom_popup.form_controller', function (require) { "use strict"; const FormController = require('web.FormController'); const core = require('web.core'); const _t = core._t; // 继承FormController,仅针对sale.order做定制 FormController.include({ async _save(ev, recordId, options) { // 先执行Odoo原生的保存逻辑,确保数据已经写入数据库 const saveResult = await this._super(...arguments); // 只对销售订单模型执行后续逻辑 if (this.modelName === 'sale.order') { // 重新加载最新的记录(避免保存后后端自动更新字段导致数据不一致) const latestRecord = await this.model.load({ res_id: this.handle.get('res_id'), model: this.modelName, }); // 替换成你的条件:比如某字段等于特定值,这里用state = 'done'举例 const targetFieldValue = latestRecord.data.state; if (targetFieldValue === 'done') { // 弹出带Accept/Discard的弹窗(保存流程已完成,弹窗不阻塞之前的操作) this.do_confirm_dialog({ title: _t('变更确认'), message: _t('您确认要保留此次变更吗?'), confirm_text: _t('Accept'), cancel_text: _t('Discard'), confirm_callback: () => { // Accept逻辑:啥也不用做,因为保存已经完成了 }, cancel_callback: () => { // Discard逻辑:切换回编辑模式,让用户可以重新修改 this.trigger_up('switch_view', { view_type: 'form', mode: 'edit', res_id: latestRecord.res_id, }); } }); } } return saveResult; } }); return FormController; });
步骤2:注册JS模块到你的自定义模块
在模块的__manifest__.py里添加资源引用,确保JS能被加载:
{ 'name': 'Sale Order Custom Popup', 'version': '1.0', 'depends': ['sale', 'web'], 'data': [], 'assets': { 'web.assets_backend': [ 'your_module_name/static/src/js/form_controller.js', ], }, 'installable': True, 'auto_install': False, }
方案优势说明
- 精准影响范围:只对
sale.order模型生效,其他模型的表单视图完全不受影响 - 逻辑安全:先执行原生保存动作,确保数据库更新后再校验条件,避免数据不一致
- 符合Odoo规范:用官方推荐的控制器继承方式,不会破坏原有框架逻辑
- 完全匹配需求:弹窗在保存后触发,Accept无操作、Discard回到编辑模式的逻辑完全覆盖你的要求
注意事项
- 如果你的条件字段是后端计算字段(比如自动生成的状态),一定要用
model.load重新读取记录,确保拿到的是数据库最新值 - 弹窗的文本、条件判断逻辑可以根据你的实际需求修改
- 测试时记得验证其他模型的表单视图,确保没有被意外影响
内容的提问来源于stack exchange,提问作者m0r7y
相关产品推荐
相关产品推荐

