🛠️ 模块安装与运维
模块 module.json 描述模块包,真实安装状态由 system_modules 表决定。本页集中讲安装、启停、卸载、运行包以及自动发现规则。如果你想看 module.json 字段或 publish-manifest.json 写法,去 模块配置 和 模块资源发布。
🎯 本页目标
读完本章节后,应能掌握:
- 模块从安装到运行所经历的完整流程。
- 安装、覆盖安装、启用、停用、卸载几条命令在效果上的差异。
- 何时该重新执行
module:build-runtime,运行包与本地构建如何协作。 - 框架按目录约定自动发现路由、Provider、装修组件的规则。
- 新增模块时推荐的初始目录结构。
🧭 模块安装
安装模块可以通过两种方式进行
1、通过后台 应用中心 安装模块;
2、通过命令行安装模块。
文件权限要求
模块安装、覆盖安装、卸载和删除都会写入或删除项目目录中的文件。无论从后台 应用中心 操作,还是执行 php artisan module:* 命令,都需要确保实际执行命令的系统用户具备对应目录权限。
常见需要写入或删除的目录包括:
| 路径 | 用途 |
|---|---|
frontend/admin | 发布或覆盖模块 Admin 源码、生成 Admin 模块扩展文件 |
frontend/uniapp | 发布或覆盖模块 uni-app 源码、更新 pages.json 和模块装修入口 |
public/modules | 发布或删除模块 Admin / H5 运行包 |
modules/{Module} | 删除模块文件时需要移除模块目录 |
生产环境建议统一使用 Web / PHP 运行用户执行模块命令,例如:
sudo -u www php artisan module:install {Module}如果曾经使用 root 或其他用户执行过安装、构建、复制文件,后续通过后台 应用中心 操作时可能因为文件所有者不一致出现 Permission denied、目录不可写、发布资源无法覆盖或卸载后文件残留。此时需要先修正目录所有者和权限,再重新执行模块操作。
如要通过命令行可使用下面的 Artisan 命令 安装模块:
# 安装模块:执行模块迁移、Seeder、资源发布,写入安装记录并启用模块
php artisan module:install {Module}适用场景:
- 首次安装模块。
- 模块业务表已经存在,但前端发布资源目录不存在。
- 模块卸载后需要重新安装,且发布目标目录已经被清理。
如果发布目标已经存在,需要显式覆盖:
# 覆盖安装:允许覆盖已发布的 admin / uni-app 模块资源
php artisan module:install {Module} --force适用场景:
- 模块已经安装过,前端资源目录仍然存在。
- 模块已安装,仍需要把
Resources中的新版本前端源码重新发布到主工程。 - 模块 Resources 有更新,需要重新发布到主工程。
--force 只影响资源发布覆盖,不会清空模块业务表,也不会删除业务数据。
安装流程会依次处理:
- 读取
modules/{Module}/module.json。 - 检查
dependencies,例如System。 - 执行
modules/{Module}/Database/Migrations下的模块迁移。 - 执行
Modules\{Module}\Database\Seeders\{Module}DatabaseSeeder。 - 按
Resources/publish-manifest.json清理历史发布目录。 - 发布资源清单中声明的 admin、uni-app 资源。
- 写入或更新
system_modules安装记录,并把status设为1。 - 刷新模块运行时缓存,包括模块注册、路由发现、MCP 工具发现等。
- 重新生成前端扩展配置,例如 admin 链接项,并把 uni-app 页面片段合并到
pages.json。
已安装模块可以单独启用或停用:
# 启用模块:保留安装记录,把 system_modules.status 写为 1
php artisan module:enable {Module}
# 停用模块:保留安装记录,把 system_modules.status 写为 0
php artisan module:disable {Module}启用、停用模块会刷新模块运行时缓存。模块中的 Controller、Service Provider、MCP Tool、AI Tool 只有在模块启用后才会进入运行时。
查看模块路由是否生效:
# 查看后台模块路由是否已注册,{slug} 来自 module.json.slug
php artisan route:list --path=adminapi/{slug}
# 查看用户端模块路由是否已注册,{slug} 来自 module.json.slug
php artisan route:list --path=api/{slug}🧹 卸载命令
默认卸载:
# 卸载模块:移除发布资源、菜单和前端扩展,并删除 system_modules 安装记录
php artisan module:uninstall {Module}默认卸载会:
- 删除安装器发布过的 admin、uni-app 资源。
- 移除模块菜单和角色菜单关系。
- 从 uni-app
pages.json中移除模块页面。 - 删除
system_modules中的模块安装记录。 - 保留模块业务数据表。
如需连同模块迁移一起回滚,必须显式声明:
# 删除模块数据结构:在默认卸载基础上回滚模块迁移,可能删除模块业务表
php artisan module:uninstall {Module} --drop-data--drop-data 会回滚模块迁移,可能删除业务数据表。包含订单、支付、账户余额、审批记录等敏感业务数据的模块,生产环境应优先使用默认卸载,谨慎执行 --drop-data。
命令影响对比:
| 命令 | 发布资源 | 菜单与权限 | 安装记录 / 启用状态 | 业务表与数据 |
|---|---|---|---|---|
module:install {Module} | 目标不存在时发布 | 执行 Seeder / 安装器 | 写入记录并设为 1 | 已执行迁移不会重复创建,已有数据保留 |
module:install {Module} --force | 覆盖发布 | 执行 Seeder / 安装器 | 写入记录并设为 1 | 已执行迁移不会重复创建,已有数据保留 |
module:enable {Module} | 不重新发布 | 不重新执行 Seeder | 写为 1 | 保留 |
module:disable {Module} | 不删除资源 | 不删除菜单 | 写为 0 | 保留 |
module:uninstall {Module} | 删除已发布资源 | 删除模块菜单和角色菜单关系 | 删除记录 | 保留业务表和数据 |
module:uninstall {Module} --drop-data | 删除已发布资源 | 删除模块菜单和角色菜单关系 | 删除记录 | 回滚模块迁移,可能删除业务表和数据 |
System 是基础模块,不能卸载。
卸载后如需彻底删除模块文件,可以使用应用中心的“删除模块”操作,或执行:
# 删除模块目录:要求模块已经卸载,实际删除 modules/{Module}
php artisan module:delete {Module}卸载、删除模块和清理残留安装记录都会刷新模块运行时缓存。正常通过应用中心或 module:* 命令管理模块时,不需要额外执行 optimize:clear 才能让 MCP 工具列表感知模块启停。
如果生产环境使用 Octane、Swoole、长时间运行的队列 Worker,模块文件变更后仍应按部署方式重启对应常驻进程。常驻进程内存中的类加载状态不属于 Laravel 配置缓存,不能只依赖 optimize:clear。
🚀 运行时与运行包关系
模块的 admin 页面在生产环境有两种加载路径:
- 本地构建:模块 admin 源码已经在最近一次
npm run admin:build时被一起打包进主 SPA。 - 模块运行包:模块单独发布的 JS 入口,部署在
public/modules/{module}/admin/*,由 Admin 启动时按admin.runtime_components注册并按需加载。
Admin 加载页面时优先使用本地组件,本地不存在时回退到运行包。这样做的目的是:
- 在生产服务器安装新模块时,可以在不重新打包 Admin 的情况下直接使用模块后台页面。
- 后续重新打包 Admin 后,本地构建自然优先,不留陈旧入口。
构建运行包命令
# 构建指定模块的 Admin 运行包:输出到 modules/{Module}/Resources/runtime/admin,并更新 publish-manifest.json
php artisan module:build-runtime {Module}
# 显式声明构建 Admin 运行包,效果与默认命令一致
php artisan module:build-runtime {Module} --admin
# 构建全部包含 Admin 页面源码的非 System 模块
php artisan module:build-runtime --all
# 也可以用 all 作为模块名构建全部模块运行包
php artisan module:build-runtime all
# 只构建运行包文件,不更新 publish-manifest.json
php artisan module:build-runtime {Module} --no-manifest执行该命令前,管理端依赖需要已经安装:
# 首次构建运行包前,在管理端目录安装依赖
cd frontend/admin
npm install何时需要重新生成运行包
出现以下情况时通常需要重新执行 module:build-runtime:
- 修改了模块
Resources/admin下的源码或路由组件。 - 修改了
admin.runtime_components入口映射,或新增了运行包组件。 - 模块新增 / 调整了由主 Admin 共享的全局组件(例如 FooterBar 这类需要在 runtime-shared 中暴露的组件)。
- 部署到生产服务器后,发现模块菜单点击进去页面空白或 404。
开发期已经在主 Admin 工程内调试通过的页面不强制重新生成运行包;运行包主要服务于“线上已部署 Admin,但新装/更新模块没有重打包”的场景。
与安装器的关系
安装器会按 publish-manifest.json 的 files 把 runtime/admin、runtime/h5 复制到 public/modules/{module}/admin、public/modules/{module}/h5。模块作者只要在打包阶段把运行包产物放到 Resources/runtime 下,安装时就会被发布到正确目录。
如果模块只有传统源码、没有运行包,仍然可以正常工作 —— 此时模块只能通过重新构建 Admin 才能在生产生效。
🔍 自动发现规则
模块运行以目录约定为主:
| 能力 | 自动发现规则 |
|---|---|
| 模块启动注册器 | Modules\{Module}\Providers\{Module}ServiceProvider |
| Admin 控制器 | modules/{Module}/Http/Controllers/Admin |
| Api 控制器 | modules/{Module}/Http/Controllers/Api |
| Admin 模块装修组件 | frontend/admin/src/views/{Module}/component/decoration/widgets/*/index.ts |
| Admin 路由前缀 | /adminapi/{slug} |
| Api 路由前缀 | /api/{slug} |
目录不存在时会自动跳过,不需要创建空目录占位。
🧭 新增模块建议
新增模块时推荐先创建结构:
modules/Shop
├─ module.json
├─ Providers/
│ └─ ShopServiceProvider.php
├─ Database/
│ ├─ Migrations/
│ ├─ Seeders/
│ └─ Support/
├─ Http/
│ └─ Controllers/
│ ├─ Admin/
│ └─ Api/
└─ Resources/
├─ admin/
├─ uniapp/
└─ publish-manifest.json模块自己的菜单、权限、默认配置应放到模块 Seeder 或安装器中,详见 模块配置 / 菜单与初始数据。Resources/publish-manifest.json 写法详见 模块资源发布。
