分享一个自动刷新看板视图的功能
-
潜水好久了,今天分享一个东东,花了老鼻子劲,最终只用了几行代码就搞定的功能。
背景与需求
一个车间的生产订单看板系统,各个大的工作站要用大屏幕显示本工作站及前后工作站相关工单的状态(每个工作站工单分为等待,在制与已完成),用文字显示如下
前一个工作站 本工作站 下一个工作站
等待 在制 已完成 等待 在制 已完成 等待 在制 已完成
问题是这些电子显示屏上的工单状态会因为在其它操作电脑上进行的工单状态变更而需要自动刷新
解决方案(过程)
1.首先想到了action里的auto_refresh参数,经实验不起作用,再经进一步google,以及代码检查(现有web里的代码只有定义这个参数,没有使用这个参数的地方),发现该选项根本就是用于之前GUI界面,并且只针对form视图
2.后来想到可以使用浏览器或插件实现自动刷新,试了firefox的reload every,经实验,其它网页可自动刷新,odoo的界面,特别是看板视图--不行
3.最后想到是否可以在界面上做一个定时的长轮询,不过想想也不靠谱,因为定时去服务器检查有没有更新的内容,工作站多了,时间间隔短的话,会大量消耗服务器的资源。效果不理想
最终解决方案
后来发现Odoo本身已实现了实时消息机制(里面有一个bus模块),另外在年度大会上有一个anybox的公司也基于socketio整了一个实时推送的模块。找到了感觉,最后的方案主要思路应该就是
1. 在服务器端(Python),在工单变更(新增,变更或删除)时,产生一个资料变更通知(事件),并利用现成的bus,发送给指定(直接取表名)的频道(chanel)
2. 在网页端,监听该频道的事件,判断当前视图是否为kanban,并取得当前的kanban对象,调用其do_reload方法,实现刷新(因为从来没写过javascript程序,如何取得当前kanban视图对象成了最大的拦路虎,好在有firebug,可以在启用调试模式并打开当前看板视图的情况下,在firebug里通过研究整个DOM对象树,最后总算搞成了!)
实际的代码(有点简陋,但经初步测试可以达到要求,贴出来一方面是分享,另一方面还希望得到高手的指点)
在此之前安装了一个anybox公司在bitbucket代码管理网站上的web_notification模块(主要是增加官方的bus模块).
后台Python
@api.model
def create(self,vals, context=None):
res = super(kanban_OrderTracking, self).create(vals)
bus = self.env['bus.bus']
message = {
'subject': 'ordertracking',
'body': 'ordertracking created',
'mode': 'notify',
}
bus.sendone('ordertracking', message)
return res
前端JS
(function() {
openerp.web.WebClient.include({
declare_bus_channel: function() {
this._super();
var self = this,
channel = 'ordertracking';
this.bus_on(channel, function(message) {
if (this.action_manager.inner_widget.active_view == "kanban") {
this.action_manager.inner_widget.views["kanban"].controller.do_reload();
}
});
this.add_bus_channel(channel);
},
});
})();
另外,该分享也在官方论坛里有,https://www.odoo.com/forum/help-1/question/how-to-auto-refresh-kanban-view-67582