You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,
}

方案优势说明

  1. 精准影响范围:只对sale.order模型生效,其他模型的表单视图完全不受影响
  2. 逻辑安全:先执行原生保存动作,确保数据库更新后再校验条件,避免数据不一致
  3. 符合Odoo规范:用官方推荐的控制器继承方式,不会破坏原有框架逻辑
  4. 完全匹配需求:弹窗在保存后触发,Accept无操作、Discard回到编辑模式的逻辑完全覆盖你的要求

注意事项

  • 如果你的条件字段是后端计算字段(比如自动生成的状态),一定要用model.load重新读取记录,确保拿到的是数据库最新值
  • 弹窗的文本、条件判断逻辑可以根据你的实际需求修改
  • 测试时记得验证其他模型的表单视图,确保没有被意外影响

内容的提问来源于stack exchange,提问作者m0r7y

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:58:53