概述
odoo拥抱自由,让设计师走得更远,让发布者可以自定义他们需要的任何东西。吹嘘中...
odoo不同于其他cms,没有header.php等文件。odoo有默认的主体结构,我们创建新主题的时候实际是在扩展它,而不是创建或者修改。它已经自动集成在系统中,安装odoo的时候会自动安装。
其中包含内容:
- 基本页面、博客和电子商务
- website builder集成
- 基本代码块
- Less/Sass自动编译
- js和css自动合并和缩小。
主要技术:
- Bootstrap
- jQuery
- jQuery UI
- underscore.js
关于模块化
odoo的主题不是一个包含html和php文件的文件夹。他是一个用xml实现的模块化框架。
传统网页设计是通过代码来实现网页布局,这是一个“静态”的页面,你可以更新网站内容,但是如果您的客户需要修改哪怕一丁点东西,也需要你来帮他实现。
而odoo主题只需要你创建代码块来让用户可以选择,并进行拖放。他们就可以自行创建页面。我们将这称之为模块化。
可以将odoo主题想象为你需要创建的一个元素或者选项列表。作为设计者,您的目标是将这些元素创建满意的效果,而不管用户在哪里甚至是否使用它们。
以下是这些元素的列表:
-
代码片段
即一段html代码,用户可以在创建网站界面时候拖动、修改或者组合他们。你可以给每个代码片段定义一些样式或者选项,用户在使用的时候可以根据他们的需要进行选择。
-
页面
这是普通的网页,但是最终用户可以对他们进行编辑。你可以定义一些空白区域,用户可以将代码片段拖动到里面来。
-
样式
样式是使用标准CSS文件(或Less / Sass)定义的。您可以将样式定义为默认或可选。默认样式始终在您的主题中处于启用状态,可选样式可以由用户启用或禁用。
-
功能
借助Odoo的模块化功能,所有内容都可以进一步个性化。这意味着您有无限的创造力。添加功能很容易,并且很容易为最终用户提供可自定义的选项。
odoo XML结构
一个odoo XML文件以以编码规范开头。然后必须包含一个<odoo>标签。
[XML]
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
## YOUR CODE HERE
</odoo>
此外,所有您定义的元素和选项都必须包含一个<template>标签,例子:
[XML]
<template id="my_title" name="My title">
<h1>This is an HTML block</h1>
<h2 class="lead">And this is a subtitle</h2>
</template>
注意:不要误解了template的意思,一个tamplate标签,仅仅定义了一段html代码或者选项。但他不一定与我们看到的视觉效果完全一致(还有页面上的其他因素影响视觉效果)。
上面的代码中定义了一个标题,但是他还不会再任何地方显示,因为这个 template 还没有和odoo默认结构的任何部分关联。所以你还需要使用xpath、qWeb或者两个都使用。下文将详细阐述如何实现。
更新主题
主题XML文件仅仅在安装主题时候被加载,每次修改后需要强制重新加载。
只需要在主题模块页面点击更新按钮。
创建主题
- 文件夹:必须以theme_ 开头。
- manifest.py:包含主题的基本配置信息。
- init.py 强制要求文件。
-
views 和 static 文件夹:views是包含代码片段和自定义页面的xml文件。 static包含css样式、图片或者自定义js代码。
manifest.py
{
'name':'Tutorial theme',
'description': 'A description for your theme.',
'version':'1.0',
'author':'Your name',
'data': [
],
'category': 'Theme/Creative',
'depends': ['website', 'website_theme_install'],}
前四个值可以自由定义。
data属性包含xml文件列表。
category定义模块分类,格式:Theme/子类别。
depends:定义主题依赖的模块。
安装主题
安装主题,之需要将theme文件夹包含在odoo的addons(插件)文件夹中。然后进入odoo网站模块(配置》设置),在网站中,点击 “选择一个样式”按钮,然后选择你的主题,兵点击“使用这个主题”。
结构化一个ODOO页面
odoo页面包含两种元素:多页面公用元素和独特元素。 一般情况下,odoo提供 header和 footer两个多页面公用元素。
使用网站创建工具简单的创建一个新页面,点击:内容》新页面 输入页面名称,可以看到页面的代码:
<div id=“wrapwrap”>
<header />
<main />
<footer />
</div>
扩展默认header(头部)
一般情况下,odoo的header包含一个响应式导航菜单和一个公司logo图片。你也可以轻松修改现有样式和增加新元素。只需要在views文件夹中创建layout.xml文件,并且将其加入到odoo的xml文件中标注出来。
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
</odoo>
在odoo标签中创建新模板,复制以下代码:
<!-- Customize header -->
<template id="custom_header" inherit_id="website.layout" name="Custom Header">
<!-- Assign an id -->
<xpath expr="//div[@id='wrapwrap']/header" position="attributes">
<attribute name="id">my_header</attribute>
</xpath>
<!-- Add an element after the top menu -->
<xpath expr="//div[@id='wrapwrap']/header/nav" position="after">
<div class="container">
<div class="alert alert-info mt16" role="alert">
<strong>Welcome</strong> in our website!
</div>
</div>
</xpath>
</template>
以上代码的第一个xpath将会增加一个id到 my_header的元素上。如果你希望修改某个元素的css样式,而避免影响页面上的其他元素, 这样是最方便的。
注意:替换默认元素时要小心, 当你拓展了默认主题后,在以后的所有更新中,将会以您的更新优先。
第二个xpath会增加一个欢迎信息在导航菜单栏后面。
最后一步是将layout.xml添加到该theme文件夹下的xml文件列表中,也就是 manifest.py:
'data': [ 'views/layout.xml' ]
然后更新您的Theme样式。
效果如下:
创建个性化布局页面
创建一个服务页面, 包含服务列表,并根据服务摘要查看更多信息。
在views文件中,创建pages.xml文件,加默认的odoo标签。 在<odoo>标签内,创建一个页面(注意不是定义<template>)。
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<!-- === Services Page === -->
<record id="services_page" model="website.page">
<field name="name">Services page</field>
<field name="website_published">True</field>
<field name="url">/services</field>
<field name="type">qweb</field>
<field name="key">theme_tutorial.services_page</field>
<field name="arch" type="xml">
<t t-name="theme_tutorial.services_page_template">
<h1>Our Services</h1>
<ul class="services">
<li>Cloud Hosting</li>
<li>Support</li>
<li>Unlimited space</li>
</ul>
</t>
</field>
</record>
</odoo>
页面里面有例如name或者url等很多属性。
虽然我们定义了页面,但还没有告诉系统如何使用这个页面。 所以,我们必须使用QWeb。 用<t>标签,把html代码包含起来。例子:
<record id="services_page" model="website.page">
<field name="name">Services page</field>
<field name="website_published">True</field>
<field name="url">/services</field>
<field name="type">qweb</field>
<field name="key">theme_tutorial.services_page</field>
<field name="arch" type="xml">
<t t-name="theme_tutorial.services_page_template">
<t t-call="website.layout">
<div id="wrap">
<div class="container">
<h1>Our Services</h1>
<ul class="services">
<li>Cloud Hosting</li>
<li>Support</li>
<li>Unlimited space</li>
</ul>
</div>
</div>
</t>
</t>
</field>
</record>
其中,<t t-call="website.layout"> 会使用我们的代码来扩展odoo默认页面布局。
我们把代码包含到两个div,其中一个的id是warp,另外一个的class 是container。这是一个最简单的布局。
下一步是增加用户可以用代码片段填充的空白区域,所以我们在div#wrap关闭之前,创建了一个class为oe_structure的div。
注意:您可以创建任意的代码片段区域,并把它们放在网页的任何位置。
另外还有一种使用<template>指令 创建页面的办法:
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<!-- === Services Page === -->
<template id="services_page_template">
<t t-call="website.layout">
<div id="wrap">
<div class="container">
<h1>Our Services</h1>
<ul class="services">
<li>Cloud Hosting</li>
<li>Support</li>
<li>Unlimited space</li>
</ul>
<!-- === Snippets' area === -->
<div class="oe_structure" />
</div>
</div>
</t>
</template>
<record id="services_page" model="website.page">
<field name="name">Services page</field>
<field name="website_published">True</field>
<field name="url">/services</field>
<field name="view_id" ref="services_page_template"/>
</record>
</odoo>
这将允许你用<xpath>进一步定制页面。
所有页面已经OK后,就可以将pages.xml加入到manifest.py文件中, 然后更新主题:
'data': [
'views/layout.xml',
'views/pages.xml'],
现在,服务页面已经就绪,并且可以通过导航 <yourwebsite>/services(xml中url配置)。
而且,该页面可以将代码片段 拖拽到 服务列表 中。
现在让我们再回到pages.xml页面,在页面模板后面,添加以下代码:
<record id="services_page_link" model="website.menu">
<field name="name">Services</field>
<field name="page_id" ref="services_page"/>
<field name="parent_id" ref="website.main_menu" />
<field name="sequence" type="int">99</field>
</record>
这段代码将会在主菜单添加一个链接,连接到我们创建的服务页面:
sequence属性是定义链接在菜单中的排序位置。此处设置99是为了让他们尽可能的靠后。你可以检查website模块中的data.xml文件,home链接设置的是10,contact us设置的是60。所以,如果你希望将服务链接放到中间,就应该设置为40。
添加样式
odoo默认包含bootstrap,所以你可以使用所有bootstrap样式和布局。如果bootstrap无法满足你的需求,你也可以按照一下方法来自定义样式和风格。
首先创建一个空的style.scss文件,然后将它放在static文件夹中的scss文件夹下。 以下样式可以个性化刚创建的服务页面,可以复制过去并保存:
.services {
background: #EAEAEA;
padding: 1em;
margin: 2em 0 3em;
li {
display: block;
position: relative;
background-color: #16a085;
color: #FFF;
padding: 2em;
text-align: center;
margin-bottom: 1em;
font-size: 1.5em;
}}
然后,需要在view文件夹下,创建一个assets.xml文件。并创建odoo标签,然后在其中加上一下代码(将theme folder替换成您的主题文件夹名称):
<template id="mystyle" name="My style" inherit_id="website.assets_frontend">
<xpath expr="link[last()]" position="after">
<link rel="stylesheet" type="text/scss" href="//www.greatytc.com/theme folder/static/scss/style.scss"/>
</xpath>
</template>
其中的inherit_id属性,是继承另外一个模板并做其他操作。这个例子是继承 assets_frontend 模板(在website模块中)。assets_frontend的作用是加载Website Builder的资源列表,而我们还需要增加自己的scss文件到其中去。
这可以通过使用xpath来查找expr="link[last()]" 和 position="after" 实现。即 将我的css文件加到资源列表的最后。
将我们的样式文件加到最后,就可以确保我们定义的样式具有优先性。
最后需要将assets.xml加到manifest.py中,并且更新主题。
现在,自定义的scss文件已经出现在我们的主题中,并且会自动编译、压缩、和现有的资源合并。如图:
创建代码片段
现在创建一个代码片段:显示三个推荐并且可以由用户通过Website Builder UI进行编辑。
在view文件夹下创建一个snippets.xml,添加odoo标签,然后复制以下代码到odoo标签中。这个模板包含要在代码片段中显示的HTML标签。
<template id="snippet_testimonial" name="Testimonial snippet">
<section class="snippet_testimonial">
<div class="container text-center">
<div class="row">
<div class="col-lg-4">
<img alt="client" class="rounded-circle" src="//www.greatytc.com/theme_tutorial/static/src/img/client_1.jpg"/>
<h3>Client Name</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
<div class="col-lg-4">
<img alt="client" class="rounded-circle" src="//www.greatytc.com/theme_tutorial/static/src/img/client_2.jpg"/>
<h3>Client Name</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
<div class="col-lg-4">
<img alt="client" class="rounded-circle" src="//www.greatytc.com/theme_tutorial/static/src/img/client_3.jpg"/>
<h3>Client Name</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>
</div>
</section>
</template>
我们在其中三列使用了bootstrap默认样式,它不仅仅是用于布局,还会被 Website Builder 识别为可以由用户进行大小调整。
定义了代码片段内容后,还需要替换到编辑栏中,用户才能将其拖动到页面中。复制一下代码到snippets.xml文件:
<template id="place_into_bar" inherit_id="website.snippets" name="Place into bar">
<xpath expr="//div[@id='snippet_structure']/div[@class='o_panel_body']" position="inside">
<t t-snippet="theme_tutorial.snippet_testimonial"
t-thumbnail="//www.greatytc.com/theme_tutorial/static/src/img/ui/snippet_thumb.jpg"/>
</xpath>
</template>
效果如图示:
使用xpath技术,我们可以用id很快定位特定的元素 snippet_structure。这个代码片段将会出现在结构标签中。如果需要修改目标标签,只需要修改xpath表达式中的id值就行:
Tab Name | Xpath expression |
---|---|
Structure | //div[@id='snippet_structure'] |
Content | //div[@id='snippet_content'] |
Feature | //div[@id='snippet_feature'] |
Effect | //div[@id='snippet_effect'] |
<t>标签会调用代码片段模板并会显示一个放在img文件夹中的缩略图。现在,你可以用代码片段中拖动代码片段,放在页面中,然后查看效果。
代码片段选项
通过代码片段选项,我们可设置一些代码片段的可编辑参数,让用户来编辑这些参数。
选项组属性
选项被组包裹起来,组有很多属性,用来定义被包含的选项如何和用户界面发生交互。
data-selector="[css selector(s)]"
将组中包含的所有选项绑定到特定元素。data-js=" custom method name "
用于绑定自定义Javascript方法。data-drop-in="[css selector(s)]"
定义该代码片段可被放入到其中的元素列表。data-drop-near="[css selector(s)]"
定义该代码片段可被放入到附近的元素列表。
默认选项方法
选项将标准CSS类应用于代码段。根据您选择的方法,UI的行为会有所不同。
data-select-class="[class name]"
同一组中的多个data-select-class定义了用户可以选择应用的样式列表。一次只能启用一个选项。
data-toggle-class="[class name]"
data-toggle-class用于将列表中的一个或多个CSS类应用于代码段。可以一次应用多个选择。
示例演示:在views文件夹中创建一个新文件:options.xml 并且添加默认的odoo标签,在标签内创建一下代码:
<template id="snippet_testimonial_opt" name="Snippet Testimonial Options" inherit_id="website.snippet_options">
<xpath expr="//div[@data-js='background']" position="after">
<div data-selector=".snippet_testimonial"> <!-- Options group -->
<div class="dropdown-submenu">
<a href="#" class="dropdown-item">Your Option</a>
<div class="dropdown-menu"><!-- Options list -->
<a href="#" class="dropdown-item" data-select-class="opt_shadow">Shadow Images</a>
<a href="#" class="dropdown-item" data-select-class="opt_grey_bg">Grey Bg</a>
<a href="#" class="dropdown-item" data-select-class="">None</a>
</div>
</div>
</div>
</xpath>
</template>
这个模板会继承默认snippet_options 模板,然后再bacnground选项后(xpath的expr属性),添加我们的选项。
要将选项按特定顺序放置,请检查网站模块中的snippet_options模板,然后在所需位置之前/之后添加您的选项。
上例中,我们将所有选项包裹在一个div标签中,该标签将对选项进行分组,并将它们定位到正确的选择器(data-selector =“.snippet_testimonial”)。
为了定义选项,我们应用了 data-select-class 属性到 li 元素。当用户选择了该选项时,这个属性中包含的class将会自动应用在元素上。
由于selectClass方法避免了多个选择,因此最后一个“空”选项会将代码段重置为默认值。
最后将options.xml添加到 manifest.py中,并且更新主题。
结果如下图。将代码段拖放到页面上,您会注意到我们的新选项会自动添加到自定义菜单中。检查页面,您还将注意到选择选项时,该类将应用于元素。
还需要创建一些css规则,才能让选项呈现视觉效果。打开style.scss文件,添加一下代码:
.snippet_testimonial {
border: 1px solid #EAEAEA;
padding: 20px;}
// These lines will add a default style for our snippet. Now let's create our custom rules for the options.
.snippet_testimonial {
border: 1px solid #EAEAEA;
padding: 20px;
&.opt_shadow img {
box-shadow: 0 2px 5px rgba(51, 51, 51, 0.4);
}
&.opt_grey_bg {
border: none;
background-color: #EAEAEA;
}
}
现在已成功为代码段创建了选项。发布者每次单击选项时,系统都会添加data-select-class属性中指定的class样式。
通过将data-select-class替换为data-toggle-class,您将能够同时选择更多的class样式。
Javascript选项
data-select-class 和 data-toggle-class只能执行简单改变样式操作,但是如果你需要定制更多功能,就需要使用javascript选项。
选项组的data-js属性用来定义客户方法。现在我们为刚创建的选项组div添加一个data-js属性,用以创建一个 推荐代码片段 :
<div data-js="snippet_testimonial_options" data-selector=".snippet_testimonial">
[...]
</div>
当我们每次进入编辑模式时,系统会自动查找 snippet_testimonial_options 方法。
现在在Static目录下创建一个 tutorial_editor.js 文件,复制一下代码进去:
odoo.define(function (require) {
var options = require('web_editor.snippets.options');
});
这个文件将包含我们的代码片段在编辑模式下所需要的所有js方法。比如我们刚需要的 snippet_testimonial_options 方法:
odoo.define(function (require) {
var options = require('web_editor.snippets.options');
options.registry.snippet_testimonial_options = options.Class.extend({
onFocus: function () {
alert("On focus!")
},
});
});
我们在代码中定义了一个onFocus方法来出发我们的函数。odoo的WebSite Builder提供了一系列事件来触发自定义函数:
Event | Description |
---|---|
start |
当发布者在编辑会话中首次选择该代码段或将代码段拖放到页面中时触发。 |
onFocus |
每次用户选择该代码段或将代码段拖放到页面中时触发。 |
onBlur |
片段失去焦点时,会发生此事件。 |
onClone |
复制代码段后立即触发。 |
onRemove |
删除摘要之前触发。 |
onBuilt |
将该片段拖放到放置区域后立即触发。触发此事件后,内容已插入页面中。 |
cleanForSave |
它在发布者保存页面之前触发。 |
现在需要将刚新建的js文件添加到编辑资源列表。 在assets.xml中创建新的template,需要继承assets_editor。
<template id="my_js" inherit_id="website.assets_editor" name="My Js">
<xpath expr="script[last()]" position="after">
<script type="text/javascript" src="//www.greatytc.com/theme_tutorial/static/src/js/tutorial_editor.js" />
</xpath>
</template>
最后更新主题即可。
测试效果:进入编辑模式,拖动代码片段到页面,就会看到js的弹出窗口。如果关掉窗口,再点击代码片段后,窗口会再次出现。如图:
编辑模式下的一些参考
基本上页面中的所有元素都可以由发布者编辑。除此之外,某些元素类型和CSS类在编辑时会触发特殊的Website Builder功能。
布局
<section />
任何 section 元素 都可以向内容块一样编辑。发布者可以移动或者复制它,也可以设置背景图片和背景颜色。section 是代码片段的标准主容器。
.row > .col-lg-*
所有来自bootstrap中 .row下级的大列,都可以由发布者调整大小。
contenteditable="Fasle"
此属性将防止对元素及其所有子元素进行编辑。
contenteditable="True"
将contenteditable= False元素中的元素加上该属性,以创建异常并使该元素及其子元素可编辑。
<a href="#" />
在“编辑模式”下,所有链接都可以被编辑或者设置样式。使用“链接模式”,链接还可以被替换为按钮。
多媒体
<span class=”fa” />
类图icon元素,编辑该元素会打开一个图形库供选择。也可以使用CSS设置该元素的样式。
<img />
图片被点击后,将打开图片库让选择图片。该元素也可以被css设置样式。
<frame />
<div class="media_iframe_video" data-src="[your url]" >
<div class="css_editable_mode_display"/>
<div class="media_iframe_video_size"/>
<iframe src="[your url]"/>
</div>
这段html代码将创建一个<iframe>元素,可由发布者编辑。
SEO 优化
方便信息录入
现在搜索引擎算法已经提升了内容的权重,对关键字比重的权重降低了很多。
由于内容对seo的重要性,所以我们应该注重让发布者能方便插入SEO相关内容。特别是内容摘要,应该更贴近seo主题。
以下是实现展示两列的代码片段,我们用两种方法来实现:
方案一:
不理想!
使用固定图片,为了保证图片和文本高度一致,发布者只能限制文本内容。
方案二:
**理想**
使用背景图片来自适应高度,发布者可以自由的添加文本,而不用关注图片高度。
页面切割
也没切割意思是将页面分成几个单独的部分,而这些部分被搜索引擎视为单独的条目。 所以在设计页面时,应该用正确的标签,以便搜索引擎能正确的识别。
<article>
用来指定一个独立的内容块。在其中应该包含一些独立的内容,这些内容应该是有意义的。也可以将<article>元素彼此嵌套。在这种情况下,这意味着嵌套元素与外部<article>元素相关。
<header>
这个标签表明这是一个独立的内容块的标题部分(<article>)。
<section>
section是代码段的默认标记,它指定内容块的一个子部分(章节)。它可以用于将<article>内容分为几个部分。建议使用标题元素(<h1> – <h6>)定义本节的主题。
<hgroup>
用于包装标题(<h1>-<h6>)。以下的例子是文章的标题和子标题都位于顶部:
<hgroup>
<h1>Main Title</h1>
<h2>Subheading</h2>
</hgroup>
页面描述
keywords 定义
应该使用适当的相关关键字以及相关的同义词。也可以将关键字放在页面的顶部,用以提升权重。
title 和 description定义
titile中的关键字应该尽可能地短,并且准确包含页面主关键字。一个好的关键字应该可以唤起读者的情感、疑问或者对读者的承诺。
description虽然对搜索引擎排序不重要,但是对于提高用户点击率却是相当重要的。它将是一个很好的广告内容,用以让用户知道搜索到的哪些页面才是他们需要的。需要注意的是:每个页面的keywords和description最好唯一,不要相同。