第二章:Odoo Web 框架

本教程的第一部分向您介绍了大部分Owl的概念。现在是时候全面了解Odoo JavaScript框架了,因为它是Web客户端所使用的。

../../../_images/previously_learned1.svg

对于本章,我们将从 awesome_tshirt 插件提供的空仪表板开始。我们将逐步添加功能,使用Odoo JavaScript框架。

目标

../../../_images/overview_02.png

每个章节的练习解决方案都托管在 官方Odoo教程存储库

1. 新布局

Odoo 网页客户端中的大多数屏幕使用了一个常见的布局:顶部的控制面板,带有一些按钮,以及下方的主要内容区域。这是通过使用 Layout 组件,该组件位于 @web/search/layout 中来实现的。

Exercise

更新位于 awesome_tshirt/static/src/AwesomeDashboard 组件,使用 Layout 组件。您可以使用 {controlPanel: { "top-right": false, "bottom-right": false } } 作为 Layout 组件的 display 属性。

打开 http://localhost:8069/web,然后打开 Awesome T-Shirts 应用程序,查看结果。

../../../_images/new_layout.png

2. 添加一些快速导航按钮

让我们现在使用动作服务来方便地访问Odoo中的常见视图。

Services 是 Odoo JavaScript 框架定义的一个概念;它是一个持久的代码片段,可以导出状态和/或函数。每个服务可以依赖其他服务,组件可以使用 useService() 钩子导入服务。

Example

这展示了如何使用动作服务从组件中打开设置视图。

import { useService } from "@web/core/utils/hooks";
...
setup() {
    this.action = useService("action");
}
openSettings() {
    this.action.doAction("base_setup.action_general_configuration");
}
...

Exercise

让我们在控制面板左下角区域添加三个按钮。

  1. 一个按钮 Customers,它打开一个包含所有客户的看板视图(此操作已经存在,所以你应该使用 其xml id)。

  2. 一个按钮 New Orders,点击后打开一个列表视图,显示最近7天内创建的所有订单。使用 Domain 辅助类来表示领域。

    小技巧

    一种表示所需领域的方法可能是 [('create_date','>=', (context_today() - datetime.timedelta(days=7)).strftime('%Y-%m-%d'))]

  3. 一个按钮 Cancelled Order,它打开了一个列表,显示了过去7天内创建的所有订单,但已经取消。不要重复定义该操作,将其合并到一个新的 openOrders 方法中。

../../../_images/navigation_buttons.png

3. 调用服务器,添加一些统计信息

让我们通过添加一些卡片(参见 Card 组件 在上一章中创建的) 来改进仪表盘,其中包含一些统计信息。有一个路由 /awesome_tshirt/statistics 执行一些计算并返回一个包含一些有用信息的对象。

每当我们需要调用特定的控制器时,我们需要使用 rpc 服务。它只导出一个执行请求的函数: rpc(route, params, settings)

这里是有关各种参数的简短说明:

  • route 是目标路由,以字符串形式表示。例如 /myroute/

  • params is an object that contains all data that will be given to the controller. (optional)

  • settings are for advanced controls on the request. Make it silent, or using a specific xhr instance. (optional)

Example

一个基本的请求可能是这样的:

setup() {
    this.rpc = useService("rpc");
    onWillStart(async () => {
        const result = await this.rpc("/my/controller", {a: 1, b: 2});
        // ...
    });
}

Exercise

  1. 修改 Dashboard 以使用 rpc 服务。

  2. onWillStart 钩子中调用统计路由 /awesome_tshirt/statistics

  3. 在仪表板中显示几张包含以下内容的卡片:

    • 本月新订单数量

    • 本月新订单的总金额

    • 本月每个订单的T恤平均数量

    • 本月取消订单数量

    • 从“新建”到“已发送”或“已取消”的订单平均处理时间

../../../_images/statistics.png

4. 缓存网络调用,创建服务

如果您打开浏览器的开发工具的 Network 选项卡,您会发现每次显示客户端操作时都会调用 /awesome_tshirt/statistics。这是因为每次挂载 Dashboard 组件时都会调用 onWillStart 钩子。但在这种情况下,我们更希望只在第一次调用时执行,因此我们实际上需要在 Dashboard 组件之外维护一些状态。这是一个很好的服务使用案例!

Example

下面的示例注册了一个简单的服务,每5秒显示一次通知。

import { registry } from "@web/core/registry";
const myService = {
    dependencies: ["notification"],
    start(env, { notification }) {
        let counter = 1;
        setInterval(() => {
            notification.add(`Tick Tock ${counter++}`);
        }, 5000);
    },
};
registry.category("services").add("myService", myService);

Exercise

  1. 注册并导入一个新的 awesome_tshirt.statistics 服务。

  2. 它应该提供一个名为 loadStatistics 的函数,一旦调用,就执行实际的rpc,并始终返回相同的信息。

  3. 使用 memoize 实用函数来缓存统计数据。

  4. Dashboard 组件中使用此服务。

  5. 检查它是否按预期工作

5. 显示饼图

每个人都喜欢图表(!),所以让我们在我们的仪表板中添加一个饼图。它将显示每个尺码(S/M/L/XL/XXL)销售的T恤比例。

对于这个练习,我们将使用 Chart.js。它是图表视图使用的图表库。然而,默认情况下它不会被加载,所以我们需要将它添加到我们的资源包中,或者进行懒加载。懒加载通常更好,因为我们的用户如果不需要它,就不必每次都加载 chartjs 代码。

Exercise

  1. 加载 chartjs,你可以使用 loadJs 函数来加载 /web/static/lib/Chart/Chart.js

  2. Card`(来自之前的练习)中,在仪表盘中显示一个 `pie chart,显示每个尺码的已售出 T 恤的正确数量(这些信息在统计路由中可用)。

../../../_images/pie_chart.png

6. 更进一步

以下是一些小的改进建议,如果您有时间可以尝试一下:

Exercise

  1. 确保你的应用程序可以通过 env._t 进行 翻译

  2. 点击饼图的某个部分应该打开一个列表视图,其中包含所有具有相应大小的订单。

  3. 添加一个 SCSS 文件,尝试更改仪表板操作的背景颜色。

../../../_images/misc.png