mcpField
T
theme-create

theme-create

github.com/ahmed-lakosha设计与 UI7657 次安装31 周前更新
代码仓库

关于 theme-create

面向 Odoo 主题开发者的实现指南,说明主题结构、SCSS 加载顺序、页面模板与激活模型。还包括安装测试步骤和不同 Odoo 版本的注意事项。

主要功能

  1. 01定义 Odoo 主题模块结构
  2. 02遵循 SCSS 变量加载规则
  3. 03配置字体与资源包
  4. 04创建网站页面模板
  5. 05实现主题复制后的激活逻辑
  6. 06检查安装与响应式布局

适用场景

  1. 01从头搭建 Odoo 网站主题
  2. 02排查 SCSS 编译或模块安装错误
  3. 03为不同 Odoo 版本调整主题
  4. 04验证主题页面及网站构建器

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ahmed-lakosha/odoo-plugins --skill theme-create

安装后在 Claude Code 中输入/theme-create确认已加载。

详细介绍

主题创建技能

关键规则

  1. 绝不修改 Odoo 核心中的 odoo/ 或 odoo/addons/
  2. 在主题 SCSS 中,绝不对 Odoo 核心变量使用 map-merge()——这些变量在加载时尚未定义
  3. 绝不使用 ir.asset 记录加载 Google Fonts——请使用 $o-theme-font-configs
  4. 在资源包中,始终对 primary_variables.scss 使用 ('prepend', ...)
  5. H6 始终为 16px(1rem)——这是固定的基准参考值
  6. 所有清单都必须包含 author: 'TaqaTechno'、website、support、license: 'LGPL-3'

生成的主题结构(v8.0)

theme_<name>/
├── __init__.py                      # Imports models
├── __manifest__.py                  # With proper asset bundles
├── models/
│   ├── __init__.py                 # Imports theme_<name>
│   └── theme_<name>.py             # theme.utils implementation (REQUIRED!)
├── security/
│   └── ir.model.access.csv
├── data/
│   ├── assets.xml                  # Minimal (fonts via SCSS, not ir.asset!)
│   ├── menu.xml
│   └── pages/                      # Individual page files (best practice)
│       ├── home_page.xml           # Inherits website.homepage
│       ├── aboutus_page.xml        # theme.website.page
│       ├── contactus_page.xml      # Inherits website.contactus
│       └── services_page.xml       # theme.website.page
├── views/
│   ├── layout/
│   │   └── templates.xml           # Base layout templates
│   └── snippets/
│       └── custom_snippets.xml
└── static/src/
    ├── scss/
    │   ├── primary_variables.scss   # Theme variables + font configs
    │   └── theme.scss               # Additional custom styles
    ├── js/
    │   └── theme.js                 # publicWidget implementations
    └── img/

清单模板

{
    'name': 'Theme <Name>',
    'version': '<odoo_version>.0.1.0.0',
    'category': 'Theme/Creative',
    'summary': 'Custom theme for <client>',
    'author': 'TaqaTechno',
    'website': 'https://www.taqatechno.com/',
    'support': '[email protected]',
    'license': 'LGPL-3',
    'depends': ['website'],
    'data': [
        'security/ir.model.access.csv',
        'views/layout/templates.xml',
        'views/snippets/custom_snippets.xml',
        'data/menu.xml',
        'data/pages/home_page.xml',
        'data/pages/aboutus_page.xml',
        'data/pages/contactus_page.xml',
    ],
    'assets': {
        'web._assets_primary_variables': [
            ('prepend', 'theme_<name>/static/src/scss/primary_variables.scss'),
        ],
        'web.assets_frontend': [
            'theme_<name>/static/src/scss/theme.scss',
            'theme_<name>/static/src/js/theme.js',
        ],
    },
    'installable': True,
    'auto_install': False,
    'application': False,
}

SCSS 加载顺序(关键)

1. YOUR theme's primary_variables.scss (via 'prepend')  ← FIRST
2. Odoo core primary_variables.scss                      ← SECOND
3. Other SCSS files

CONSEQUENCE:
  - CANNOT use map-merge() with core variables (they don't exist yet!)
  - MUST define standalone variables
  - Use 'color-palettes-name': 'default-1' to reference existing palettes

WRONG:  $o-color-palettes: map-merge($o-color-palettes, (...));
RIGHT:  $o-website-values-palettes: ( ( 'color-palettes-name': 'default-1' ) );

primary_variables.scss 模板

// ===================================================================
// Theme: <Name> — Generated by TaqaTechno
// PREPENDED before Odoo core — DO NOT use map-merge()!
// ===================================================================

// === Font Configuration (STANDALONE) ===
$o-theme-font-configs: (
    'Inter': (
        'family': ('Inter', sans-serif),
        'url': 'Inter:300,300i,400,400i,500,500i,600,600i,700,700i',
    ),
);

// === Website Values Palette (MASTER CONFIGURATION) ===
$o-website-values-palettes: (
    (
        'color-palettes-name': 'default-1',

        // Typography
        'font': 'Inter',
        'headings-font': 'Inter',
        'navbar-font': 'Inter',
        'buttons-font': 'Inter',

        // Header (NO custom header.xml needed!)
        'header-template': 'default',
        'header-links-style': 'default',
        'logo-height': 3rem,
        'fixed-logo-height': 2rem,

        // Buttons
        'btn-padding-y': 0.45rem,
        'btn-padding-x': 1.35rem,
        'btn-border-radius': 0.25rem,

        // Footer (NO custom footer.xml needed!)
        'footer-template': 'default',
        'footer-scrolltop': true,

        // Links & Layout
        'link-underline': 'hover',
        'layout': 'full',
    )
);

// === Typography Multipliers ===
$o-theme-h1-font-size-multiplier: (64 / 16); // 64px
$o-theme-h2-font-size-multiplier: (48 / 16); // 48px
$o-theme-h3-font-size-multiplier: (32 / 16); // 32px
$o-theme-h4-font-size-multiplier: (24 / 16); // 24px
$o-theme-h5-font-size-multiplier: (20 / 16); // 20px
$o-theme-h6-font-size-multiplier: (16 / 16); // 16px (FIXED)

页面创建模式

主页(继承 website.homepage)
<template id="view_home" inherit_id="website.homepage" name="Home">
    <xpath expr="//div[@id='wrap']" position="replace">
        <div id="wrap" class="oe_structure">
            
        </div>
    </xpath>
</template>
联系页面(继承 website.contactus)
<template id="view_contact" inherit_id="website.contactus" name="Contact">
    <xpath expr="//h1" position="replace">
        <h1>Get in Touch</h1>
    </xpath>
</template>
自定义页面(theme.website.page)
<template id="view_about" name="About">
    <t t-call="website.layout">
        <div id="wrap" class="oe_structure">
            <section class="s_title pt96 pb48">
                <div class="container"><h1>About Us</h1></div>
            </section>
        </div>
    </t>
</template>

<record id="page_about" model="theme.website.page">
    <field name="view_id" ref="view_about"/>
    <field name="is_published" eval="True"/>
    <field name="url">/about</field>
</record>

主题镜像模型架构

theme.ir.ui.view (Template) → ir.ui.view (Actual, with website_id)
theme.website.page (Template) → website.page (Actual, with website_id)

每个网站都会获得独立副本,从而能够在多个网站中重复使用主题。

theme.utils 激活(必需)

每个主题都必须包含 models/theme_<name>.py:

from odoo import models

class Theme<Name>(models.AbstractModel):
    _inherit = 'theme.utils'

    def _theme_<name>_post_copy(self, mod):
        """Called automatically when theme is installed on a website."""
        # Enable header template
        self.enable_view('website.template_header_default')
        # Enable footer template
        self.enable_view('website.template_footer_contact')
        # Show logo, not brand name
        self.enable_view('website.option_header_brand_logo')
        self.disable_view('website.option_header_brand_name')

方法名必须为 _theme_{technical_name}_post_copy,其中 technical_name 必须与文件夹名称一致。

可用方法:enable_view(xml_id)、disable_view(xml_id)、enable_asset(xml_id)、disable_asset(xml_id)

安装与测试

# 1. Update module list
python -m odoo -c conf/<PROJECT>.conf -d <DB> --update-list

# 2. Install theme
python -m odoo -c conf/<PROJECT>.conf -d <DB> -i theme_<name> --stop-after-init

# 3. If errors, auto-fix and retry (up to 3 attempts)
常见自动修复模式
错误修复方法
Undefined variable "$o-color-palettes"移除 map-merge,改用独立定义
Undefined variable "$o-theme-font-configs"独立定义(不使用 map-merge)
SyntaxError in SCSS定位解析错误位置并修复语法
Module not found在清单中添加依赖项
Malformed Google Fonts @import移除 ir.asset,改用 $o-theme-font-configs
测试清单
  • 主题安装无错误
  • CSS 编译成功
  • 浏览器控制台中没有 SCSS/JS 错误
  • 页眉和页脚样式应用正确
  • 响应式布局在手机/平板/桌面设备上均能正常工作
  • 网站构建器(编辑模式)运行正常,无错误

特定版本说明

OdooBootstrap片段注册主要差异
14-154.x简单 XPathml-*/mr-* 类
16-175.1.3简单 XPathms-*/me-* 类
18-195.1.3需要分组需要 snippet-group 属性

完整的 115+ 个 SCSS 变量参考,请参阅 theme-scss 技能。 有关 Figma 到 Odoo 的工作流和页面模板匹配,请参阅 theme-design 技能。

评论

支持 Markdown