npm package: @leiyin/v-form-renderer
Description: Base on element-ui, Render form-item easily
Author: leiyin
Latest version: 1.0.2

# @leiyin/v-form-renderer

一个基于 Vue 3 + Element Plus 的配置化表单渲染组件，用 JSON/Schema 快速生成复杂表单。

## ✨ 特性
- 配置驱动（Content Schema）
- 支持 group 嵌套、动态显隐与禁用
- v-model 双向绑定与方法暴露
- 远程选项加载与自定义组件
- 完整 TypeScript 类型与 ESM/CJS 构建

## 📦 安装
- peerDependencies：vue ^3.2.0、element-plus 2.11.7

```bash
pnpm add @leiyin/v-form-renderer
# 或
npm install @leiyin/v-form-renderer
# 或
yarn add @leiyin/v-form-renderer
```

## 🚀 基础用法
```vue
<template>
  <VFormRenderer :content="schema" />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import VFormRenderer from '@leiyin/v-form-renderer'

const schema = ref([
  { id: 'username', type: 'input', label: '用户名', el: { placeholder: '请输入' }, default: '' },
  { id: 'role', type: 'select', label: '角色', options: [
    { label: '管理员', value: 'admin' },
    { label: '普通用户', value: 'user' }
  ] }
])
</script>
```

## 🔗 v-model 与方法
- v-model：使用 v-model:model 绑定整个表单对象
- 方法暴露：通过 ref 获取实例并调用内置方法

```vue
<template>
  <VFormRenderer
    v-model:model="form"
    :content="schema"
    ref="formRef"
    @enter="onEnter"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import VFormRenderer, { type VFormRendererInstance } from '@leiyin/v-form-renderer'

const form = ref<Record<string, any>>({})
const formRef = ref<VFormRendererInstance>()

const onEnter = () => {
  // 回车事件
}

const getValue = () => {
  const result = formRef.value?.getFormValue() // outputFormat 后的值
  console.log(result)
}

const validate = async () => {
  const ok = await formRef.value?.validate()
  console.log('valid:', ok)
}

const reset = () => {
  formRef.value?.resetFields()
}

const patch = () => {
  formRef.value?.updateForm({ username: '张三' })
}
</script>
```

方法来源与实现参考：
- 组件实现 [v-form-renderer.vue](file:///v-form-renderer/src/v-form-renderer.vue)
- 方法定义 [useFormEvents.ts](file:///v-form-renderer/src/hooks/useFormEvents.ts#L1-L75)
- Props 定义 [v-form-renderer.ts](file:///v-form-renderer/src/v-form-renderer.ts#L1-L31)

## ⚙️ Props
- content: Content[] 必填，表单 Schema
- labelWidth: string，统一 label 宽度，默认 98px
- disabled: boolean，禁用整个表单
- inline: boolean，行内表单，默认 true
- readonly: boolean，只读模式（input 显示文本，select 显示 label）
- 透传：支持 Element Plus el-form 的其余属性与事件（使用 v-bind="$attrs"）

## 🧩 Content Schema
类型定义参考 [form.ts](file:///v-form-renderer/src/types/form.ts#L1-L109)

常用字段：
- id: string，唯一键，作为数据 key
- label: string | Function，表单项标题；支持组件函数
- type: string，例如 'input' | 'select' | 'radio-group' | 'checkbox-group' | 'cascader' | 'group'
- el: Record<string, any>，对应组件的属性，如 placeholder、multiple 等
- default: any，初始默认值
- items: Content[]，当 type='group' 时的子项
- hidden(formValue, item): boolean，返回 true 隐藏
- disabled(formValue, item): boolean，返回 true 禁用
- options: { label: string; value?: any }[]，选择类组件选项
- component: 自定义组件，优先于 type 的内置组件
- inputFormat(obj): any，处理输入值（default/v-model/updateForm）
- outputFormat(val, obj): any，处理输出值（getFormValue 时应用）
- rules: FormItemRule[]，Element Plus 校验规则
- remote: 远程 prop/选项加载（select/radio/checkbox 支持自动映射）
- on: 事件监听回调，签名为 (args, updateForm, setOptions) => void

示例：group 嵌套
```ts
const schema = [
  {
    id: 'user',
    type: 'group',
    label: '用户信息',
    items: [
      { id: 'name', type: 'input', label: '姓名', default: '' },
      { id: 'age', type: 'input', label: '年龄', el: { type: 'number' } }
    ]
  }
]
```

## 🌐 远程选项加载
```ts
const schema = [
  {
    id: 'city',
    type: 'select',
    label: '城市',
    remote: {
      // 返回 Promise 的方法（可传入 params）
      url: (params) => fetch(`/api/cities?kw=${params.kw}`).then(r => r.json()),
      dataPath: 'data.list',   // 响应体中数据路径
      label: 'name',           // 用作 label 的字段
      value: 'code'            // 用作 value 的字段
    }
  }
]
```
当为 select/radio-group/checkbox-group 时，远程数据会自动映射为 Element Plus 的选项。
实现参考 [RenderFormItem.vue](file:///v-form-renderer/src/components/RenderFormItem.vue#L194-L247)。

## 👁️ 只读与显隐
- readonly: true 时，input 显示文本、select 显示选中项 label
- hidden/disabled：传入函数，依据当前 formModel 动态控制

```ts
const schema = [
  {
    id: 'level',
    type: 'select',
    label: '级别',
    options: [{ label: 'A', value: 'A' }, { label: 'B', value: 'B' }]
  },
  {
    id: 'extra',
    type: 'input',
    label: '额外信息',
    hidden: (form) => form.level !== 'A'
  }
]
```

## 🎯 校验与重置
- 使用 Element Plus 的规则校验（rules）
- validate(): Promise<boolean | void>
- resetFields(): 重置为 default 值并清除校验

参考 [useFormEvents.ts](file:///v-form-renderer/src/hooks/useFormEvents.ts#L20-L44)。

## 🧱 插槽与自定义
- 命名插槽：以 id 为名注入内容，例如 #id:username
- label 组件：将 label 设置为组件/函数，渲染自定义标题
- 自定义组件：传入 component 替代内置 Element Plus 组件

```vue
<template>
  <VFormRenderer :content="schema">
    <template #id:username>
      <span style="margin-right: 8px">用户名扩展内容</span>
    </template>
  </VFormRenderer>
</template>

<script setup lang="ts">
const schema = [
  {
    id: 'username',
    type: 'input',
    label: '用户名',
    el: { placeholder: '请输入' }
  }
]
</script>
```
插槽实现参考 [v-form-renderer.vue](file:///v-form-renderer/src/v-form-renderer.vue#L60-L83) 与渲染器 [render-component.ts](file:///v-form-renderer/src/components/render-component.ts#L1-L33)。

## 📚 导入与类型
- 默认导出：VFormRenderer
- 类型导出：Content、VFormProps、VFormRendererInstance 等

入口参考 [index.ts](file:///v-form-renderer/src/index.ts)。