插件
InsightSite 的插件分两类,都在「后台 → 插件」统一管理:
| 运行时插件 | 代码包插件 | |
|---|---|---|
| 形态 | 一个 JSON 清单 nuxtcms.plugin.json | 一个 Nuxt Layer(npm 包 / Git 仓库) |
| 能力 | 设置项、注入代码、CSP 白名单、事件 Webhook、定时任务 | 以上全部 + 页面、组件、API、数据库表 |
| 安装 | 后台在线安装,无需重新构建,所有部署形态通用 | plugin.mjs add 后重新构建部署 |
| 典型 | 统计代码、在线客服、群机器人通知、搜索推送 | 会员、商城、表单设计器 |
官方插件中心
官网(https://insightme.top,NUXT_PLUGIN_HUB_URL 可改)就是插件中心,提供一条龙服务:
- 注册账号:官网
/account/register。 - 绑定站点:官网「账号 → API 令牌」创建令牌,粘贴到站点「后台 → 插件 → 账号与授权」。令牌只保存在服务端。
- 在线下载安装:插件市场里点「安装」,免费插件直接装好;有新版本时显示「更新到 vX」。
- 积分购买:付费插件标价为积分,点「N 积分购买」即扣积分并为当前域名签发授权。积分暂不支持在线支付,联系管理员充值。
- 联系授权:需要多站点授权、试用或报价,点「联系授权」,留言连同域名提交到官网后台,由管理员处理并发放授权码。
- 授权关联:授权绑定域名(
NUXT_PUBLIC_SITE_URL的 host)。也可以在插件设置里手动填写授权码。授权每天由 cron 复核一次;插件中心暂时连不上时保留上次结果,不会让正常运行的站点突然失效。
未授权的付费插件可以先安装和配置,但不会生效(不注入代码、不触发 Webhook)。
默认授权:插件中心管理员在「插件中心 → 概览 → 自有站点」登记的域名(例如自己公司的站点),安装付费插件时自动获得授权码,无需购买;已安装但没有授权码的付费插件会在校验或每日复核时自动领取。
插件中心不可达时(内网、离线),市场自动切换为框架内置的官方插件(plugins/official/*.json),免费插件照常安装。
使用量统计:站点每天最多向插件中心报告一次"正在运行"(后台检查更新、cron、upgrade.mjs 部署后),用于官网首页的"站点在用"数字。只发送 NUXT_PUBLIC_SITE_URL 的域名和框架版本号;插件中心只保存域名的 SHA-256 哈希,并在首次收到时访问该站的 /api/health 核实。本地地址(localhost)从不上报;设置 NUXT_HUB_TELEMETRY=false 即可关闭。
运行时插件清单
{
"id": "my-plugin",
"name": { "zh": "我的插件", "us": "My plugin" },
"version": "1.0.0",
"description": { "zh": "做什么用的", "us": "What it does" },
"requires": ">=1.3.0",
"category": "analytics",
"icon": "i-lucide-bar-chart-3",
"license": "free",
"settings": [
{ "key": "siteId", "label": "站点 ID", "type": "text", "required": true }
],
"inject": [
{ "position": "head", "when": "siteId", "html": "<script src=\"https://cdn.example.com/a.js?id={{settings.siteId}}\" async></script>" }
],
"csp": { "script-src": ["https://cdn.example.com"] },
"webhooks": [
{ "event": "contact.created", "url": "https://hooks.example.com/x", "body": { "text": "{{event.name}}:{{event.message}}" } }
],
"tasks": [
{ "name": "每日同步", "cron": "0 3 * * *", "url": "{{site.url}}/api/cron/xxx", "headers": { "Authorization": "Bearer {{cronSecret}}" } }
]
}
| 字段 | 说明 |
|---|---|
id | 小写字母、数字、短横线,全局唯一 |
name / description / label / help | 字符串或 { "zh": "...", "us": "..." } |
version | semver;市场据此提示更新 |
requires | 需要的最低 InsightSite 版本 |
license / priceCredits | free 或 paid(付费插件只能从插件中心安装) |
settings[].type | text textarea number boolean select secret url;secret 不回显给浏览器 |
inject[] | position: head / body;scope: public(默认,只在前台)/ all;when: 某个设置为真时才注入;raw: true 表示设置值本身就是 HTML(不转义) |
csp | 注入代码需要的外部域名。只有真正注入了代码的页面才会放开,没装插件的站点保持严格策略 |
webhooks[] | event 见下表;url / headers / body 都可以用模板 |
tasks[] | 安装时写入「定时任务」,由 cron 调度器执行;插件停用时任务一起停用,卸载时删除 |
模板变量
{{settings.xxx}}、{{site.url}}、{{site.name}}、{{event.xxx}}(Webhook)、{{cronSecret}}(任务)。注入 HTML 时变量会做 HTML 转义,防止设置值破坏页面。
事件
| 事件 | 时机 | 载荷 |
|---|---|---|
contact.created | 前台提交联系表单 | name email phone message createdAt |
form.submitted | 访客提交后台「表单」里建的表单 | form(标识)name id locale data(字段标识 → 答案) |
content.published | 文章 / 页面 / 产品 / 内容类型条目发布(含定时发布到点) | kind id title slug locale status url(条目另有 collection) |
content.updated | 内容被修改 | 同上 |
content.deleted | 内容被删除 | 同上 |
plugin.installed | 插件安装或更新 | id version updated |
order.created | 商城新订单 | number status total totalFormatted currency email name phone paymentMethod shippingMethod items url |
order.paid | 付款确认(在线支付或后台标记已付款) | 同 order.created |
order.status_changed | 订单状态变化 | 同上 + previousStatus |
comment.created | 博客新评论(非垃圾) | id postId postTitle status name email content url |
subscriber.created | 邮件订阅 | email name status locale source |
saas.payment.paid | SaaS 套件收到一笔付款(套餐购买、订阅续费) | number plan period amount amountFormatted currency provider email name url |
system.error | 服务器 5xx 错误(同一路由和错误 10 分钟内只发一次,每小时最多 20 条) | status method path message at |
Webhook 在响应之后执行(Cloudflare 上用 waitUntil),失败只记日志,不影响用户操作。
本地调试
「后台 → 插件 → 开发者」可粘贴或上传清单直接安装,修改后再次导入即覆盖(设置保留)。
代码包插件
一个普通的 Nuxt Layer,根目录放 nuxtcms.plugin.json("kind": "package"),在 Nitro 插件里注册:
// server/plugins/my-plugin.ts
import manifest from '../../nuxtcms.plugin.json'
export default defineNitroPlugin(() => {
defineCmsPlugin(manifest, ({ on }) => {
on('content.published', async (payload) => {
// 插件停用或未授权时不会被调用
})
})
})
代码包插件给后台加菜单(app.config.ts):
export default defineAppConfig({
nuxtcms: { adminNav: [{ label: '我的插件', icon: 'i-lucide-puzzle', to: '/admin/my-plugin', adminOnly: true, after: 'plugins' }] },
})
后台菜单分两级:主菜单(内容、产品、用户与会员、SEO 与营销、扩展功能、系统)下是子菜单。菜单项默认归入 after 指向的那一项所在的主菜单;用 group 指定主菜单(content、products、users、growth、extensions、system),或用 adminNavGroups 新增一个主菜单(官方商城插件即如此):
nuxtcms: {
adminNavGroups: [{ key: 'crm', labelKey: 'crm.admin.menu', icon: 'i-lucide-contact', order: 35 }],
adminNav: [{ labelKey: 'crm.admin.leads', icon: 'i-lucide-inbox', to: '/admin/crm/leads', group: 'crm' }],
}
站点不用的内置菜单可以用 adminNavHide 隐藏(填菜单键名,如 posts、media、products);外部页面(例如站点自己的旧后台)用 external: true 加入菜单,to 原样使用、不加语言前缀,target: '_blank' 在新标签打开;labels 按界面语言命名菜单项或主菜单:
nuxtcms: {
adminNavHide: ['posts', 'pages', 'media', 'products'],
adminNavGroups: [{ key: 'store', label: 'Store', labels: { cn: '商城后台', us: 'Store' }, icon: 'i-lucide-store', order: 5 }],
adminNav: [{ to: '/admin/orders', labels: { cn: '订单', us: 'Orders' }, external: true, target: '_blank', group: 'store' }],
}
后台左上角的名称和 logo 用 adminBrand: { name: 'JIHE-TCM', logo: '/assets/logo.png' } 设置(默认 InsightSite)。后台配色可在站点 main.css 里改 cms-admin-sidebar、cms-admin-brand、cms-admin-header、cms-admin-main 以及菜单的 cms-nav-link / cms-nav-group(is-active)。
只有一个可见子项的主菜单直接显示为该菜单项。站点自定义了后台布局时,把菜单链接列表交给 <AdminSidebarNav :links="visibleLinks" /> 即可得到同样的两级菜单(可用 link-class、active-class、inactive-class 套用站点自己的样式)。
在 API 里判断是否可用、读取设置:
export default defineEventHandler(async (event) => {
if (!(await isPluginActive(event, 'my-plugin'))) throw createError({ statusCode: 404 })
const settings = await getPluginSettings(event, 'my-plugin')
// ...
})
安装 / 卸载(在站点项目目录执行,然后重新构建部署):
node node_modules/nuxtcms/scripts/plugin.mjs list
node node_modules/nuxtcms/scripts/plugin.mjs add my-plugin --license NCMS-XXXX # 从插件中心按 id 安装
node node_modules/nuxtcms/scripts/plugin.mjs add github:you/nuxtcms-plugin-x#v1.0.0
node node_modules/nuxtcms/scripts/plugin.mjs remove my-plugin
CLI 会用项目的包管理器安装依赖,并记录到 nuxtcms.plugins.json;基座的 nuxt.config.ts 自动 extends 其中的包。带 --license 时授权码随构建下发,首次访问后台或 cron 运行时自动绑定并校验。
官方 package 插件
shop(付费)、saas(付费)、ai(付费)、builder(免费)、marketing(免费)和 blog(免费)随框架一起发布(plugins/shop、plugins/saas、plugins/ai、plugins/builder、plugins/marketing、plugins/blog),添加时无需下载:
node node_modules/nuxtcms/scripts/plugin.mjs add shop,重新构建并部署即可。详见 商城、SaaS 套件、AI 助手、区块页面搭建、营销工具 与 博客增强。
扩展点
package 插件和站点无需复制基座文件即可扩展:
| 扩展点 | 用法 |
|---|---|
| 界面插槽 | 基座页面里的 <CmsSlot name> 渲染 app.config 中 nuxtcms.slots 注册的组件,如 { 'product:aside': { ShopBuyBox: 10 } }(数字为顺序,false 为隐藏)。可用插槽:header:actions、app:end、post:meta、post:before-content、post:after-content、post:footer、product:aside、product:after-media、product:after-content、product-card:footer、editor:sidebar、account:main、account:aside(SaaS 用户中心,ctx.user)、account:nav(用户中心标签栏)、pricing:after(价格页底部)、page:blocks(页面模板中替代正文显示,ctx.page)。插槽组件须为全局组件(app/components/global/),ctx 以 props 传入(post、product,编辑器里为 type 与 contentId)。 |
| 积分 | 收费的插件调用 cmsCredits(event, 'check' / 'spend', 数量, 原因),管理余额的插件(SaaS 套件)监听 Nitro 钩子 cms:credits 作答;没有提供者时返回 503 credits.unavailable。 |
| 区块中的插件组件 | 在 app.config 的 nuxtcms.builderWidgets 中登记全局组件({ MyWidget: 'i18n 名称键' }),区块编辑器的「插件组件」区块即可选用;未登记的名称不会渲染。 |
| 编辑器表单 | editor:sidebar 中的组件 inject('cmsEditor') 得到 state(标题、正文、SEO 字段等),可直接填入建议。 |
| 编辑器保存钩子 | editor:sidebar 中的组件注入 cmsEditor 并调用 onSave(({ id, slug, type }) => ...),在文章/产品本身保存成功后执行。 |
| 公开数据 | 服务端 onPublicContent((items, { event, kind, detail }) => ...) 在缓存前装饰 /api/public/products、/api/public/posts 与 /api/public/pages/:slug(kind 为 page)的响应。产品页会把 offers / sku 写入 JSON-LD,有 hideInquiry 时隐藏询盘卡片;文章页有 related 时优先使用。响应会被缓存,只能放目录数据。 |
| 自有数据表 | 每种方言一份 Drizzle schema,配合 ensurePluginSchema(event, id, ddl):每个实例只执行一次幂等 DDL({prefix} 为表前缀)。官方插件用 node scripts/plugin-ddl.mjs <id> 生成 DDL。 |
| 事件 | 新增 order.created、order.paid、order.status_changed、comment.created、subscriber.created、saas.payment.paid。 |
在框架仓库里开发插件:NUXT_PACKAGE_PLUGINS=./plugins/shop,./plugins/blog,./plugins/saas nuxt dev,nuxt dev 不校验授权。
插件页面位于 node_modules/nuxtcms/plugins,站点 main.css 需要 @source "../../../node_modules/nuxtcms/plugins";(upgrade.mjs 会自动补上)。
发布到官方插件中心
把清单(运行时插件)或包地址(代码包插件)提交给管理员,在官网后台「插件中心 → 插件」上架、定价(积分)。站点下次打开插件市场即可看到。