当前位置: 首页 > news >正文

【odoo17】odoo前端视图的结构分析及新增视图类型的实现

odoo前端视图加载的架构分析

1.视图入口

用F12定位到比如tree视图的地方,可以看到odoo的最顶层定义了一个view组件,然后根据视图类型到了各自的视图结构中。
在这里插入图片描述
可以看到,在view视图中,odoo已经通过load方法加载了不少参数,主要是action中的参数。
在这里插入图片描述

2.视图结构

对比各种视图的代码目录,结构都是相同的。以tree视图为例,进入list代码目录中,看到代码目录。
在这里插入图片描述
这里介绍主要的组成部分,每个视图主要由ArchParser、Controller、Renderer、Model组成。

2.1.ArchParser

ArchParser是用于解析view的xml代码,在list视图中,需要解析的是tree视图,解析结果:
在这里插入图片描述

2.2.Controller

Controller中的分为两部分,上半部分主要由操作按钮、搜索框等组成,下半部分通过props.Renderer在Renderer中实现。
在这里插入图片描述

2.3.Renderer

Renderer在list视图中实现controller中的下半部分,在controller中通过props.Renderer在Renderer调用。
在这里插入图片描述

2.4.Model

Model用于从数据库读取数据,并且会根据视图需要进行相应的处理,odoo对常用数据通过@web/model/relational_model/relational_model中进行处理,如有特殊需求,可以自行构建Model。
model的创建是在Controller的setup中完成,在controller的template中调用。
在这里插入图片描述
在这里插入图片描述

3.视图实现

最终view中通过调用t-component="Controller"来完成对controller中的调用。
在这里插入图片描述

4.新增视图report

4.1.需求描述

在上一章《在报表上方增加搜索视图》中,实现了报表上方增加搜索视图,这种方式由于没有controller,导致searchModel等一系列的组件无法获取,实现麻烦、可扩展性差。因此通过新增视图类型report来实现。

4.2.新增视图类型report

class ActWindowView(models.Model):
    _inherit = 'ir.actions.act_window.view'

    view_mode = fields.Selection(selection_add=[('report', "Report")], ondelete={'report': 'cascade'})


class View(models.Model):
    _inherit = 'ir.ui.view'

    type = fields.Selection(selection_add=[('report', "Report")])

在report中指定props.Renderer

<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <data>
        <record id="view_asset_liabilities_report_report" model="ir.ui.view">
            <field name="name">Asset Liabilities Report</field>
            <field name="model">asset.liabilities.report</field>
            <field name="arch" type="xml">
                <report string="资产负债表" template_id="jcerp_account_ledger.AssetLiabilitiesReport"/>
            </field>
        </record>

        <record id="action_asset_liabilities_report_test" model="ir.actions.act_window">
            <field name="name">资产负债表</field>
            <field name="res_model">asset.liabilities.report</field>
            <field name="view_mode">report</field>
            <field name="view_id" ref="view_asset_liabilities_report_report"/>
        </record>
    </data>
</odoo>

4.3.ArchParser

在ArchParser需要获取report视图传过来的template名称。

export class ReportArchParser {
    parse(arch, fields = {}) {
        const archInfo = { fields, fieldAttrs: {}};
        visitXML(arch, (node) => {
            switch (node.tagName) {
                case "report": {
                    if (node.hasAttribute("template_id")) {
                        archInfo.template_id = node.getAttribute("template_id");
                    }
                    const title = node.getAttribute("string");
                    if (title) {
                        archInfo.title = title;
                    }
                    break;
                }
            }
        });
        return archInfo;
    }
}

4.4.Renderer

由于Renderer是根据template_id生成,因此这里不需要实现Renderer

4.5.Model

根据search传过来的参数获取并解析字段

    /**
     * @param {SearchParams} searchParams
     */
    async load(searchParams) {
        this.searchParams = searchParams;
        if (!this.initialGroupBy) {
            this.initialGroupBy = searchParams.context.graph_groupbys || this.metaData.groupBy; // = arch groupBy --> change that
        }
        this.data = {'value': '测试'}
        // const metaData = this._buildMetaData();
        // await this._fetchDataPoints(metaData);
    }

4.6.Controller

在useEffect中用传过来的template_xmlid,model中的解析数据生成template页面,并且替换o_content。

export class ReportController extends Component {
    setup() {
        this.archInfo = this.props.archInfo;
        this.model = useModelWithSampleData(this.props.Model, this.props.modelParams);
        useSetupView({
            rootRef: useRef("root"),
            getLocalState: () => {
                return { metaData: this.model.metaData };
            }
        });
        this.rootRef = useRef("root");
        this.searchBarToggler = useSearchBarToggler();
        useEffect(() => this.renderReport());
    }
    renderReport() {
        const innerHTML = renderToString(this.archInfo.template_xmlid, {
            model: this.model
        });
        const template = Object.assign(document.createElement("template"), { innerHTML });
        const tooltip = template.content.firstChild;
        // 将o_content替换为tooltip
        this.rootRef.el.querySelector('.o_content').replaceWith(tooltip);
    }
}

4.6.实现效果

在这里插入图片描述

5.总结

通过新增视图类型的方式
1、实现了controller的上半部分统一的效果,比如搜索的多选,新增数字筛选等
2、减少了report开发人员的工作量,开发人员可以专注于template的实现,真正做到组件化。

相关文章:

  • 【从零开始学习计算机科学】操作系统(一)什么是操作系统?操作系统的功能是什么
  • 案例1_1:Proteus点亮8个蓝色LED灯
  • 从头开始开发基于虹软SDK的人脸识别考勤系统(python+RTSP开源)(五)补充剩余内容
  • 邮件发送IP信誉管理:避免封号
  • 用CSS画一条0.5px的线
  • Aim Robotics电动胶枪:机器人涂胶点胶的高效解决方案
  • 《算法篇:三数之和问题的两种解法》
  • 修改Flutter项目使用的JAVA版本
  • linux-文本处理命令(echo,cut,sort,uniq,wc,tr,grep)
  • oneinstack 部署 lamp/lnmp
  • MongoDB 自动化部署
  • 搞定python之二----数据类型和程序的控制结构
  • Spring Boot 项目中 `Query` 后缀对象的放置位置
  • 每天五分钟深度学习框架PyTorch:ResNet算法模型完成CAFIR十分类
  • 【Spring IOC/AOP】
  • 怎么用vscode 写 markdown 文档
  • 【社区投稿】深入再谈智能指针、AsRef引用与Borrow借用
  • springboot3 spring security+jwt实现接口权限验证实现
  • Vue动态修改页面的 title 浏览器页签名称
  • 数据结构--【顺序表与链表】笔记
  • 做设备推广的网站/代写文章质量高的平台
  • 常熟做公司网站/网站排名优化公司哪家好
  • 网站二维码链接怎么做/国家免费培训机构
  • 宝安建设与住宅局网站/关键词排名seo优化
  • 佛山顺德网站建设公司/全网推广怎么做
  • wordpress开启https/疫情二十条优化措施