翼度科技»论坛 编程开发 python 查看内容

odoo wizard界面显示带复选框列表及勾选数据获取

3

主题

3

帖子

9

积分

新手上路

Rank: 1

积分
9
实践环境

Odoo 14.0-20221212 (Community Edition)
需求描述

如下图(非实际项目界面截图,仅用于介绍本文主题),打开记录详情页(form视图),点击某个按钮(图中的"选取ffers"按钮),弹出一个向导(wizard)界面,并将详情页中内联tree视图("Offers" Tab页)的列表记录展示到向导界面,且要支持复选框,用于选取目标记录,然执行目标操作。


详情页所属模型EstateProperty
  1. class EstateProperty(models.Model):
  2.     _name = 'estate.property'
  3.     _description = 'estate property table'
  4.     # ... 略
  5.     offer_ids = fields.One2many("estate.property.offer", "property_id", string="PropertyOffer")
  6.     def action_do_something(self, args):
  7.         # do something
  8.         print(args)
复制代码
OffersTab页Tree列表所属模型EstatePropertyOffer
  1. class EstatePropertyOffer(models.Model):
  2.     _name = 'estate.property.offer'
  3.     _description = 'estate property offer'
  4.    
  5.     # ... 略
  6.     property_id = fields.Many2one('estate.property', required=True)
复制代码
代码实现

代码组织结构

为了更好的介绍本文主题,下文给出了项目文件大致组织结构(为了让大家看得更清楚,仅保留关键文件)
  1. odoo14         
  2. ├─custom
  3. │  ├─estate
  4. │  │  │  __init__.py
  5. │  │  │  __manifest__.py
  6. │  │  │         
  7. │  │  ├─models
  8. │  │  │  estate_property.py
  9. │  │  │  estate_property_offer.py
  10. │  │  │  __init__.py
  11. │  │  │         
  12. │  │  ├─security
  13. │  │  │      ir.model.access.csv
  14. │  │  │      
  15. │  │  ├─static
  16. │  │  │  │      
  17. │  │  │  └─src
  18. │  │  │      │         
  19. │  │  │      └─js
  20. │  │  │              list_renderer.js
  21. │  │  │              
  22. │  │  ├─views
  23. │  │  │      estate_property_offer_views.xml
  24. │  │  │      estate_property_views.xml
  25. │  │  │      webclient_templates.xml     
  26. │  │  │         
  27. │  │  └─wizards
  28. │  │        demo_wizard.py
  29. │  │        demo_wizard_views.xml
  30. │  │        __init__.py
  31. │  │         
  32. ├─odoo
  33. │  │  api.py
  34. │  │  exceptions.py
  35. │  │  ...略
  36. │  │  __init__.py
  37. │  │  
  38. │  ├─addons
  39. │  │  │  __init__.py
  40. │  ...略
  41. ...略      
复制代码
wizard简介

wizard(向导)通过动态表单描述与用户(或对话框)的交互会话。向导只是一个继承TransientModel而非model的模型。TransientModel类扩展Model并重用其所有现有机制,具有以下特殊性:

  • wizard记录不是永久的;它们在一定时间后自动从数据库中删除。这就是为什么它们被称为瞬态(transient)。
  • wizard可以通过关系字段(many2one或many2many)引用常规记录或wizard记录,但常规记录不能通过many2one字段引用wizard记录
详细代码

注意:为了更清楚的表达本文主题,代码文件中部分代码已略去
wizard实现

odoo14\custom\estate\wizards\demo_wizard.py

实现版本1
  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. import logging
  4. from odoo import models,fields,api
  5. from odoo.exceptions import UserError
  6. _logger = logging.getLogger(__name__)
  7. class DemoWizard(models.TransientModel):
  8.     _name = 'demo.wizard'
  9.     _description = 'demo wizard'
  10.     property_id = fields.Many2one('estate.property', string='property')
  11.     offer_ids = fields.One2many(related='property_id.offer_ids')
  12.     def action_confirm(self):
  13.         '''选中记录后,点击确认按钮,执行的操作'''
  14.         #### 根据需要对获取的数据做相应处理
  15.         # ... 获取数据,代码略(假设获取的数据存放在 data 变量中)
  16.      
  17.         record_ids = []
  18.         for id, value_dict in data.items():
  19.             record_ids.append(value_dict.get('data', {}).get('id'))
  20.         if not record_ids:
  21.             raise UserError('请选择记录')
  22.         self.property_id.action_do_something(record_ids)               
  23.         return True      
  24.    
  25.     @api.model
  26.     def action_select_records_via_checkbox(self, args):
  27.         '''通过wizard窗口界面复选框选取记录时触发的操作
  28.         @params: args 为字典
  29.         '''
  30.         # ...存储收到的数据(假设仅存储data部分的数据),代码略
  31.         
  32.         return True # 注意,执行成功则需要配合前端实现,返回True
  33.     @api.model
  34.     def default_get(self, fields_list):
  35.         '''获取wizard 窗口界面默认值,包括记录列表 #因为使用了@api.model修饰符,self为空记录集,所以不能通过self.fieldName = value 的方式赋值'''
  36.         res = super(DemoWizard, self).default_get(fields_list)
  37.         record_ids = self.env.context.get('active_ids') # 获取当前记录ID列表(当前记录详情页所属记录ID列表) # self.env.context.get('active_id') # 获取当前记录ID
  38.         property = self.env['estate.property'].browse(record_ids)
  39.         res['property_id'] = property.id
  40.         offer_ids = property.offer_ids.mapped('id')
  41.         res['offer_ids'] = [(6, 0, offer_ids)]
  42.         return res
复制代码
说明:

  • 注意,不能使用类属性来接收数据,因为类属性供所有对象共享,会相互影响,数据错乱。
  • action_select_records_via_checkbox函数接收的args参数,其类型为字典,形如以下,其中f412cde5-1e5b-408c-8fc0-1841b9f9e4de为UUID,供web端使用,用于区分不同页面操作的数据,'estate.property.offer_3'为供web端使用的记录ID,'data'键值代表记录的数据,其id键值代表记录在数据库中的主键id,context键值代表记录的上下文。arg数据格式为:
    1. {'uuid':{'recordID1':{'data': {}, 'context':{}}, 'recordID2': {'data': {}, 'context':{}}}}
    复制代码
    1. {'f412cde5-1e5b-408c-8fc0-1841b9f9e4de': {'estate.property.offer_3': {'data': {'price': 30000, 'partner_id': {'context': {}, 'count': 0, 'data': {'display_name': 'Azure Interior, Brandon Freeman', 'id': 26}, 'domain': [], 'fields': {'display_name': {'type': 'char'}, 'id': {'type': 'integer'}}, 'id': 'res.partner_4', 'limit': 1, 'model': 'res.partner', 'offset': -1, 'ref': 26, 'res_ids': [], 'specialData': {}, 'type': 'record', 'res_id': 26}, 'validity': 7, 'date_deadline': '2022-12-30', 'status': 'Accepted', 'id': 21}, 'context': {'lang': 'en_US', 'tz': 'Europe/Brussels', 'uid': 2, 'allowed_company_ids': [1], 'params': {'action': 85, 'cids': 1, 'id': 41, 'menu_id': 70, 'model': 'estate.property', 'view_type': 'form'}, 'active_model': 'estate.property', 'active_id': 41, 'active_ids': [41], 'property_pk_id': 41}}}}
    复制代码
实现版本2
  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. import uuid
  4. import logging
  5. from odoo import models, fields, api
  6. from odoo.exceptions import UserError, ValidationError, MissingError
  7. _logger = logging.getLogger(__name__)
  8. class DemoWizard(models.TransientModel):
  9.     _name = 'demo.wizard'
  10.     _description = 'demo wizard'
  11.     property_id = fields.Many2one('estate.property', string='property')
  12.     property_pk_id = fields.Integer(related='property_id.id') # 用于action_confirm中获取property
  13.     offer_ids = fields.One2many(related='property_id.offer_ids')
  14.     @api.model
  15.     def action_confirm(self, data:dict):
  16.         '''选中记录后,点击确认按钮,执行的操作'''
  17.         #### 根据需要对获取的数据做相应处理
  18.         record_ids = []
  19.         for id, value_dict in data.items():
  20.             record_ids.append(value_dict.get('data', {}).get('id'))
  21.         if not record_ids:
  22.             raise UserError('请选择记录')
  23.             
  24.         property_pk_id = None
  25.         for id, value_dict in data.items():
  26.             property_pk_id = value_dict.get('context', {}).get('property_pk_id')
  27.             break
  28.         if not property_pk_id:
  29.             raise ValidationError('do something fail')
  30.             
  31.         property = self.env['estate.property'].browse([property_pk_id]) # 注意,,所以,这里不能再通过self.property_id获取了
  32.         if property.exists():
  33.             property.action_do_something(record_ids)
  34.         else:
  35.             raise MissingError('do something fail:当前property记录(id=%s)不存在' % property_pk_id)
  36.         return True
  37.    
  38.     @api.model
  39.     def default_get(self, fields_list):
  40.         '''获取wizard 窗口界面默认值,包括记录列表'''
  41.         res = super(DemoWizard, self).default_get(fields_list)
  42.         record_ids = self.env.context.get('active_ids')
  43.         
  44.         property = self.env['estate.property'].browse(record_ids)
  45.         res['property_id'] = property.id
  46.         res['property_pk_id'] = property.id
  47.         offer_ids = property.offer_ids.mapped('id')
  48.         res['offer_ids'] = [(6, 0, offer_ids)]
  49.         return res
复制代码
odoo14\custom\estate\wizards\__init__.py
  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. from . import demo_wizard
复制代码
odoo14\custom\estate\__init__.py
  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. from . import models
  4. from . import wizards
复制代码
odoo14\custom\estate\wizards\demo_wizard_views.xml

实现版本1

对应demo_wizard.py实现版本1
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <odoo>
  3.     <data>
  4.         <record id="demo_wizard_view_form" model="ir.ui.view">
  5.             <field name="name">demo.wizard.form</field>
  6.             <field name="model">demo.wizard</field>
  7.             <field name="arch" type="xml">
  8.                 <form>
  9.                     <field name="offer_ids">
  10.                         <tree hasCheckBoxes="true" modelName="demo.wizard" modelMethod="action_select_records_via_checkbox" jsMethodOnModelMethodDone="enableActionConfirmButton()" jsMethodOnToggleCheckbox="disableActionConfirmButton()">
  11.                             <field name="price" string="Price"/>
  12.                             <field name="partner_id" string="partner ID"/>
  13.                             <field name="validity" string="Validity(days)"/>
  14.                             <field name="date_deadline" string="Deadline"/>
  15.                             <button name="action_accept_offer" string=""  type="object" icon="fa-check" attrs="{'invisible': [('status', 'in', ['Accepted','Refused'])]}"/>
  16.                             <button name="action_refuse_offer" string=""  type="object" icon="fa-times" attrs="{'invisible': [('status', 'in', ['Accepted','Refused'])]}"/>
  17.                             <field name="status" string="Status"/>
  18.                         </tree>
  19.                     </field>
  20.                     <footer>
  21.                         <button name="action_confirm" type="object" string="确认(do something you want)" />
  22.                         <button string="取消"  special="cancel"/>
  23.                     </footer>
  24.                 </form>
  25.             </field>
  26.         </record>
  27.         
  28.         <record id="action_demo_wizard" model="ir.actions.act_window">
  29.             <field name="name">选取offers</field>
  30.             <field name="res_model">demo.wizard</field>
  31.             <field name="type">ir.actions.act_window</field>
  32.             <field name="view_mode">form</field>
  33.             <field name="target">new</field>            
  34.         </record>
  35.     </data>
  36. </odoo>
复制代码
说明:
  1. [/code]
  2. [list]
  3. [*]hasCheckBoxes  设置"true",则显示复选框。以下属性皆在hasCheckBoxes  为"true"的情况下起作用。
  4. [*]modelName 点击列表复选框时,需要访问的模型名称,需要配合modelMethod方法使用,缺一不可。可选
  5. [*]modelMethod 点击列表复选框时,需要调用的模型方法,通过该方法收集列表勾选记录的数据。可选。
  6. [*]jsMethodOnModelMethodDone 定义modelMethod方法执行完成后,需要调用的javascript方法([b]注意,包括参数,如果没有参数则写成(),形如 jsMethod()[/b])。可选。
  7. [*]jsMethodOnToggleCheckbox 定义点击列表复选框时需要调用的javascript方法,比modelMethod优先执行([b]注意,包括参数,如果没有参数则写成(),形如 jsMethod()[/b])。可选。
  8. [/list]以上参数同下文saveSelectionsToSessionStorage 参数可同时共存
  9. 如果需要将action绑定到指定模型指定视图的Action,可以在ir.actions.act_window定义中添加binding_model_id和binding_view_types字段,如下:
  10. [code]        <record id="action_demo_wizard" model="ir.actions.act_window">
  11.             <field name="name">选取offers</field>
  12.             <field name="res_model">demo.wizard</field>
  13.             <field name="type">ir.actions.act_window</field>
  14.             <field name="view_mode">form</field>
  15.             <field name="target">new</field>            
  16.             
  17.             <field name="binding_model_id" ref="estate.model_estate_property"/>
  18.             <field name="binding_view_types">form</field>
  19.         </record>
复制代码
效果如下

参考连接:https://www.odoo.com/documentation/14.0/zh_CN/developer/reference/addons/actions.html
实现版本2

对应demo_wizard.py实现版本2
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <odoo>
  3.     <data>
  4.         <record id="demo_wizard_view_form" model="ir.ui.view">
  5.             <field name="name">demo.wizard.form</field>
  6.             <field name="model">demo.wizard</field>
  7.             <field name="arch" type="xml">
  8.                 <form>
  9.                     <field name="property_pk_id" invisible="1"/>
  10.                     <field name="offer_ids" context="{'property_pk_id': property_pk_id}">
  11.                         <tree string="List" hasCheckBoxes="true" saveSelectionsToSessionStorage="true">
  12.                             <field name="price" string="Price"/>
  13.                             <field name="partner_id" string="partner ID"/>
  14.                             <field name="validity" string="Validity(days)"/>
  15.                             <field name="date_deadline" string="Deadline"/>
  16.                             <button name="action_accept_offer" string=""  type="object" icon="fa-check" attrs="{'invisible': [('status', 'in', ['Accepted','Refused'])]}"/>
  17.                             <button name="action_refuse_offer" string=""  type="object" icon="fa-times" attrs="{'invisible': [('status', 'in', ['Accepted','Refused'])]}"/>
  18.                             <field name="status" string="Status"/>
  19.                         </tree>
  20.                     </field>
  21.                     <footer>
  22.                         <button name="action_confirm" onclick="do_confirm_action('demo.wizard','action_confirm')"  string="确认(do something you want)" />
  23.                         <button string="取消"  special="cancel"/>
  24.                     </footer>
  25.                 </form>
  26.             </field>
  27.         </record>
  28.         
  29.         <record id="action_demo_wizard" model="ir.actions.act_window">
  30.             <field name="name">选取offers</field>
  31.             <field name="res_model">demo.wizard</field>
  32.             <field name="type">ir.actions.act_window</field>
  33.             <field name="view_mode">form</field>
  34.             <field name="target">new</field>            
  35.         </record>
  36.     </data>
  37. </odoo>
复制代码
说明:

  • saveSelectionsToSessionStorage 为"true"则表示点击复选框时,将当前选取的记录存到浏览器sessionStorage中,可选
odoo14\custom\estate\security\ir.model.access.csv
  1. id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
  2. # ...略
  3. access_demo_wizard_model,access_demo_wizard_model,model_demo_wizard,base.group_user,1,1,1,1
复制代码
注意:wizard模型也是需要添加模型访问权限配置的
复选框及勾选数据获取实现

大致思路通过继承web.ListRenderer实现自定义ListRenderer,进而实现复选框展示及勾选数据获取。
odoo14\custom\estate\static\src\js\list_renderer.js

注意:之所以将uuid函数定义在list_renderer.js中,是为了避免因为js顺序加载问题,可能导致加载list_renderer.js时找不到uuid函数定义问题。
  1. function uuid() {
  2.         var s = [];
  3.         var hexDigits = "0123456789abcdef";
  4.         for (var i = 0; i < 36; i++) {
  5.                 s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
  6.         }
  7.         s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
  8.         s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
  9.         s[8] = s[13] = s[18] = s[23] = "-";
  10.         var uuid = s.join("");
  11.         return uuid;
  12. }
  13. odoo.define('estate.ListRenderer', function (require) {
  14.     "use strict";
  15.         var ListRenderer = require('web.ListRenderer');
  16.         ListRenderer = ListRenderer.extend({
  17.             init: function (parent, state, params) {
  18.                     this._super.apply(this, arguments);
  19.                     this.hasCheckBoxes = false;
  20.                         if ('hasCheckBoxes' in params.arch.attrs && params.arch.attrs['hasCheckBoxes']) {
  21.                 this.objectID = uuid();
  22.                 $(this).attr('id', this.objectID);
  23.                             this.hasCheckBoxes = true;
  24.                             this.hasSelectors = true;
  25.                             this.records = {}; // 存放当前界面记录
  26.                             this.recordsSelected = {}; // 存放选取的记录
  27.                             this.modelName = undefined; // 定义点击列表复选框时需要访问的模型
  28.                             this.modelMethod = undefined; // 定义点击列表复选框时需要调用的模型方法
  29.                             this.jsMethodOnModelMethodDone = undefined; // 定义modelMethod方法执行完成后,需要调用的javascript方法
  30.                             this.jsMethodOnToggleCheckbox = undefined; // 定义点击列表复选框时需要调用的javascript方法,比modelMethod优先执行
  31.                             if ('modelName' in params.arch.attrs && params.arch.attrs['modelName']) {
  32.                                 this.modelName = params.arch.attrs['modelName'];
  33.                             }
  34.                             if ('modelMethod' in params.arch.attrs && params.arch.attrs['modelMethod']) {
  35.                                 this.modelMethod = params.arch.attrs['modelMethod'];
  36.                             }
  37.                             if ('jsMethodOnModelMethodDone' in params.arch.attrs && params.arch.attrs['jsMethodOnModelMethodDone']){
  38.                                 this.jsMethodOnModelMethodDone = params.arch.attrs['jsMethodOnModelMethodDone'];
  39.                             }
  40.                             if ('jsMethodOnToggleCheckbox' in params.arch.attrs && params.arch.attrs['jsMethodOnToggleCheckbox']) {
  41.                                 this.jsMethodOnToggleCheckbox = params.arch.attrs['jsMethodOnToggleCheckbox'];
  42.                             }
  43.                
  44.                 if ('saveSelectionsToSessionStorage' in params.arch.attrs && params.arch.attrs['saveSelectionsToSessionStorage']) {
  45.                                 this.saveSelectionsToSessionStorage = params.arch.attrs['saveSelectionsToSessionStorage'];
  46.                             }
  47.             }
  48.                 },
  49. //                _onToggleSelection: function (ev) {
  50.             // 点击列表表头的全选/取消全选复选框时会调用该函数
  51. //                    this._super.apply(this, arguments);
  52. //        },
  53.         _onToggleCheckbox: function (ev) {
  54.             if (this.hasCheckBoxes) {
  55.                 var classOfEvTarget = $(ev.target).attr('class');
  56.                 /* cstom-control-input 刚好点中复选框input,
  57.                 custom-control custom-checkbox 刚好点中复选框input的父元素div
  58.                 o_list_record_selector 点击到复选框外上述div的父元素*/               
  59.                 if (['custom-control custom-checkbox', 'custom-control-input', 'o_list_record_selector'].includes(classOfEvTarget)){
  60.                     if (this.jsMethodOnToggleCheckbox) {
  61.                         eval(this.jsMethodOnToggleCheckbox)
  62.                     }
  63.                     var id = $(ev.currentTarget).closest('tr').data('id'); // 'custom-control-input' == classOfEvTarget
  64.                     var checked = !this.$(ev.currentTarget).find('input').prop('checked') // 获取复选框是否框选 'custom-control-input' != classOfEvTarget
  65.                     if ('custom-control-input' ==  classOfEvTarget) {
  66.                         checked = this.$(ev.currentTarget).find('input').prop('checked')
  67.                     }
  68.                     
  69.                     if (id == undefined) {
  70.                         if (checked == true) { // 全选
  71.                             this.recordsSelected = JSON.parse(JSON.stringify(this.records));
  72.                         } else { // 取消全选
  73.                             this.recordsSelected = {};
  74.                         }
  75.                     } else {
  76.                         if (checked == true) { // 勾选单条记录
  77.                             this.recordsSelected[id] = this.records[id];
  78.                         } else { // 取消勾选单条记录
  79.                             delete this.recordsSelected[id];
  80.                         }
  81.                     }
  82.                     if (this.saveSelectionsToSessionStorage) {
  83.                         window.sessionStorage[this.objectID] = JSON.stringify(this.recordsSelected);
  84.                     }
  85.                     
  86.                     // 通过rpc请求模型方法,用于传输界面勾选的记录数据
  87.                     if (this.modelName && this.modelMethod) {
  88.                         self = this;
  89.                         this._rpc({
  90.                                 model: this.modelName,
  91.                                 method: this.modelMethod,
  92.                                 args: [this.recordsSelected],
  93.                             }).then(function (res) {
  94.                                 if (self.jsMethodOnModelMethodDone) {
  95.                                     eval(self.jsMethodOnModelMethodDone);
  96.                                 }
  97.                             });
  98.                     }
  99.                 }
  100.             }
  101.             this._super.apply(this, arguments);
  102.         },
  103.         _renderRow: function (record) {
  104.             // 打开列表页时会渲染行,此时存储渲染的记录
  105.             if (this.hasCheckBoxes) {
  106.                 this.records[record.id] = {'data': record.data, 'context': record.context};
  107.             }
  108.             return this._super.apply(this, arguments);
  109.         }
  110.         });
  111. odoo.__DEBUG__['services']['web.ListRenderer'] = ListRenderer; //覆盖原有的ListRender服务
  112. });
复制代码
实践过程中,有尝试过以下实现方案,视图通过指定相同服务ID web.ListRenderer来覆盖框架自带的web.ListRenderer定义,这种实现方案只能在非Debug模式下正常工作,且会导致无法开启Debug模式,odoo.define实现中会对服务是否重复定义做判断,如果重复定义则会抛出JavaScript异常。
  1. odoo.define('web.ListRenderer', function (require) {
  2.     "use strict";
  3.     //...略,同上述代码
  4.     // odoo.__DEBUG__['services']['web.ListRenderer'] = ListRenderer;
  5.     return ListRenderer;
  6. });
复制代码
笔者后面发现,可以使用include替代extend方法修改现有的web.ListRenderer,如下
  1. odoo.define('estate.ListRenderer', function (require) {
  2.     "use strict";
  3.         var ListRenderer = require('web.ListRenderer');
  4.         ListRenderer = ListRenderer.include({//...略,同上述代码});
  5.    
  6.     // odoo.__DEBUG__['services']['web.ListRenderer'] = ListRenderer;  //不需要添加这行代码了
  7. });
复制代码
odoo14\custom\estate\static\src\js\demo_wizard_views.js

实现版本1

供demo_wizard_views.xml实现版本1使用
  1. function disableActionConfirmButton(){ // 禁用按钮
  2.     $("button[name='action_confirm']").attr("disabled", true);
  3. }
  4. function enableActionConfirmButton(){ // 启用按钮
  5.     $("button[name='action_confirm']").attr("disabled", false);
  6. }
复制代码
这里的设计是,执行复选框操作时,先禁用按钮,不允许执行确认操作,因为执行复选框触发的请求可能没那么快执行完成,前端数据可能没完全传递给后端,此时去执行操作,可能会导致预期之外的结果。所以,等请求完成再启用按钮。
实现版本2

供demo_wizard_views.xml实现版本2使用
  1. function do_confirm_action(modelName, modelMethod, context){
  2.     $("button[name='action_confirm']").attr("disabled", true); // 点击按钮后,禁用按钮状态,比较重复点击导致重复发送请求   
  3.     var wizard_dialog = $(event.currentTarget.offsetParent.parentElement.parentElement);
  4.     var dataUUID = $(event.currentTarget.parentElement.parentElement.parentElement.parentElement).find('div.o_list_view').prop('id');
  5.     var rpc = odoo.__DEBUG__.services['web.rpc'];
  6.     rpc.query({
  7.         model: modelName,
  8.         method: modelMethod,
  9.         args: [JSON.parse(window.sessionStorage.getItem(dataUUID) || '{}')]
  10.     }).then(function (res)         if (res == true) {
  11.             wizard_dialog.css('display', 'none'); // 隐藏对话框
  12.             window.sessionStorage.removeItem(dataUUID);
  13.         } else {
  14.             $("button[name='action_confirm']").attr("disabled", false);
  15.         }
  16.     }).catch(function (err) {
  17.         $("button[name='action_confirm']").attr("disabled", false);
  18.     });
  19. }
复制代码
odoo14\odoo\addons\base\rng\tree_view.rng

可选操作。如果希望hasCheckBoxes,modelName,modelMethod等也可作用于非内联tree视图,则需要编辑该文件,添加hasCheckBoxes,modelName,modelMethod等属性,否则,更新应用的时候会报错。
[code]

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具