npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

element-engin

v1.0.0

Published

基于 Element Plus 的页面搭建引擎:通过 TS/JS 配置驱动生成后台 CRUD 管理页面

Readme

element-engin

基于 Element Plus 的页面搭建引擎:通过 TypeScript / JavaScript 页面配置(definePage)驱动,自动生成具备 增删改查(CRUD) 能力的后台管理页面。

  • 声明式配置:表格、搜索、表单、分页、接口
  • RESTful 默认 + 单操作自定义覆盖
  • 生命周期钩子:before* / after* / onError
  • 默认提交 Loading、成功/失败 Notification
  • 完整 TypeScript 类型

安装

npm install element-engin
npm install vue element-plus   # peerDependencies

在入口引入 Element Plus 样式:

import 'element-plus/dist/index.css'
import 'element-engin/style.css'

快速开始

1. 定义页面配置

// pages/user.ts
import { definePage } from 'element-engin'

export const userPage = definePage({
  page: { title: '用户管理' },
  columns: [
    { prop: 'name', label: '姓名', width: 120 },
    { prop: 'email', label: '邮箱' },
  ],
  search: [
    { prop: 'name', label: '姓名', component: 'Input' },
  ],
  form: {
    create: {
      fields: [
        { prop: 'name', label: '姓名', component: 'Input', required: true },
        { prop: 'email', label: '邮箱', component: 'Input', required: true },
      ],
    },
  },
  apis: {
    resource: '/api/users', // RESTful 自动生成 list/create/update/delete/detail
  },
})

2. 挂载 PageEngine

<script setup lang="ts">
import { PageEngine } from 'element-engin'
import { userPage } from './pages/user'
</script>

<template>
  <PageEngine :config="userPage" />
</template>

3. 本地演示

仓库内置完整 Demo(Mock API + 钩子 + 自定义接口):

npm run demo

详见 examples/demo


RESTful 接口规范

配置 apis.resource 后,未单独声明的操作按 RESTful 默认推导:

| 操作 | Method | URL | 入参通道 | |------|--------|-----|----------| | list | GET | {resource} | query | | create | POST | {resource} | body | | update | PUT | {resource}/:id | body | | delete | DELETE | {resource}/:id | query | | detail | GET | {resource}/:id | query |

  • 主键默认字段名 id,通过 apis.idField 修改;URL 中 :id 自动替换为行数据对应字段值
  • 任意操作可 单独覆盖,不影响其他操作:
apis: {
  resource: '/api/users',
  create: {
    url: '/api/custom/create-user',
    method: 'POST',
    transformParams: ({ formData }) => ({ ...formData }),
  },
}

未配置且无 resource 可推导的接口,对应 UI 能力自动隐藏(如无 delete 则不显示删除按钮)。


transformParams

为单个 CRUD 接口配置入参转换函数,在请求发出前执行:

apis: {
  resource: '/api/users',
  list: {
    transformParams: ({ search, pagination }) => ({
      ...search,
      page: pagination?.page,
      pageSize: pagination?.pageSize,
    }),
  },
  update: {
    transformParams: ({ formData, row }) => ({
      id: row?.id,
      ...formData,
    }),
  },
}

上下文 TransformParamsContext

| 字段 | 适用操作 | |------|----------| | action | 全部 | | search | list | | pagination | list | | formData | create / update | | row | update / delete / detail |

未配置 transformParams 时引擎使用内置默认:list 合并 search + 分页;create/update 使用 formData。


responseMapping

从接口响应中提取数据,路径以 . 分隔:

apis: {
  resource: '/api/users',
  list: {
    responseMapping: { list: 'data.list', total: 'data.total' },
  },
  detail: {
    responseMapping: { detail: 'data' },
  },
}

未配置时的兜底:listdata.list / 响应数组;detail → 响应体本身。


生命周期钩子

hooks 中定义,按操作类型在请求各阶段触发:

| 钩子 | 时机 | 说明 | |------|------|------| | beforeList / beforeCreate / beforeUpdate / beforeDelete | 请求发出前 | 返回 false 可中断请求 | | afterList / afterCreate / afterUpdate / afterDelete | 请求成功后 | 可访问 response | | onError | 任意请求失败 | 与默认错误提示配合使用 |

hooks: {
  afterList: ({ response, engine }) => {
    console.log('列表加载完成', response)
  },
  beforeDelete: ({ row }) => {
    return row?.status !== 'locked' // false 阻止删除
  },
  afterDelete: ({ row, engine }) => {
    engine.showMessage({ type: 'success', message: `已删除 ${row?.name}` })
  },
  onError: ({ action, error }) => {
    console.error(action, error)
  },
}

错误提示职责:

  • create / update 失败:默认走 form.*.notification.error(6.10),onError 做日志/埋点等副作用
  • list / delete / detail 失败:默认 error Notification 由 onError 路径统一展示,可通过 notification.list.error 等配置

HookContext 常用字段: actionparamsresponserowformDataerrorengine


EngineInstance

钩子与 transformParams 中通过 ctx.engine 调用:

| 方法 | 说明 | |------|------| | refreshList() | 重新加载列表 | | openDialog(mode, row?) | 打开新增/编辑弹窗(编辑走 detail 回显流程) | | closeDialog() | 关闭弹窗 | | getSearchParams() | 当前搜索条件快照 | | getPagination() | 当前分页快照 | | setSearchParams(params, opts?) | 合并搜索条件,默认回第 1 页并刷新 | | resetSearch(opts?) | 重置搜索为默认值 | | setPagination({ page, pageSize }, opts?) | 更新分页并刷新 | | showNotification(options) | 右上角 Notification | | showMessage(options) | 短提示 Message |


页面配置字段说明

顶层 PageConfig

| 字段 | 必填 | 说明 | |------|------|------| | columns | 是 | 表格列 | | apis | 是 | CRUD 接口(至少配置 resource 或单项接口) | | page | 否 | 标题、路由元信息 | | search | 否 | 搜索区字段(与 FieldConfig 相同) | | form | 否 | 新增/编辑表单 | | pagination | 否 | 分页默认值(pageSize 默认 20) | | notification | 否 | 页面级 Notification 默认 | | hooks | 否 | 生命周期钩子 |

columns 列配置

| 字段 | 说明 | |------|------| | prop / label | 字段名 / 列标题 | | width / minWidth | 列宽 | | sortable / align / fixed | 排序、对齐、固定列 | | formatter | (row, cellValue) => string 单元格格式化 |

search / form.fields 字段配置

| 字段 | 说明 | |------|------| | prop / label | 字段名 / 标签 | | component | Input | Select | InputNumber | Switch | DatePicker(默认 Input) | | required | 必填简写 | | defaultValue | 默认值 | | options | Select 选项 { label, value }[] | | rules | 校验规则 | | placeholder / disabled | 占位、禁用 |

form.create / form.update

| 字段 | 说明 | |------|------| | fields | 表单字段列表 | | title | 弹窗标题 | | labelWidth | 标签宽度 | | submitLoading | 提交 Loading,默认 true | | notification | 成功/失败 Notification(可 enabled: false 关闭) | | useDetail | 编辑时是否调 detail 接口回显,默认 false |

notification 优先级

表单提交成功/失败:form.create|update.notification > notification.create|update > notification 全局 > 内置默认文案。

列表/删除/详情失败:notification.list|delete|detail.error > notification.error > 内置默认。


注入 HTTP 客户端

默认使用内置 axios 实例。宿主项目可注入自己的实例(复用拦截器、baseURL):

import axios from 'axios'
import { setHttpClient } from 'element-engin'

const client = axios.create({ baseURL: '/api' })
setHttpClient(client)

在挂载 PageEngine 之前调用。


导出 API

import {
  definePage,
  PageEngine,
  resolveApis,
  resolvePageVisibility,
  validatePageConfig,
  setHttpClient,
  getHttpClient,
} from 'element-engin'

import type { PageConfig, HookContext, EngineInstance } from 'element-engin'

开发

npm install
npm run typecheck   # 类型检查
npm run test        # 单元测试(157+)
npm run build       # 构建 dist(ESM + CJS + d.ts)
npm run verify:build # 验证 exports / types / ESM / CJS 产物
npm run build:verify # build + verify 一键执行
npm run demo        # 启动示例

License

MIT