如何在Odoo POS界面弹窗显示客户列表并恢复后台产品界面?
解决Odoo POS弹窗显示客户列表时产品屏幕被隐藏的问题
我来帮你搞定这个问题~ 你之前尝试的直接移除oe_hidden或者调用show()方法无效,核心原因是Odoo POS的show_screen方法内部自带了屏幕切换的强制隐藏逻辑——每次调用它显示新屏幕时,框架会自动给当前活跃屏幕加上oe_hidden类,同时移除目标屏幕的该类,你的手动操作会被这个内置逻辑覆盖掉。
下面给你两个可行的解决方案,按需选择:
方案1:改用弹窗组件(推荐)
不要把客户列表做成独立screen,而是自定义一个弹窗组件,这样完全不会影响产品屏幕的显示状态:
- 先定义客户列表弹窗的Widget:
odoo.define('your_module.customer_popup', function(require) { "use strict"; var core = require('web.core'); var PopupWidget = require('point_of_sale.popup'); var gui = require('point_of_sale.gui'); var _t = core._t; // 自定义弹窗组件 var CustomerPopup = PopupWidget.extend({ template: 'CustomerPopupTemplate', // 需自己创建对应XML模板 init: function(parent, options) { this._super(parent, options); this.customers = options.customers; // 传入客户数据 }, renderElement: function() { this._super(); // 绑定客户选择事件 this.$('.customer-item').on('click', function() { var customerId = $(this).data('id'); // 将选中客户绑定到当前订单 const order = this.pos.get_order(); order.set_client(this.pos.db.get_partner_by_id(customerId)); this.close(); // 关闭弹窗 }.bind(this)); }, }); // 注册弹窗 gui.define_popup({name:'customer_popup', widget: CustomerPopup}); return CustomerPopup; });
- 在XML里添加弹窗模板(示例):
<t t-name="CustomerPopupTemplate"> <div class="popup"> <div class="title">选择客户</div> <div class="body"> <div class="customer-list"> <t t-foreach="widget.customers" t-as="customer"> <div class="customer-item" t-att-data-id="customer.id"> <span t-esc="customer.name"/> </div> </t> </div> </div> <div class="footer"> <button class="button cancel" t-on-click="widget.close()">取消</button> </div> </div> </t>
- 修改ActionpadWidget的点击事件:
// 替换原来的show_screen逻辑 this.gui.show_popup('customer_popup', { title: _t('选择客户'), customers: this.pos.db.get_partners_sorted(), // 取排序后的客户列表 });
方案2:修改屏幕切换逻辑(保留screen模式)
如果你坚持要用clientlist-screen作为弹窗,需要重写Odoo的屏幕切换方法,让它支持不隐藏当前屏幕:
- 重写Gui的show_screen方法:
odoo.define('your_module.custom_gui', function(require) { "use strict"; var gui = require('point_of_sale.gui'); // 保存原方法 const originalShowScreen = gui.Gui.prototype.show_screen; // 扩展方法,添加hide_current参数 gui.Gui.prototype.show_screen = function(screenName, options) { options = options || {}; if (!options.hide_current) { // 不隐藏当前屏幕,直接显示目标屏幕 const targetScreen = this.screens[screenName]; if (targetScreen) { targetScreen.$el.removeClass('oe_hidden'); targetScreen.show(); if (options.params) { targetScreen.render_element(options.params); } } return; } // 原逻辑:隐藏当前屏幕,显示目标屏幕 originalShowScreen.call(this, screenName, options); }; });
- 给
clientlist-screen添加弹窗样式(确保它悬浮在产品屏幕上方):
.clientlist-screen { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 80%; max-width: 650px; height: 75%; background-color: white; z-index: 9999; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2); overflow-y: auto; }
- 在ActionpadWidget的点击事件里调用:
// 传入hide_current参数,阻止隐藏产品屏幕 self.gui.show_screen('clientlist', {hide_current: false});
内容的提问来源于stack exchange,提问作者Gopakumar N G




