@xinnian/form-create-core
v1.0.0
Published
这是一个基于 **Vue 3 + Element Plus** 的“规则驱动表单/展示”核心库。
Readme
@xinnian/form-create-core 使用示例
这是一个基于 Vue 3 + Element Plus 的“规则驱动表单/展示”核心库。
核心组件:
FormCreateschema 转规则:
buildRules(schema)(支持colSpan栅格、doubleRow/table/audio/descriptions,并支持Section.children多级嵌套分区)设计器辅助:
useRuleDesigner(sections, { mode, grouped })
说明:本仓库内新增了此
README.md作为使用文档;当前package.json的files仅发布dist,不会把 README 发布到 npm(如需发布可再调整files)。
1. 安装
- 必需 peer:
vue@^3.4、element-plus@^2.11
pnpm add @xinnian/form-create-core element-plus如果你的项目使用 按需引入(推荐),可使用 unplugin-element-plus(或其它方案)。
2. 最小可运行示例(直接写 Rule[])
当你已经习惯“规则数组”时,可以直接传 Rule[]:
<script setup lang="ts">
import { ref } from 'vue'
import { FormCreate, type Rule } from '@xinnian/form-create-core'
const formData = ref({ name: '', age: 18 })
const rules: Rule[] = [
{ type: 'input', field: 'name', title: '姓名', props: { placeholder: '请输入' }, required: true },
{ type: 'inputNumber', field: 'age', title: '年龄', props: { min: 0, max: 120 } }
]
</script>
<template>
<FormCreate v-model="formData" :rules="rules" />
</template>title/label:FormCreate会优先使用title,并兼容label。
3. 推荐用法:用 schema(ColumnItem/Section)+ buildRules 自动生成布局
3.1 ColumnItem[](无分区)
import { buildRules, type ColumnItem } from '@xinnian/form-create-core'
const columns: ColumnItem[] = [
{ field: 'userName', label: '用户名', type: 'input', colSpan: 8 },
{ field: 'phone', label: '手机号', type: 'input', colSpan: 8 },
{ field: 'address', label: '地址', type: 'input', colSpan: 24 }
]
const rules = buildRules(columns)3.2 Section[](带分区标题,支持多级嵌套)
Section 支持用 children 实现“分类嵌套分类”。同时为了兼容旧写法:
columns可选:你可以只用分区当容器(只写children)children可选:保持原先单层分区写法不变
import { buildRules, type Section } from '@xinnian/form-create-core'
const sections: Section[] = [
{
title: '处理情况',
children: [
{
title: '入户信息',
gutter: 20,
columns: [
{ field: 'userCode', label: '用户编号', type: 'input', colSpan: 8, required: true },
{ field: 'userName', label: '用户名称', type: 'input', colSpan: 8, required: true },
{ field: 'remark', label: '备注', type: 'textarea', colSpan: 24, props: { rows: 3 } }
]
},
{
title: '表具信息明细',
children: [
{
title: '第一条明细',
gutter: 20,
columns: [
{ field: 'changeType', label: '变更类型', type: 'input', colSpan: 8 },
{ field: 'opType', label: '操作类型', type: 'input', colSpan: 8 }
]
}
]
}
]
}
]
const rules = buildRules(sections)- 栅格规则:
colSpan默认按 element-plus 的 24 栅格理解。
4. doubleRow:一个 label 下并排两个字段
适用于“联系人电话 1/2”这类 UI:
import { buildRules, type ColumnItem } from '@xinnian/form-create-core'
const columns: ColumnItem[] = [
{
label: '联系人电话',
type: 'doubleRow',
colSpan: 24,
children: [
{ field: 'phone1', label: '电话1', type: 'input', colSpan: 12 },
{ field: 'phone2', label: '电话2', type: 'input', colSpan: 12 }
]
}
]
const rules = buildRules(columns)5. table:表格(不走 v-model),列由外部动态传入
import { buildRules, type ColumnItem } from '@xinnian/form-create-core'
const columns: ColumnItem[] = [
{
label: '审核表格',
type: 'table',
field: 'auditRows',
colSpan: 24,
props: { border: true, style: { width: '100%' } },
tableColumns: [
{ label: '环节', prop: 'stage', minWidth: 160 },
{ label: '审核人', prop: 'auditor', minWidth: 140 },
{ label: '审核时间', prop: 'time', minWidth: 160 }
]
}
]
const rules = buildRules(columns)table.field作为 data 来源,内部会取model[field],并确保是数组。
6. descriptions:描述列表(ElDescriptions)展示型布局
对应 element-plus:
<el-descriptions :column="columnNum" border>
<el-descriptions-item :label="item.label" :label-width="item.width" :span="item.span">
{{ item.value }}
</el-descriptions-item>
</el-descriptions>在本库里对应 ColumnItem.type = 'descriptions':
import { buildRules, type ColumnItem } from '@xinnian/form-create-core'
const columns: ColumnItem[] = [
{
label: '处理信息(描述列表)',
type: 'descriptions',
colSpan: 24,
props: { column: 4, border: true },
descriptionsItems: [
{ label: '处理人员', field: 'handlePerName', span: 1 },
{ label: '处理人员工号', field: 'handlePer', span: 1 },
{ label: '处理时间', field: 'handleTime', span: 1 },
{ label: '处理结果', value: '已处理', span: 1 }
]
}
]
const rules = buildRules(columns)descriptionsItems[].field:从model[field]取值展示descriptionsItems[].value:直接展示静态值span/width会映射到ElDescriptionsItem的span/labelWidth
7. 校验、必填与联动(表达式/函数)
7.1 必填
const rules = [
{
type: 'input',
field: 'userCode',
title: '用户编号',
required: true,
requiredMessage: '请输入用户编号'
}
]7.2 联动:根据 model 控制显隐/禁用/必填
- 规则里支持
visible/disabled/required为:boolean / function / string 表达式。
const rules = [
{ type: 'switch', field: 'vip', title: 'VIP' },
{
type: 'textarea',
field: 'remark',
title: '备注',
disabled: 'model.vip !== true',
required: 'model.vip === true',
requiredMessage: 'VIP 时备注必填'
}
]注意:string 表达式内部会以
new Function(...)执行,表达式来源请确保可信。
8. FormCreate 的 option(preset/组件映射)
默认 preset 为 element-plus,可以通过 option 传入覆盖。
const option = {
form: {
props: {
labelWidth: '120px',
labelPosition: 'right'
}
}
}如果你想替换某个组件或新增 type 映射:
const option = {
components: {
// 例如自定义组件注册到这里
MyCustom: MyCustomComp
},
typeMap: {
// 让规则 type=custom 映射到 MyCustom
custom: 'MyCustom'
}
}9. API:校验、清理校验、滚动到字段
通过 ref 拿到 api:
<script setup lang="ts">
import { ref } from 'vue'
import { FormCreate } from '@xinnian/form-create-core'
const fcRef = ref<{ api: any } | null>(null)
async function onValidate() {
const ok = await fcRef.value?.api?.validate?.()
const errors = fcRef.value?.api?.getValidateErrors?.() ?? {}
console.log(ok, errors)
}
function onClearValidate() {
fcRef.value?.api?.clearValidate?.()
}
function onScrollToUserCode() {
fcRef.value?.api?.scrollToField?.('userCode')
}
</script>
<template>
<FormCreate ref="fcRef" />
</template>10. useRuleDesigner:生成模式 + JSON 编辑模式
用于“设计器页面”两种模式切换:
import { computed, reactive, toRef } from 'vue'
import { useRuleDesigner, type Section } from '@xinnian/form-create-core'
const ui = reactive({ mode: 'builder' as const, grouped: true })
const sections = computed<Section[]>(() => [
{
title: '用户信息',
gutter: 20,
children: [
{
title: '基础信息',
columns: [{ field: 'name', label: '姓名', type: 'input', colSpan: 8 }]
}
]
}
])
const { jsonText, parseError, previewRules, copyBuilderToEditor } = useRuleDesigner(sections, {
mode: toRef(ui, 'mode'),
grouped: toRef(ui, 'grouped')
})previewRules:最终给FormCreate渲染的规则- JSON 模式增强:JSON 编辑器里允许直接粘贴
ColumnItem[]/Section[](包含children多级嵌套),内部会自动buildRules(...)再预览
11. 常见坑
- 样式丢失/不显示:本包的
package.json已设置sideEffects白名单保留按需样式副作用导入;消费端仍需确保 element-plus 样式按需/全量正确注入。 colSpan不生效:colSpan属于 schema 字段;需要buildRules转成row/col规则(或直接把 schema 传给FormCreate,库会自动识别并转换)。
12. 规则类型速查(常用)
- 字段类:
input、textarea、inputNumber、select、switch、datePicker... - 布局/容器:
row、col、divider、group、fragment - 展示:
text、descriptions、descriptionsItem - 表格:
table、tableColumn
如需增加更多内置类型(例如 ElTag/ElAlert/ElCard 这类展示组件),可以按 preset-element-plus.ts 的方式扩展 typeMap。
