# 模板开发

# 快速开始

示例模板仓库https://github.com/beikeshop/beikeshop-sample-theme

可以先下载示例模板,参考其目录结构和代码进行开发:

# 下载示例模板
git clone https://github.com/beikeshop/beikeshop-sample-theme.git

# 将 SampleTheme 文件夹复制到 beikeshop 的 plugins/ 目录下
# 然后按照本文档说明进行修改和开发

# 一、模板架构概述

BeikeShop 支持以插件形式开发模板主题。相同的功能可以拥有完全不一样的用户界面。

# 模板加载机制

系统采用以下模板加载策略:

  1. 优先使用已启用的主题模板
  2. 如果启用的模板中不存在某个文件,则回退到 themes/default 目录下的默认模板文件

这意味着你只需要覆盖需要自定义的模板文件即可,不需要复制所有文件。

# 核心目录结构

beikeshop/
├── plugins/                          # 插件目录
│   └── YourTheme/                    # 你的模板插件(文件夹名,大驼峰命名)
│       ├── config.json               # 插件配置(必须)
│       ├── Bootstrap.php             # 插件启动文件(必须)
│       ├── Resources/                # 开发用源文件(SCSS/JS)
│       │   └── beike/shop/your_theme/
│       │       ├── css/
│       │       │   ├── bootstrap/bootstrap.scss
│       │       │   └── app.scss
│       │       └── js/
│       │           └── app.js
│       ├── Themes/                   # Blade 模板文件
│       │   └── your_theme/
│       │       ├── layout/
│       │       │   └── master.blade.php
│       │       ├── home.blade.php
│       │       └── ...
│       ├── Static/                   # 静态资源(发布到 public)
│       │   ├── image/
│       │   │   ├── logo.png          # 插件图标
│       │   │   └── theme.jpg         # 模板预览图
│       │   └── public/
│       │       └── build/beike/shop/your_theme/
│       │           ├── css/
│       │           │   ├── bootstrap.css  # 编译后的 CSS
│       │           │   └── app.css
│       │           └── js/
│       │               └── app.js
│       └── Seeders/                  # 演示数据(可选)
│           └── ThemeSeeder.php
├── themes/                           # 系统模板目录(安装时自动复制)
│   └── your_theme/                   # 从 plugins/YourTheme/Themes 复制而来
└── public/                           # 公共资源目录(安装时自动复制)
    └── plugin/your_theme/            # 从 plugins/YourTheme/Static 复制而来

# 二、创建模板插件

# 2.1 创建插件目录

plugins/ 目录下创建你的模板文件夹,例如 Fashion

mkdir plugins/Fashion

# 2.2 创建 config.json

在插件根目录创建 config.json,这是插件的核心配置文件:

{
    "code": "fashion",
    "name": {
        "zh_cn": "时尚模板",
        "en": "Fashion Theme"
    },
    "description": {
        "zh_cn": "一款时尚的电商模板",
        "en": "A fashionable e-commerce theme"
    },
    "type": "theme",
    "version": "v1.0.0",
    "icon": "/image/logo.png",
    "theme": "/image/theme.jpg",
    "author": {
        "name": "你的名称",
        "email": "your@email.com"
    }
}

重要字段说明:

字段 说明 示例
code 模板唯一标识,小写+下划线命名 fashionmy_theme
name 模板名称,支持多语言 {"zh_cn": "时尚模板", "en": "Fashion"}
type 必须为 theme theme
icon 插件图标路径,相对于 Static/ 目录,尺寸 500×500 /image/logo.png
theme 模板预览图路径,相对于 Static/ 目录,尺寸 740×856 /image/theme.jpg

# 2.3 创建 Bootstrap.php

在插件根目录创建 Bootstrap.php,这是插件的启动文件:

<?php
namespace Plugin\Fashion;

class Bootstrap
{
    public function boot()
    {
        // 在这里添加 hook 逻辑
        // 例如:添加自定义 CSS/JS 到页面
        add_hook_blade('layout.header.code', function ($callback, $output, $data) {
            return view('fashion::shop.custom-code');
        });
    }
}

命名规则:

  • namespace 必须为 Plugin\你的插件文件夹名(大驼峰)
  • 类名必须为 Bootstrap
  • 必须包含 boot() 方法

# 三、开发模板文件

# 3.1 Blade 模板文件

模板文件放在 Themes/ 目录下,目录结构应与 themes/default 保持一致。

开发流程:

  1. themes/default 复制需要修改的模板文件到你的插件目录:

    themes/default/home.blade.php
    → plugins/Fashion/Themes/fashion/home.blade.php
    
  2. 只修改你需要自定义的文件,不需要修改的文件保持默认即可

  3. 系统加载顺序:

    • 先查找 themes/fashion/xxx.blade.php
    • 如果不存在,则回退到 themes/default/xxx.blade.php

示例目录结构:

plugins/Fashion/Themes/fashion/
├── layout/
│   ├── master.blade.php      # 主布局(可选覆盖)
│   ├── header.blade.php      # 头部(可选覆盖)
│   └── footer.blade.php      # 底部(可选覆盖)
├── home.blade.php            # 首页
├── category.blade.php        # 分类页
├── product/
│   └── product.blade.php     # 商品详情页
└── cart/
    └── cart.blade.php        # 购物车页

# 3.2 SCSS/CSS 样式

样式源文件放在 Resources/beike/shop/your_theme/css/ 目录下。

目录结构:

plugins/Fashion/Resources/beike/shop/fashion/css/
├── bootstrap/
│   └── bootstrap.scss        # Bootstrap 自定义变量
├── app.scss                  # 主样式文件
├── global.scss               # 全局样式
├── header.scss               # 头部样式
├── footer.scss               # 底部样式
└── home.scss                 # 首页样式

app.scss 示例:

// 引入 bootstrap 变量
@import 'bootstrap/bootstrap';

// 引入各模块样式
@import 'global';
@import 'header';
@import 'footer';
@import 'home';

# 3.3 JavaScript

JS 源文件放在 Resources/beike/shop/your_theme/js/ 目录下。

目录结构:

plugins/Fashion/Resources/beike/shop/fashion/js/
├── app.js                    # 主 JS 文件
├── common.js                 # 公共函数
├── header.js                 # 头部交互
└── product.js                # 商品页交互

app.js 示例:

import './common';
import './header';
import './product';

# 四、编译配置(重点)

# 4.1 配置 webpack.mix.js

这是最关键的一步。开发新模板时,必须配置 webpack.mix.js 文件。

打开项目根目录的 webpack.mix.js,找到被注释的模板编译代码段(约第 30-55 行),取消注释并修改 themeFileName 为你的插件文件夹名称(大驼峰):

/* 如果开发新模版,编译需要开启下面代码, 将 themeFileName 的值修改为你的模版文件名 */
const themeFileName = 'Fashion';  // ← 修改为你的插件文件夹名(大驼峰)
const themeCode = themeFileName.replace(/([A-Z])/g,"_$1").toLowerCase().replace(/^_/,'');

// 拷贝模版 blade 文件 到 themes 目录下
if (!mix.inProduction()) {
  mix.copy(`plugins/${themeFileName}/Themes`, 'themes');
}

// 编译模版 scss/js 到 public/build 下
mix.sass(`plugins/${themeFileName}/Resources/beike/shop/${themeCode}/css/bootstrap/bootstrap.scss`, `public/build/beike/shop/${themeCode}/css/bootstrap.css`)
.then(() => {
  fs.copyFileSync(`public/build/beike/shop/${themeCode}/css/bootstrap.css`, `plugins/${themeFileName}/Static/public/build/beike/shop/${themeCode}/css/bootstrap.css`);
});

mix.sass(`plugins/${themeFileName}/Resources/beike/shop/${themeCode}/css/app.scss`, `public/build/beike/shop/${themeCode}/css/app.css`)
.then(() => {
  fs.copyFileSync(`public/build/beike/shop/${themeCode}/css/app.css`, `plugins/${themeFileName}/Static/public/build/beike/shop/${themeCode}/css/app.css`);
});

mix.js(`plugins/${themeFileName}/Resources/beike/shop/${themeCode}/js/app.js`, `public/build/beike/shop/${themeCode}/js/app.js`)
.then(() => {
  fs.copyFileSync(`public/build/beike/shop/${themeCode}/js/app.js`, `plugins/${themeFileName}/Static/public/build/beike/shop/${themeCode}/js/app.js`);
});

重要说明:

变量 说明 示例
themeFileName 插件文件夹名称(大驼峰) FashionMyTheme
themeCode 自动转换后的 code(小写+下划线) fashionmy_theme

转换规则:

Fashion    → fashion
MyTheme    → my_theme
Fashion4   → fashion4

# 4.2 编译命令

开发阶段(监听文件变化,自动编译):

npm install          # 首次需要安装依赖
npm run watch        # 监听模式,文件修改后自动编译

生产环境(压缩构建):

npm run prod         # 压缩编译 CSS/JS

# 4.3 编译输出说明

编译后会自动生成以下文件:

public/build/beike/shop/fashion/
├── css/
│   ├── bootstrap.css
│   └── app.css
└── js/
    └── app.js

同时,通过 .then() 回调,编译后的文件会自动复制到插件的 Static/public/build/ 目录下:

plugins/Fashion/Static/public/build/beike/shop/fashion/
├── css/
│   ├── bootstrap.css
│   └── app.css
└── js/
    └── app.js

# 4.4 ⚠️ 打包前必须确认编译文件已同步

这是很多开发者容易忽略的关键点!

模板打包发布前,必须确保:

  1. 编译后的 CSS/JS 文件已经存在于 Static/public/build/ 目录中
  2. 这些文件会随插件一起打包,用户安装后才有样式

如何确保:

  • 方式一(推荐):使用 webpack.mix.js 中配置好的自动复制功能

    • 取消注释模板编译代码
    • 运行 npm run prod
    • 编译后的文件会自动复制到 Static/public/build/ 目录
  • 方式二(手动):手动拷贝编译文件

    • public/build/beike/shop/your_theme/ 下的文件
    • 复制到 plugins/YourTheme/Static/public/build/beike/shop/your_theme/

如果忘记这一步,用户安装模板后将没有样式!


# 五、安装和启用模板

# 5.1 安装模板

  1. 进入后台 → 插件列表
  2. 找到你的模板插件
  3. 点击 安装

安装时系统会自动执行:

  • Themes/ 目录下的 Blade 模板复制到 themes/your_theme/
  • Static/ 目录下的静态资源复制到 public/ 对应目录

# 5.2 启用模板

  1. 进入后台 → 设计模板设置
  2. 找到你的模板,点击 去启用
  3. 可选:勾选"导入演示数据"(如果模板提供了 Seeders)
  4. 确认启用

# 5.3 访问前台

启用后访问前台即可看到新模板的效果。


# 六、模板数据 Seeders(可选)

如果你的模板需要自带演示数据(如首页布局配置),可以使用 Seeders。

# 6.1 创建 Seeder

Seeders/ 目录下创建 ThemeSeeder.php

<?php
namespace Plugin\Fashion\Seeders;

use Beike\Repositories\SettingRepo;
use Illuminate\Database\Seeder;

class ThemeSeeder extends Seeder
{
    public function run()
    {
        $homeSetting = $this->getHomeSetting();
        SettingRepo::update('system', 'base', ['design_setting' => $homeSetting]);
    }

    private function getHomeSetting(): array
    {
        // 返回首页布局配置
        // 数据格式参考 settings 表中 design_setting 的值
        return [
            // ... 你的首页配置数据
        ];
    }
}

# 6.2 如何获取首页配置数据

  1. 在后台设计器中配置好首页布局
  2. 到数据库 settings 表,查找 name = 'design_setting' 的记录
  3. 复制 value 字段的 JSON 数据
  4. 使用工具将 JSON 转为 PHP 数组:https://uutool.cn/json2php/
  5. 将转换后的数组放入 getHomeSetting() 方法中

# 6.3 启用时导入数据

用户在后台启用模板时,勾选"导入演示数据"选项,系统会自动运行 Seeder 导入数据。


# 七、静态资源管理

# 7.1 Static 目录结构

plugins/Fashion/Static/
├── image/
│   ├── logo.png          # 插件图标(后台插件列表显示)
│   └── theme.jpg         # 模板预览图(模板设置页显示)
├── public/
│   └── build/beike/shop/fashion/
│       ├── css/          # 编译后的 CSS(必须包含)
│       └── js/           # 编译后的 JS(必须包含)
└── catalog/fashion/      # 模板用到的图片(banner、icon 等)
    └── demo/

# 7.2 资源访问

在模板中访问静态资源:

{{-- 访问插件静态文件 --}}
<img src="{{ plugin_asset('fashion', 'image/logo.png') }}">
<img src="{{ asset('plugin/fashion/catalog/fashion/demo/banner.jpg') }}">

{{-- 访问编译后的 CSS/JS(系统自动加载) --}}
{{ mix('/build/beike/shop/fashion/css/app.css') }}
{{ mix('/build/beike/shop/fashion/js/app.js') }}

# 八、打包发布

# 8.1 打包前检查清单

  • [ ] 所有 SCSS/JS 已编译,编译后的文件在 Static/public/build/
  • [ ] logo.pngtheme.jpg 已替换为自己的素材
  • [ ] config.json 信息完整准确
  • [ ] Bootstrap.php 命名空间正确
  • [ ] 模板文件路径正确(Themes/your_theme/
  • [ ] 测试安装、启用、切换功能正常

# 8.2 打包

将插件文件夹打包为 ZIP 压缩包:

cd plugins
zip -r Fashion.zip Fashion/

# 8.3 发布

  1. 登录 BeikeShop 官网
  2. 进入个人中心 → 插件市场
  3. 上传 ZIP 包发布
  4. 其他用户可在后台插件市场购买并安装

# 九、常见问题

# Q1: 模板安装后没有样式?

原因:编译后的 CSS/JS 文件没有包含在插件的 Static/public/build/ 目录中。

解决

  1. 确保 webpack.mix.js 中的模板编译代码已取消注释
  2. 运行 npm run prod 进行编译
  3. 确认 plugins/YourTheme/Static/public/build/ 目录下有编译后的文件

# Q2: 修改了 SCSS 但前台没有变化?

原因:没有重新编译或编译后没有刷新缓存。

解决

  1. 开发阶段使用 npm run watch 监听自动编译
  2. 修改后等待几秒自动编译完成
  3. 刷新浏览器(可能需要强制刷新 Ctrl+Shift+R)

# Q3: 模板文件修改后没有生效?

原因:Blade 模板缓存未清除。

解决

php artisan view:clear
php artisan cache:clear

# Q4: 如何只覆盖部分模板文件?

不需要复制所有文件。系统会先查找 themes/your_theme/ 下的文件,如果不存在则回退到 themes/default/。所以只需要覆盖你需要修改的文件即可。

# Q5: themeFileName 和 themeCode 有什么区别?

  • themeFileName:插件文件夹名称,大驼峰命名,如 Fashion
  • themeCode:模板唯一标识,小写+下划线,如 fashion
  • 两者通过正则自动转换,通常只需要修改 themeFileName

# 十、最佳实践

  1. 只覆盖需要的文件:不要复制所有 default 模板文件,只覆盖需要修改的
  2. 保持代码整洁:遵循项目已有的编码风格
  3. 做好版本管理:每次发布更新时修改 config.json 中的 version
  4. 测试多语言:确保模板在不同语言下显示正常
  5. 响应式设计:确保模板在移动端显示良好
  6. 性能优化:图片使用 WebP 格式,CSS/JS 压缩后发布
  7. 备份数据:启用新模板前备份现有配置数据

# 附录:命名规范速查表

项目 命名规则 示例
插件文件夹 大驼峰 FashionMyTheme
config.json code 小写+下划线 fashionmy_theme
namespace Plugin\文件夹名 Plugin\Fashion
themeCode 小写+下划线 fashion
资源路径 小写+下划线 beike/shop/fashion/css/
Blade 文件 小写+下划线 home.blade.php