跳转到内容

主题开发

主题决定前台外观——本文教你从零开发一个 BangNiCMS 主题。

my-theme/
├── manifest.json 必填:主题元数据
├── README.md 说明文档
├── theme.config.ts 主题设置 schema
├── src/
│ ├── layouts/ 页面布局
│ │ ├── BaseLayout.astro
│ │ └── ContentLayout.astro
│ ├── components/ UI 组件
│ │ ├── Header.astro
│ │ ├── Footer.astro
│ │ ├── ProductCard.astro
│ │ └── ...
│ ├── pages/ 页面模板
│ │ ├── index.astro 首页
│ │ ├── products/[key].astro 产品详情
│ │ ├── articles/[key].astro 文章详情
│ │ └── ...
│ └── styles/ 样式
│ ├── global.css
│ └── theme.css
├── public/ 静态资源
│ ├── images/
│ └── fonts/
└── package.json

主题元数据:

{
"extensionType": "theme",
"extensionKey": "my-modern-b2b",
"name": "现代 B2B 主题",
"version": "1.0.0",
"author": "Your Name",
"description": "为出海 B2B 企业打造的多语言主题",
"compatibility": {
"bangnicms": ">=1.0.0"
},
"slots": [
"homepage-hero",
"homepage-features",
"footer-extra"
],
"marketingMeta": {
"preview": "https://...",
"screenshots": ["...", "..."]
}
}

主题用 Astro + React 组件。Astro 提供:

  • 服务端渲染(SSR)
  • 静态生成(SSG)
  • React / Vue / Svelte 等框架混用

每个 .astro 文件 = 一个页面:

src/pages/products/[key].astro
---
import { getProduct } from '@bangnicms/sdk';
import BaseLayout from '../layouts/BaseLayout.astro';
export async function getStaticPaths() {
const products = await getAllProducts();
return products.map((p) => ({ params: { key: p.productKey } }));
}
const { key } = Astro.params;
const product = await getProduct(key, { lang: Astro.locals.lang });
---
<BaseLayout title={product.title}>
<h1>{product.title}</h1>
<p>{product.description}</p>
...
</BaseLayout>

通过 @bangnicms/sdk 提供的 helper:

import { getProduct, listProducts, getCategoryTree } from '@bangnicms/sdk';
const product = await getProduct('industrial-laser', { lang: 'en' });
const products = await listProducts({ category: 'industrial', limit: 10 });
const tree = await getCategoryTree('product');

主题在固定位置预留挂载点:

---
import { PluginSlot } from '@bangnicms/sdk';
---
<header>
<Logo />
<Nav />
<PluginSlot name="header-utility" />
</header>
<main>
<slot />
</main>
<PluginSlot name="footer-extra" />
<Footer />

运营在后台把插件挂到对应 slot → 主题自动渲染插件内容。

详见 插件开发

主题需要适配多语言——Astro.locals.lang 自动注入:

---
const lang = Astro.locals.lang;
const isDefault = Astro.locals.isDefaultLang;
---
<html lang={lang}>
<head>
<link rel="alternate" hreflang="x-default" href="..." />
{languages.map((l) => (
<link rel="alternate" hreflang={l.code} href={`/${l.urlSegment}/...`} />
))}
</head>
</html>

硬编码的 UI 文案通过字典:

---
import { t } from '@bangnicms/sdk/i18n';
---
<button>{t('common.submit', { default: '提交' })}</button>

字典在后台「i18n 字典管理」编辑。详见 UI 文案 i18n

theme.config.ts 声明可调设置:

import { defineThemeConfig } from '@bangnicms/sdk';
export default defineThemeConfig({
colors: {
primary: { type: 'color', default: '#2563EB', label: '主色' },
secondary: { type: 'color', default: '#06B6D4' },
},
layout: {
containerWidth: { type: 'select', options: ['1200', '1440', '1600'], default: '1200' },
},
homepage: {
showHero: { type: 'boolean', default: true },
heroTitle: { type: 'localized-text', default: { 'zh-CN': '...', 'en': '...' } },
},
});

后台「扩展市场 → 主题 → 设置」自动渲染对应表单。

---
import { getThemeSetting } from '@bangnicms/sdk';
const primaryColor = await getThemeSetting('colors.primary');
---
<style>
:root {
--primary: { primaryColor };
}
</style>

如果用户装了模型包扩展了产品字段,主题如何渲染?

---
import { getExtensionFields } from '@bangnicms/sdk';
const extensionFields = await getExtensionFields('product', product.id, { lang });
---
{extensionFields.specifications && (
<section>
<h3>规格</h3>
<div set:html={extensionFields.specifications.value} />
</section>
)}
---
const seoTitle = product.seoTitle || `${product.title} - ${siteName}`;
const seoDesc = product.seoDescription || product.description.slice(0, 160);
---
<head>
<title>{seoTitle}</title>
<meta name="description" content={seoDesc} />
<meta property="og:title" content={seoTitle} />
<meta property="og:image" content={product.coverImageUrl} />
...
</head>
  • 图片懒加载loading="lazy" for非首屏
  • 字体优化font-display: swap
  • CSS 关键路径:内联首屏 CSS
  • JS 异步<script defer />
  • 预取<link rel="prefetch" />
Terminal window
# 构建
pnpm build
# 打包 zip
zip -r my-theme-v1.0.0.zip dist manifest.json README.md

详见 打包与发布

  • 本地:pnpm dev 启动 BangNiCMS + 主题
  • 集成测试:在测试 BangNiCMS 实例上传 zip 测试
  • 多语言:每种语言验证一遍
  • 移动端:手机 / 平板测试