# 模板开发
# 快速开始
示例模板仓库:https://github.com/beikeshop/beikeshop-sample-theme
可以先下载示例模板,参考其目录结构和代码进行开发:
# 下载示例模板
git clone https://github.com/beikeshop/beikeshop-sample-theme.git
# 将 SampleTheme 文件夹复制到 beikeshop 的 plugins/ 目录下
# 然后按照本文档说明进行修改和开发
# 一、模板架构概述
BeikeShop 支持以插件形式开发模板主题。相同的功能可以拥有完全不一样的用户界面。
# 模板加载机制
系统采用以下模板加载策略:
- 优先使用已启用的主题模板
- 如果启用的模板中不存在某个文件,则回退到
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 | 模板唯一标识,小写+下划线命名 | fashion、my_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 保持一致。
开发流程:
从
themes/default复制需要修改的模板文件到你的插件目录:themes/default/home.blade.php → plugins/Fashion/Themes/fashion/home.blade.php只修改你需要自定义的文件,不需要修改的文件保持默认即可
系统加载顺序:
- 先查找
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 | 插件文件夹名称(大驼峰) | Fashion、MyTheme |
themeCode | 自动转换后的 code(小写+下划线) | fashion、my_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 ⚠️ 打包前必须确认编译文件已同步
这是很多开发者容易忽略的关键点!
模板打包发布前,必须确保:
- 编译后的 CSS/JS 文件已经存在于
Static/public/build/目录中 - 这些文件会随插件一起打包,用户安装后才有样式
如何确保:
方式一(推荐):使用
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 安装模板
- 进入后台 → 插件列表
- 找到你的模板插件
- 点击 安装
安装时系统会自动执行:
- 将
Themes/目录下的 Blade 模板复制到themes/your_theme/ - 将
Static/目录下的静态资源复制到public/对应目录
# 5.2 启用模板
- 进入后台 → 设计 → 模板设置
- 找到你的模板,点击 去启用
- 可选:勾选"导入演示数据"(如果模板提供了 Seeders)
- 确认启用
# 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 如何获取首页配置数据
- 在后台设计器中配置好首页布局
- 到数据库
settings表,查找name = 'design_setting'的记录 - 复制
value字段的 JSON 数据 - 使用工具将 JSON 转为 PHP 数组:https://uutool.cn/json2php/
- 将转换后的数组放入
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.png和theme.jpg已替换为自己的素材 - [ ]
config.json信息完整准确 - [ ]
Bootstrap.php命名空间正确 - [ ] 模板文件路径正确(
Themes/your_theme/) - [ ] 测试安装、启用、切换功能正常
# 8.2 打包
将插件文件夹打包为 ZIP 压缩包:
cd plugins
zip -r Fashion.zip Fashion/
# 8.3 发布
- 登录 BeikeShop 官网
- 进入个人中心 → 插件市场
- 上传 ZIP 包发布
- 其他用户可在后台插件市场购买并安装
# 九、常见问题
# Q1: 模板安装后没有样式?
原因:编译后的 CSS/JS 文件没有包含在插件的 Static/public/build/ 目录中。
解决:
- 确保
webpack.mix.js中的模板编译代码已取消注释 - 运行
npm run prod进行编译 - 确认
plugins/YourTheme/Static/public/build/目录下有编译后的文件
# Q2: 修改了 SCSS 但前台没有变化?
原因:没有重新编译或编译后没有刷新缓存。
解决:
- 开发阶段使用
npm run watch监听自动编译 - 修改后等待几秒自动编译完成
- 刷新浏览器(可能需要强制刷新 Ctrl+Shift+R)
# Q3: 模板文件修改后没有生效?
原因:Blade 模板缓存未清除。
解决:
php artisan view:clear
php artisan cache:clear
# Q4: 如何只覆盖部分模板文件?
不需要复制所有文件。系统会先查找 themes/your_theme/ 下的文件,如果不存在则回退到 themes/default/。所以只需要覆盖你需要修改的文件即可。
# Q5: themeFileName 和 themeCode 有什么区别?
themeFileName:插件文件夹名称,大驼峰命名,如FashionthemeCode:模板唯一标识,小写+下划线,如fashion- 两者通过正则自动转换,通常只需要修改
themeFileName
# 十、最佳实践
- 只覆盖需要的文件:不要复制所有 default 模板文件,只覆盖需要修改的
- 保持代码整洁:遵循项目已有的编码风格
- 做好版本管理:每次发布更新时修改
config.json中的version - 测试多语言:确保模板在不同语言下显示正常
- 响应式设计:确保模板在移动端显示良好
- 性能优化:图片使用 WebP 格式,CSS/JS 压缩后发布
- 备份数据:启用新模板前备份现有配置数据
# 附录:命名规范速查表
| 项目 | 命名规则 | 示例 |
|---|---|---|
| 插件文件夹 | 大驼峰 | Fashion、MyTheme |
| config.json code | 小写+下划线 | fashion、my_theme |
| namespace | Plugin\文件夹名 | Plugin\Fashion |
| themeCode | 小写+下划线 | fashion |
| 资源路径 | 小写+下划线 | beike/shop/fashion/css/ |
| Blade 文件 | 小写+下划线 | home.blade.php |