主题开发
主题决定前台外观——本文教你从零开发一个 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.jsonmanifest.json
Section titled “manifest.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 文件 = 一个页面:
---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');Slot 机制
Section titled “Slot 机制”主题在固定位置预留挂载点:
---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 文案 i18n
Section titled “UI 文案 i18n”硬编码的 UI 文案通过字典:
---import { t } from '@bangnicms/sdk/i18n';---
<button>{t('common.submit', { default: '提交' })}</button>字典在后台「i18n 字典管理」编辑。详见 UI 文案 i18n。
主题设置 schema
Section titled “主题设置 schema”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': '...' } }, },});后台「扩展市场 → 主题 → 设置」自动渲染对应表单。
调用主题设置
Section titled “调用主题设置”---import { getThemeSetting } from '@bangnicms/sdk';const primaryColor = await getThemeSetting('colors.primary');---
<style> :root { --primary: { primaryColor }; }</style>模型包字段渲染
Section titled “模型包字段渲染”如果用户装了模型包扩展了产品字段,主题如何渲染?
---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>)}SEO 友好
Section titled “SEO 友好”---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" />
# 构建pnpm build
# 打包 zipzip -r my-theme-v1.0.0.zip dist manifest.json README.md详见 打包与发布。
- 本地:
pnpm dev启动 BangNiCMS + 主题 - 集成测试:在测试 BangNiCMS 实例上传 zip 测试
- 多语言:每种语言验证一遍
- 移动端:手机 / 平板测试