{"id":"6959beeb-28cd-4e0f-9388-950216e6bef8","slug":"es-plus","kind":"mcp","name":"es-plus","summary":"基于 Vue 3 + Element Plus 的企业级中后台 CRUD 组件库 — 配置化驱动表单、表格、弹窗全链路联动","owner":"liujiaao","repoUrl":"https://github.com/liujiaao/es-plus","license":"MIT","licenseTier":"permissive","trust":"community","stars":14,"match":null,"fewStars":false,"format":"mcp","createdAt":"2026-05-15T14:03:27.000Z","addedAt":"2026-11-08T04:48:30.038Z","logoUrl":"https://avatars.githubusercontent.com/u/25057724?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["developer-tools"],"tags":["admin","component-library","config-driven","crud","dialog","element-plus","enterprise","form"],"runtime":"node","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-11-08T04:49:52.155Z","sample":false,"url":"https://conduits.dev/tools/es-plus","language":"JavaScript","transports":["stdio"],"install":{"npm":"@es-plus/mcp-server"},"requirements":{"env":[{"name":"ESPLUS_MCP_PROFILE","secret":false,"required":false,"description":"Tool surface to expose: `full` (default, all tools) or `front-door` (the preferred entries — generate_scene / generate_composition / generate_crud plus single-surface fragments, validate/refine/ingest"}],"upstreamMayCharge":false},"tools":null,"readme":"# ES-Plus\n\n让 AI 生成的 CRUD 页面**可以直接合进代码库**：LLM 只写一份 JSON 配置，ES-Plus 负责 Schema 校验 + 确定性编译，一次产出 **Vue 3 + Element Plus / Vue 2 + Element UI / Vue 3 + Ant Design Vue** 三套可运行代码 —— 同一份配置、三端一致、可复现。\n\n中文 | [English](./README.en.md)\n\n[![@es-plus/vue3](https://img.shields.io/npm/v/%40es-plus%2Fvue3.svg?label=%40es-plus%2Fvue3)](https://www.npmjs.com/package/@es-plus/vue3)\n[![@es-plus/vue2](https://img.shields.io/npm/v/%40es-plus%2Fvue2.svg?label=%40es-plus%2Fvue2)](https://www.npmjs.com/package/@es-plus/vue2)\n[![@es-plus/adapter-antdv](https://img.shields.io/npm/v/%40es-plus%2Fadapter-antdv.svg?label=%40es-plus%2Fadapter-antdv)](https://www.npmjs.com/package/@es-plus/adapter-antdv)\n[![@es-plus/core](https://img.shields.io/npm/v/%40es-plus%2Fcore.svg?label=%40es-plus%2Fcore)](https://www.npmjs.com/package/@es-plus/core)\n[![license](https://img.shields.io/npm/l/%40es-plus%2Fvue3.svg)](https://www.npmjs.com/package/@es-plus/vue3)\n[![GitHub stars](https://img.shields.io/github/stars/liujiaao/es-plus?style=social)](https://github.com/liujiaao/es-plus)\n[![heldout accuracy](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fliujiaao%2Fes-plus%2Fmaster%2F__tests__%2Fgolden%2Flast-accuracy-badge.json)](./docs/internal/wave-2-production-trust-design.md)\n[![heldout zero-edit](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fliujiaao%2Fes-plus%2Fmaster%2F__tests__%2Fgolden%2Flast-accuracy-badge-scoped.json)](./docs/internal/wave-2-production-trust-design.md)\n\n<sub>两个徽章都来自夜间 Layer-2 评估对 golden 语料**留出集**（few-shot 未见域、已排除近变体）的实测，**不是营销数字**。徽章 label 里标着测量所用的模型：读数随模型变化，**不同模型之间不可横向比较**，也不与历史读数拼成一条曲线。<br>\n第一个是**门禁口径**：in-schema intent 命中率 = 「零编辑 **∨** 3 轮内收敛」—— 模型首轮就给出可零改合并的配置，**或**在至多 3 轮自然语言修正内收敛到同一份配置，都算命中（[定义](docs/internal/wave-2-production-trust-design.md)）。<br>\n第二个是其中更严的一半：**只算首轮零编辑**，不给收敛机会，用来分辨「一次就对」和「改几轮才对」。<br>\n语料目前 227 例（留出 203 例），是回归哨兵而非统计显著的 benchmark，提升靠补语料而非调口径；门禁目标 ≥95%，当前实测以上方徽章为准（由夜间 eval 从 `__tests__/golden/last-accuracy.json` 生成）。</sub>\n\n**[在线文档](https://main.esplus-ai.com/)** · **[Playground](https://main.esplus-ai.com/#/playground)** · **[AI CRUD 生成器](https://main.esplus-ai.com/#/ai-crud)** · **[更新日志](https://github.com/liujiaao/es-plus/releases)** · **[v1.4 迁移指南](./docs/migrate-v1.4.md)**\n\n**同一份配置的三个渲染端，各自一个线上站**：[Vue 3 + Element Plus](https://main.esplus-ai.com/) · [Vue 3 + Ant Design Vue](https://antdv.esplus-ai.com/) · [Vue 2 + Element UI](https://esui.esplus-ai.com/) —— 三个站都跑在线上，示例由各自站点的构建与守卫覆盖。\n\n> **v1.4.0 起重命名**：`es-plus-ui` 已重命名为 [`@es-plus/vue3`](https://www.npmjs.com/package/@es-plus/vue3)，同时新增 Vue 2 渲染器 [`@es-plus/vue2`](https://www.npmjs.com/package/@es-plus/vue2) 与框架无关的 [`@es-plus/core`](https://www.npmjs.com/package/@es-plus/core)。原 `es-plus-ui` 包继续作为 stub 包工作，详见 [迁移指南](./docs/migrate-v1.4.md)。\n\n---\n\n## 为什么选择 ES-Plus\n\n2026 年用 AI 生成前端早不稀奇，稀奇的是**敢不敢把生成结果直接合并**。多数 AI codegen 是「凭感觉」：每次输出都不一样、对不上你的设计系统、没人替它校验 —— 于是你还得逐行 review、改、再 review。\n\nES-Plus 把这件事反过来做：**让 LLM 只做它擅长的语义推理（需求 → 一份配置），把「生成正确代码」这件必须确定的事交给编译器**。\n\n- **LLM 产出配置，不产出代码** —— 通过 MCP 把 Schema/约定交给宿主 LLM（Claude Code / Cursor），它只输出一份 JSON\n- **库做校验** —— zod + JSON Schema 在编译前拦下非法配置，坏配置到不了产物\n- **确定性编译** —— 同一份配置永远编译出字节级相同的三端代码，golden 用例语料 × 多类确定性不变量 + esbuild 真语法解析在 CI 守着\n- **三端一致** —— 一份配置通吃 Vue 3 + Element Plus、Vue 2 + Element UI、Vue 3 + Ant Design Vue\n\n而且它首先是个**好用的 CRUD 库**：中后台系统 80% 的页面是 CRUD —— 表单查询 → 表格展示 → 弹窗编辑。用原生 Element Plus 每个页面需要 200+ 行模板代码，用 ES-Plus 只需 **30 行配置**。\n\n| 传统写法 | ES-Plus |\n|---------|---------|\n| 每个字段 5-8 行 `<el-form-item>` + `<el-input>` | 一行配置 `{ prop, label, formtype }` |\n| 手动 `v-model` 绑定每个字段 | 自动绑定到 `model` |\n| 手动 `@click` 查询 + `resetFields()` 重置 | `triggerEvent: true` 全自动 |\n| 模板声明 `<el-dialog v-model=\"visible\">` | 函数调用 `dialog({ title, render })` |\n| 手动编写分页事件处理 | 分页切换自动触发请求 |\n\n**同一页面、同一功能范围：模板与事件胶水代码减少 76.5%（115 → 27 行），整页非空行减少 40.4%（136 → 81 行）；查询 / 重置 / 翻页 / 取数零事件代码。**\n\n> 数字由 `npm run one-config:gen` 从 `docs/brand/one-config/{native,esplus}.vue` 实测得出，\n> 由 `npm run check:site-claims` 守住院线。口径：模板区行数 + `handle*`/`fetch*` 事件与取数函数行数。\n\n---\n\n## 核心特性\n\n- **配置驱动** — JSON 配置生成表单、表格、弹窗，替代大量模板代码\n- **全链路联动** — EsForm 嵌套在 EsTable 中，查询/重置/分页全自动联动\n- **编程式弹窗** — `useDialog()` 命令式调用，JSX 渲染，表单验证集成\n- **16 种表单控件** — Input、InputNumber、Select、DatePicker、TimePicker、Cascader、TreeSelect、Autocomplete、Radio、Checkbox、Switch、Slider、Rate、ColorPicker、Transfer、Upload\n- **自适应高度** — ResizeObserver 自动重算表格高度\n- **跨页选择** — `cachePageSelection` 分页切换保留勾选\n- **任意后端适配** — `configTableOut` 配置化映射 API 响应字段\n- **权限控制** — `permissionValue` 声明式按钮权限，无需 v-if\n- **国际化** — `labelKey` + 自定义翻译函数，兼容任意 i18n 方案\n- **TypeScript** — 完整类型定义 + 44 个跨渲染器契约类型（CI 强制三端同构导出，数量由 `check:readme` 校验）\n- **AI 原生支持** — 配套 MCP Server 和 CLI：MCP 通过协议把 Schema/约定交给宿主 LLM（Claude Code/Cursor）做语义推理，es-plus 负责约束校验 + 确定性编译成可运行页面\n\n---\n\n## 快速开始\n\n### 一行起步（推荐）\n\n```bash\nnpm create es-plus@latest\n```\n\n交互式选渲染器（Vue 3 + Element Plus / Vue 2 + Element UI / Vue 3 + Ant Design Vue），可选一键写入 MCP（AI 生成）配置，产出一个**装上就能跑**的 CRUD 示例项目（查询表单 + 表格，零后端）。CI 用脚手架 smoke 守着三端 `scaffold → install → build` 全绿。详见 [`create-es-plus`](./packages/create-es-plus/README.md)。\n\n想手动集成到已有项目，继续往下看。\n\n### 安装（Vue 3）\n\n```bash\nnpm install @es-plus/vue3 element-plus @element-plus/icons-vue\n```\n\n### 注册插件（Vue 3）\n\n```typescript\nimport { createApp } from 'vue'\nimport ElementPlus from 'element-plus'\nimport 'element-plus/dist/index.css'\nimport ESPlus from '@es-plus/vue3'\nimport '@es-plus/vue3/dist/style.css'\nimport App from './App.vue'\n\nconst app = createApp(App)\napp.use(ElementPlus)\napp.use(ESPlus)\napp.mount('#app')\n```\n\n### Vue 2 项目？\n\n```bash\nnpm install @es-plus/vue2 element-ui\n# Vue 2.6 还需要 @vue/composition-api\n```\n\n参见 [`@es-plus/vue2` README](./packages/vue2/README.md)，配置 API 与 Vue 3 版本完全一致。\n\n### Ant Design Vue 项目？\n\n```bash\nnpm install @es-plus/adapter-antdv ant-design-vue @ant-design/icons-vue dayjs\n```\n\n```typescript\nimport { createApp } from 'vue'\nimport Antd from 'ant-design-vue'\nimport 'ant-design-vue/dist/reset.css'\nimport ESPlus from '@es-plus/adapter-antdv'\nimport '@es-plus/adapter-antdv/dist/style.css'\n\nconst app = createApp(App)\napp.use(Antd)\napp.use(ESPlus)\napp.mount('#app')\n```\n\n[`@es-plus/adapter-antdv`](./packages/adapter-antdv/README.md) 是 Ant Design Vue 4.x 渲染适配器，**与 `@es-plus/vue3` 共享同一份 JSON 配置 Schema**，配置 API 完全一致，仅底层 UI 组件不同。详见 [adapter-antdv 文档](./packages/adapter-antdv/README.md)。\n\n### 第一个 CRUD 页面\n\n```vue\n<template>\n  <es-table\n    ref=\"tableRef\"\n    :columns=\"columns\"\n    :options=\"options\"\n    v-model:data-source=\"tableData\"\n    v-model:pagination=\"pagination\"\n  >\n    <es-form :model=\"form\" :form-item-list=\"formItems\" :config-btn=\"btns\" />\n  </es-table>\n</template>\n\n<script setup>\nimport { reactive, ref } from 'vue'\n\nconst form = reactive({ name: '', status: '' })\nconst tableData = ref([])\nconst pagination = ref({ current: 1, pageSize: 10, total: 0 })\n\nconst formItems = [\n  { prop: 'name', label: '姓名', formtype: 'Input', span: 6, attrs: { clearable: true } },\n  { prop: 'status', label: '状态', formtype: 'Select', span: 6,\n    dataOptions: [{ label: '启用', value: 1 }, { label: '禁用', value: 0 }] }\n]\n\nconst btns = [\n  { name: '查询', type: 'primary', key: 'query', triggerEvent: true },\n  { name: '重置', key: 'rest', triggerEvent: true }\n]\n\nconst columns = [\n  { prop: 'name', label: '姓名' },\n  { prop: 'status', label: '状态' },\n  { prop: 'operate', label: '操作',\n    btns: [\n      { name: '编辑', type: 'primary', clickEvent: (row) => edit(row) },\n      { name: '删除', type: 'danger', clickEvent: (row) => del(row) }\n    ] }\n]\n\nconst options = {\n  border: true,\n  stripe: true,\n  httpRequest: async (params) => {\n    // 替换为你的 API 调用\n    const res = await fetch('/api/list', { method: 'POST', body: JSON.stringify(params.formParams) })\n    return res.json()\n  },\n  configTableOut: { total: 'total', tableData: 'data', pageSize: 'pageSize', current: 'pageIndex' }\n}\n</script>\n```\n\n> EsForm 嵌套在 EsTable 中，查询/重置/分页全自动联动，**零事件处理代码**。\n\n---\n\n## 联动机制\n\n```\n┌───────────────────────────────────────────────┐\n│  EsTable（通过 provide/inject 提供表格实例）     │\n│  ┌─────────────────────────────────────────┐  │\n│  │  EsForm（自动发现父级 EsTable）           │  │\n│  │  [查询] → 自动调用 table.httpRequest()   │  │\n│  │  [重置] → 重置表单 + 重新查询             │  │\n│  └─────────────────────────────────────────┘  │\n│  ┌─────────────────────────────────────────┐  │\n│  │  表格数据（自动分页）                     │  │\n│  └─────────────────────────────────────────┘  │\n│  ┌─────────────────────────────────────────┐  │\n│  │  分页器（翻页自动触发 httpRequest）       │  │\n│  └─────────────────────────────────────────┘  │\n└───────────────────────────────────────────────┘\n```\n\nEsForm 放在 EsTable 的默认插槽中，通过 Vue 的 provide/inject 自动发现父级表格。按钮配置 `triggerEvent: true` 后，自动调用表格的数据请求方法，无需手动连接。\n\n---\n\n## 组件一览\n\n| 组件 | 说明 | 典型场景 |\n|------|------|---------|\n| **EsForm** | 配置化表单 | 查询表单、弹窗编辑表单、筛选条件 |\n| **EsTable** | 配置化表格 | 数据列表、跨页多选、多级表头 |\n| **useDialog** | 编程式弹窗 | 新增/编辑弹窗、详情查看、嵌套弹窗 |\n| **EsDialog** | 增强弹窗组件 | 拖拽、全屏切换、自定义头部/底部 |\n| **EsCrudPage** | CRUD 页面组件 | 传入 Schema 一键生成完整 CRUD 页面 |\n| **SvgIcon** | SVG 图标 | 图标展示 |\n\n---\n\n## EsForm 表单配置\n\n```typescript\nconst formItems = [\n  // 文本输入\n  { prop: 'name', label: '姓名', formtype: 'Input', span: 6 },\n  // 下拉选择（静态选项）\n  { prop: 'status', label: '状态', formtype: 'Select', span: 6,\n    dataOptions: [{ label: '启用', value: 1 }, { label: '禁用', value: 0 }] },\n  // 日期范围\n  { prop: 'date', label: '日期', formtype: 'datePicker', span: 8,\n    attrs: { type: 'daterange', valueFormat: 'YYYY-MM-DD' } },\n  // 远程数据加载\n  { prop: 'category', label: '分类', formtype: 'Select', span: 6,\n    apiParams: { url: '/api/categories' },\n    callOptionListFormat: (data) => data.map(i => ({ label: i.name, value: i.id })) },\n  // 条件显隐\n  { prop: 'remark', label: '备注', formtype: 'Input', span: 12,\n    attrs: { type: 'textarea' },\n    isHidden: (model) => model.status !== 1 }\n]\n```\n\n### 核心配置项\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `prop` | `string` | 字段名（必填） |\n| `label` | `string` | 标签（必填） |\n| `formtype` | `string` | 控件类型（16 种） |\n| `span` | `number` | 栅格列宽（1-24） |\n| `attrs` | `object` | 透传到 Element Plus 组件 |\n| `dataOptions` | `array` | Select/Radio/Checkbox 选项 |\n| `isHidden` | `(model) => boolean` | 条件显隐 |\n| `render` | `(h, model) => VNode` | 自定义渲染 |\n| `apiParams` | `object` | 远程加载选项数据 |\n| `labelKey` | `string` | i18n 翻译键 |\n\n---\n\n## EsTable 表格配置\n\n```typescript\nconst columns = [\n  { prop: 'name', label: '姓名' },\n  { prop: 'amount', label: '金额', formatter: (row) => `¥${row.amount.toFixed(2)}` },\n  // 自定义渲染\n  { prop: 'status', label: '状态',\n    render: (_, { row }) => h(ElTag,\n      { type: row.status === 1 ? 'success' : 'danger' },\n      () => row.status === 1 ? '启用' : '禁用') },\n  // 操作按钮（prop 必须为 'operate'）\n  { prop: 'operate', label: '操作',\n    btns: [\n      { name: '编辑', type: 'primary', clickEvent: (row) => openForm('编辑', row) },\n      { name: '删除', type: 'danger', clickEvent: (row) => handleDelete(row) }\n    ] }\n]\n\nconst options = {\n  border: true,\n  stripe: true,\n  highlightCurrentRow: true,\n  httpRequest: fetchList,\n  configTableOut: { total: 'total', tableData: 'records', pageSize: 'size', current: 'page' },\n  rowkey: 'id',\n  cachePageSelection: true\n}\n```\n\n### 后端响应映射\n\n后端返回 `{ result: { items: [...], count: 50 } }`？只需配置：\n\n```typescript\nconfigTableOut: { total: 'count', tableData: 'items', pageSize: 'pageSize', current: 'pageIndex' }\n```\n\n组件会递归查找响应中的字段，适配任意嵌套结构。\n\n### 请求/响应拦截\n\n```typescript\noptions: {\n  listenToCallBack: {\n    brcb: (params) => ({ ...params, token: getToken() }),   // 请求前拦截\n    qrcb: (response) => transformResponse(response)          // 响应后转换\n  }\n}\n```\n\n---\n\n## useDialog 编程式弹窗\n\n```tsx\nimport { useDialog } from '@es-plus/vue3'\n\nconst dialog = useDialog()\n\nfunction openEditForm(row) {\n  const formData = reactive({ ...row })\n  dialog({\n    title: '编辑用户',\n    width: '500px',\n    render: (h, { registerRef }) => (\n      <EsForm\n        ref={el => el && registerRef('form', el)}\n        model={formData}\n        formItemList={[\n          { prop: 'name', label: '姓名', formtype: 'Input', span: 24 },\n          { prop: 'email', label: '邮箱', formtype: 'Input', span: 24 }\n        ]}\n      />\n    ),\n    configBtn: [\n      { name: '取消', click: (_, { close }) => close() },\n      { name: '确定', type: 'primary', click: async (_, { close, getRefs }) => {\n        try {\n          await getRefs('form')?.validate()\n          await api.updateUser(formData)\n          close()\n        } catch { /* 表单验证失败 */ }\n      }}\n    ]\n  })\n}\n```\n\n---\n\n## 权限控制\n\n安装时配置权限函数，按钮自动按权限显隐：\n\n```typescript\napp.use(ESPlus, {\n  permission: (value) => userPermissions.includes(value)\n})\n```\n\n```typescript\n// 按钮配置中声明权限标识\nconst btns = [\n  { name: '新增', type: 'primary', permissionValue: 'user:add', click: () => add() },\n  { name: '删除', type: 'danger', permissionValue: 'user:delete', click: (row) => del(row) }\n]\n// 无 'user:delete' 权限时，删除按钮自动隐藏，无需 v-if\n```\n\n---\n\n## 国际化\n\n安装时配置翻译函数，配合任意 i18n 库：\n\n```typescript\nimport { useI18n } from 'vue-i18n'\n\napp.use(ESPlus, {\n  t: (key) => useI18n().t(key)\n})\n```\n\n```typescript\nconst formItems = [\n  { prop: 'name', label: '姓名', labelKey: 'form.name', formtype: 'Input' }\n]\n// 有 labelKey 时使用 t(labelKey) 翻译，否则回退到 label\n```\n\n---\n\n## TypeScript 类型\n\n```typescript\nimport type {\n  FormItemOption,    // 表单项配置\n  BtnConfig,         // 按钮配置\n  LayoutFormProps,   // 表单布局配置\n  TableColumn,       // 表格列配置\n  TableOptions,      // 表格选项\n  PaginationConfig,  // 分页配置\n  DialogOptions,     // 弹窗选项\n  ApiParams,         // 接口参数\n  EsFormInstance,    // 表单实例方法\n  EsTableInstance,   // 表格实例方法\n  EsPlusOptions      // 全局配置\n} from '@es-plus/vue3'\n```\n\n> 跨 Vue 2 / Vue 3 / AntDV 共享类型时，从 `@es-plus/core/types` 导入 — 同一份 `columns` / `formItemList` 在三个渲染器中通用。\n\n---\n\n## AI 工具链\n\nES-Plus 从设计上拥抱 AI 编码，配套两个官方工具：\n\n### @es-plus/mcp-server — AI 编码工具集成\n\n让 Claude Code、Cursor 等 AI 工具直接调用 CRUD 生成能力：\n\n```bash\n# Claude Code 一行配置\nclaude mcp add es-plus -- npx -y @es-plus/mcp-server\n```\n\n然后在 AI 对话中直接说：\n\n> \"生成一个用户管理页面，查询姓名、手机号、状态，表格显示姓名、邮箱、状态、创建时间，支持新增编辑删除\"\n\nAI 自动调用 MCP Server 生成完整可运行的 .vue 文件。\n\n工具面遵循「一个前门 + 确定性支撑」：**`generate_scene` 是唯一前门**（先声明要建什么：crud / table / form / dialog，再填该场景的意图表，路由与编译是确定性代码）。`generate_composition` 把多个独立片段装成一张能跑的页面。`generate_crud` 是 `scene='crud'` 的**兼容入口**（产物逐字节相同），`generate_crud_from_config` 标注 **ADVANCED**（已持有类型化配置时用），`generate_crud_schema` 标注 **LEGACY FALLBACK**（no-LLM 正则兜底）。`ESPLUS_MCP_PROFILE=front-door` 把 18 个工具收缩到 12 个 —— 隐藏标准不是「旧不旧」，而是 `generate_scene` 能否**逐字节复现**（四个 scene 复用同一组发射器），宿主每轮的 `tools/list` 因此从 ~339 KB 降到 ~21 KB。完整工具清单、选择决策树与分层依据见 [`packages/mcp-server/AI-NATIVE-ARCHITECTURE.md`](./packages/mcp-server/AI-NATIVE-ARCHITECTURE.md)。\n\n想先看效果再看原理：AI 案例导览 [`docs/ai/ai-showcase.md`](./docs/ai/ai-showcase.md) 逐个说明站点上每个 AI 页面证明了什么、证据在哪，以及 `claim`（`measure` / `compile` / `execute`）该怎么读 —— 跑过的才叫 `execute`。\n\n### @es-plus/cli — 命令行工具\n\n终端直接生成 CRUD 页面：\n\n```bash\n# 交互式生成\nnpx @es-plus/cli create user-management\n\n# 非交互式\nnpx @es-plus/cli create user-management \\\n  -d \"用户管理，查询姓名、手机号、状态，表格显示姓名、手机号、邮箱、状态、创建时间，支持新增编辑删除\"\n\n# 校验 JSON 配置\nnpx @es-plus/cli validate ./config.json --schema form-item\n\n# 生成页面脚手架\nnpx @es-plus/cli scaffold dashboard --features query,table,dialog\n```\n\n---\n\n## 全局配置\n\n```typescript\napp.use(ESPlus, {\n  // 权限控制\n  permission: (value) => userPermissions.includes(value),\n  // 国际化\n  t: (key) => i18n.global.t(key),\n  // 表格全局默认配置\n  EsTable: {\n    httpRequest: async (params) => axios(params).then(r => r.data),\n    configQueryFieldOutput: {\n      total: 'total', tableData: 'data', pageSize: 'pageSize', current: 'pageIndex'\n    },\n    paginationLayout: {\n      layout: 'total, sizes, prev, pager, next, jumper',\n      pageSizes: [10, 20, 50, 100]\n    },\n    // 每张表的 options 默认值（实例 :options 优先）\n    defaults: { size: 'small', border: true }\n  }\n})\n```\n\n---\n\n## 项目结构\n\n```\nes-plus/\n├── packages/\n│   ├── vue3/             # Vue 3 + Element Plus 渲染器（npm: @es-plus/vue3）\n│   ├── vue2/             # Vue 2 + Element UI 渲染器（npm: @es-plus/vue2）\n│   ├── adapter-antdv/    # Vue 3 + Ant Design Vue 渲染器（npm: @es-plus/adapter-antdv）\n│   ├── core/             # 框架无关核心层（npm: @es-plus/core）\n│   ├── es-plus-legacy/   # 兼容 stub（npm: es-plus-ui，re-export @es-plus/vue3）\n│   ├── shared/           # MCP/CLI 共享逻辑（npm: @es-plus/shared）\n│   ├── mcp-server/       # MCP Server（npm: @es-plus/mcp-server）\n│   └── cli/              # CLI 工具（npm: @es-plus/cli）\n├── es-plus-docs/         # 主文档站（Vite + Vue 3 + Element Plus）\n├── es-eui/               # Vue 2 + Element UI 文档站\n├── es-pc/                # Ant Design Vue 文档站\n├── scripts/              # 一致性/契约校验脚本（check:consistency 等）\n├── __tests__/            # e2e 矩阵 + Playwright 运行时测试\n└── docs/                 # 设计文档与迁移指南\n```\n\n## 本地开发\n\n```bash\n# 根目录一次性装依赖（workspaces monorepo，无需逐包 install）\nnpm install --legacy-peer-deps\n\n# 构建全部可发布包（按依赖顺序：shared → vue3 → vue2 → adapter-antdv → cli → mcp-server）\nnpm run build:packages\n\n# 文档站点开发\ncd es-plus-docs && npm run dev\n\n# 运行全部包单测\nnpm test\n\n# 跨包 e2e 矩阵（vue2/vue3/antdv × schema/sfc）\nnpm run test:e2e\n\n# 类型检查（逐包）\nnpm run typecheck --workspaces --if-present\n\n# 一致性校验（三端类型导出 / schema 单一真源）\nnpm run check:consistency\n```\n\n## 相关链接\n\n| 包 | 说明 | 链接 |\n|---|---|---|\n| `@es-plus/vue3` | Vue 3 + Element Plus 渲染器 | [npm](https://www.npmjs.com/package/@es-plus/vue3) |\n| `@es-plus/vue2` | Vue 2 + Element UI 渲染器 | [npm](https://www.npmjs.com/package/@es-plus/vue2) |\n| `@es-plus/adapter-antdv` | Vue 3 + Ant Design Vue 渲染器 | [npm](https://www.npmjs.com/package/@es-plus/adapter-antdv) |\n| `@es-plus/core` | 框架无关核心层（类型/工具/算法） | [npm](https://www.npmjs.com/package/@es-plus/core) |\n| `@es-plus/mcp-server` | AI 编码工具集成 | [npm](https://www.npmjs.com/package/@es-plus/mcp-server) |\n| `@es-plus/cli` | 命令行工具 | [npm](https://www.npmjs.com/package/@es-plus/cli) |\n| `es-plus-ui` (deprecated) | 已迁移至 `@es-plus/vue3` | [迁移指南](./docs/migrate-v1.4.md) |\n| 在线文档 | 完整 API 与示例 | [文档](https://main.esplus-ai.com/) |\n\n## 贡献\n\n欢迎提交 Issue 和 Pull Request！用法提问、集成讨论和功能设想请走 [GitHub Discussions](https://github.com/liujiaao/es-plus/discussions)；能复现的缺陷与明确的功能请求请开 [Issue](https://github.com/liujiaao/es-plus/issues/new)。\n\n1. Fork 本仓库\n2. 创建功能分支：`git checkout -b feature/your-feature`\n3. 提交更改：`git commit -m 'feat: add your feature'`\n4. 推送分支：`git push origin feature/your-feature`\n5. 提交 Pull Request\n\n## License\n\n[MIT](LICENSE)\n"}