UNPKG

@vue-ui-kit/ant

Version:

Vue3 UI Kit based on Ant Design

624 lines (539 loc) 15.2 kB
<div align="center"> [English](./README.md) | 简体中文 </div> # Vue UI Kit 使用文档 基于 Ant Design Vue 的 Vue 3 UI 组件库,提供增强的表单、网格和实用组件。 ## 安装 ```bash npm install @vue-ui-kit/ant # 或 yarn add @vue-ui-kit/ant # 或 pnpm add @vue-ui-kit/ant ``` ```ts /*main.ts*/ import { createApp } from 'vue'; import App from './App.vue'; import Antd from 'ant-design-vue'; import UIKit from '@vue-ui-kit/ant'; import '@vue-ui-kit/ant/scss'; /*创建渲染器(推荐使用tsx配置)*/ import { setupKit } from './setup/kit.tsx'; /*创建格式化*/ UIKit.addFormatter({ test: ({ row, column, cellValue }) => 'test:...' + 'field:' + column.field + '...v:' + cellvalue, }); createApp(App).use(Antd).use(UIKit).mount('#app'); ``` ```tsx /*kit.tsx*/ import UIKit from '@vue-ui-kit/ant'; import { TypographyParagraph, Switch } from 'ant-design-vue'; export const setupKit = () => { /*注册$paragraph作为单元格渲染器*/ UIKit.addRender('$paragraph', { renderDefault({ props = {} }: RenderOptions, { row, field }: RenderTableParams) { const content = props.getContent?.({ row, field }) ?? (valued(field) ? row[field!] : ''); return valued(field) ? ( <TypographyParagraph {...merge({}, defaultProps.$paragraph, omit(props, ['content', 'getContent']))} content={content} /> ) : null; }, }); /*注册$switch 作为表单渲染器*/ UIKit.addRender('$switch', { renderItemContent( { props = {}, events = {} }: RenderOptions, { data, field }: RenderFormParams, ) { return valued(field) ? ( <Switch v-model:checked={data[field!]} {...props} onChange={(...arg) => { events.change?.({ data, field }, ...arg); }} /> ) : null; }, }); }; /* * 已内置了渲染器 * $input: Input, AInput: Input, $textarea: Textarea, Textarea: Textarea, $number: InputNumber, AInputNumber: InputNumber, $select: Select, ASelect: Select, $date: DatePicker, ADatePicker: DatePicker, $range: RangePicker, ARangePicker: RangePicker, AAutoComplete: AutoComplete, $Cascader: Cascader, ACascader: Cascader, ACheckbox: Checkbox, AMentions: Mentions, ARate: Rate, ASlider: Slider, $time: TimePicker, ATimePicker: TimePicker, ATreeSelect: TreeSelect, * * */ ``` ## 环境要求 - Node.js >= 16 - Vue >= 3.2.0 - ant-design-vue >= 4.0.0 - @ant-design/icons-vue >= 7.0.0 ## 组件 ### PGrid 增强的数据表格组件,集成了查询表单、分页和工具栏功能。 #### 基础示例 ```vue <script setup lang="ts"> import { computed } from 'vue'; import { PGridProps, labelColDict } from '@vue-ui-kit/ant'; const gridSetting = computed<PGridProps<Student, { keyword?: string }>>(() => ({ columns: [ { field: 'name', title: '姓名', width: 200 }, { field: 'email', title: '邮箱', width: 200 }, { field: 'age', title: '年龄', width: 100 }, ], formConfig: { items: [ { field: 'keyword', title: '关键字', labelCol: labelColDict[3], itemRender: { name: '$input', props: { placeholder: '请输入关键字...' }, }, }, ], }, proxyConfig: { ajax: { query: ({ form, page }) => api.getStudents({ ...form, ...page }), }, }, })); </script> <template> <p-grid v-bind="gridSetting" /> </template> ``` ### PForm 增强的表单组件,具有简化的配置和动态字段功能。 #### 属性 | 属性 | 类型 | 说明 | 默认值 | | --- | --- | --- | --- | | items | `PFormItemProps[]` | 表单项配置数组 | - | | data | `T` | 表单数据对象 | - | | customReset | `() => void` | 自定义重置函数 | - | | labelCol | `ColProps` | 标签列布局 | `{ span: 6 }` | | wrapperCol | `ColProps` | 包装列布局 | `{ span: 16 }` | | ...其他 | `FormProps` | 所有 ant-design-vue Form 的属性 | - | #### 事件 | 事件 | 说明 | 参数 | | --- | --- | --- | | apply | 表单提交时触发 | `(formData: T) => void` | | reset | 表单重置时触发 | `() => void` | #### PFormItemProps | 属性 | 类型 | 说明 | 默认值 | | --- | --- | --- | --- | | field | `string` | 表单字段名 | - | | title | `string` | 字段标签 | - | | span | `number` | 栅格跨度 (1-24) | - | | colon | `boolean` | 标签后显示冒号 | `true` | | labelCol | `ColProps` | 标签列布局 | - | | wrapperCol | `ColProps` | 包装列布局 | - | | forceRequired | `boolean` | 显示必填标记(仅视觉效果) | `false` | | align | `'left' \| 'right' \| 'center'` | 文本对齐方式 | `'left'` | | col | `ColProps` | 栅格列属性 | - | | rule | `Rule[]` | 验证规则 | - | | itemRender | `ItemRender` | 字段渲染器配置 | - | | tooltipConfig | `TooltipConfig` | 提示配置 | - | | slots | `object` | 自定义插槽渲染器 | - | #### 内置渲染器 - `$input`: 输入框 - `$textarea`: 文本域 - `$number`: 数字输入框 - `$select`: 下拉选择 - `$date`: 日期选择器 - `$range`: 日期范围选择器 - `$time`: 时间选择器 - `ASwitch`: 开关组件 - `ACheckbox`: 复选框 - `ARate`: 评分组件 - `ASlider`: 滑动输入条 #### 基础示例 ```vue <script setup lang="ts"> import { ref, computed } from 'vue'; import { PFormProps } from '@vue-ui-kit/ant'; interface UserForm { name: string; email: string; age?: number; gender: string; skills: string[]; } const formData = ref<UserForm>({ name: '', email: '', age: undefined, gender: '', skills: [], }); const formSetting = computed<PFormProps<UserForm>>(() => ({ items: [ { field: 'name', title: '姓名', span: 12, rule: [{ required: true, message: '请输入姓名' }], itemRender: { name: '$input', props: { placeholder: '请输入姓名' }, }, }, { field: 'email', title: '邮箱', span: 12, rule: [ { required: true, message: '请输入邮箱' }, { type: 'email', message: '邮箱格式不正确' }, ], itemRender: { name: '$input', props: { placeholder: '请输入邮箱' }, }, }, { field: 'gender', title: '性别', span: 12, rule: [{ required: true, message: '请选择性别' }], itemRender: { name: '$select', props: { placeholder: '请选择性别', options: [ { label: '男', value: 'male' }, { label: '女', value: 'female' }, ], }, }, }, { field: 'skills', title: '技能', span: 24, itemRender: { name: '$select', props: { mode: 'multiple', placeholder: '请选择技能', options: [ { label: 'Vue.js', value: 'vue' }, { label: 'React', value: 'react' }, { label: 'Angular', value: 'angular' }, ], }, }, }, ], })); const handleSubmit = (data: UserForm) => { console.log('表单提交:', data); }; </script> <template> <p-form v-bind="formSetting" :data="formData" @apply="handleSubmit" /> </template> ``` #### 自定义插槽示例 ```vue <script setup lang="tsx"> import { ref, computed } from 'vue'; const formData = ref({ name: '', isActive: false, }); const formSetting = computed(() => ({ items: [ { field: 'isActive', title: '状态', span: 24, slots: { default: ({ data }) => ( <a-switch v-model:checked={data.isActive} checkedChildren="启用" unCheckedChildren="禁用" /> ), }, }, ], })); </script> ``` ### PFormGroup 动态表单组组件,用于管理多个表单实例,支持添加/删除功能。 #### 属性 | 属性 | 类型 | 说明 | 默认值 | | --- | --- | --- | --- | | v-model | `Array<T & { __index: number }>` | 表单组数据数组 | `[]` | | getFormSetting | `(data: T) => PFormProps<T>` | 获取表单配置的函数 | - | | title | `string` | 组标题 | - | | tabLabel | `string` | 自定义标签页标签模板 | - | | editAble | `boolean` | 标签页是否可编辑 | `true` | | showAdd | `boolean` | 显示添加按钮 | `true` | | lazyErrorMark | `boolean` | 延迟错误标记 | `false` | | forceRender | `boolean` | 强制渲染所有标签页 | `false` | | keepSerial | `boolean` | 保持连续编号 | `false` | | loading | `boolean` | 加载状态 | `false` | | max | `number` | 最大项目数量 | `Infinity` | | itemMenus | `GroupMenuItem[]` | 自定义菜单项 | 默认复制/删除 | | createItem | `(opts: { list: T[] }) => Promise<T>` | 自定义项目创建器 | - | | menuHandler | `GroupMenuItemHandler<T>` | 自定义菜单处理器 | - | #### 暴露的方法 | 方法 | 说明 | 参数 | 返回值 | | --- | --- | --- | --- | | validateAll | 验证所有表单实例 | - | `Promise<void>` | | validate | 验证特定表单实例 | `__index: number` | `Promise<void>` | | setActiveKey | 设置活动标签页 | `key: number` | `void` | #### 基础示例 ```vue <script setup lang="ts"> import { ref, computed } from 'vue'; import { PFormGroupProps } from '@vue-ui-kit/ant'; interface Project { __index: number; name: string; startDate: string; endDate: string; budget?: number; } const projects = ref<Project[]>([ { __index: 0, name: '项目A', startDate: '', endDate: '', budget: undefined, } ]); const groupSetting = computed<PFormGroupProps<Project>>(() => ({ title: '项目管理', showAdd: true, max: 10, getFormSetting: (data) => ({ items: [ { field: 'name', title: '项目名称', span: 24, rule: [{ required: true, message: '请输入项目名称' }], itemRender: { name: '$input', props: { placeholder: '请输入项目名称' }, }, }, { field: 'startDate', title: '开始日期', span: 12, rule: [{ required: true, message: '请选择开始日期' }], itemRender: { name: '$date', props: { placeholder: '请选择开始日期' }, }, }, { field: 'endDate', title: '结束日期', span: 12, rule: [{ required: true, message: '请选择结束日期' }], itemRender: { name: '$date', props: { placeholder: '请选择结束日期' }, }, }, { field: 'budget', title: '预算', span: 24, itemRender: { name: '$number', props: { min: 0, placeholder: '请输入预算', formatter: (value) => `¥ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ','), parser: (value) => value.replace(/¥\s?|(,*)/g, ''), }, }, }, ], }), })); const handleSave = async () => { try { await groupRef.value?.validateAll(); console.log('所有项目已保存:', projects.value); } catch (error) { console.error('验证失败:', error); } }; const groupRef = ref(); </script> <template> <div> <p-form-group ref="groupRef" v-model="projects" v-bind="groupSetting" /> <a-button type="primary" @click="handleSave"> 保存所有项目 </a-button> </div> </template> ``` #### 自定义菜单示例 ```vue <script setup lang="ts"> import { ref, computed } from 'vue'; const projects = ref([]); const groupSetting = computed(() => ({ title: '高级项目管理', itemMenus: [ { content: '复制', code: 'copy' }, { content: '删除', code: 'delete' }, { content: '导出', code: 'export' }, { content: '归档', code: 'archive', visibleMethod: ({ data }) => data.status !== 'archived' }, ], createItem: async ({ list }) => { return { name: `项目 ${list.length + 1}`, status: 'active', startDate: new Date().toISOString().split('T')[0], }; }, menuHandler: ({ code, data, index }) => { switch (code) { case 'export': exportProject(data); break; case 'archive': archiveProject(data, index); break; } }, getFormSetting: (data) => ({ // ... 表单配置 }), })); </script> ``` ## 工具函数 ### labelColDict 为不同文本长度预定义的标签列配置: ```ts import { labelColDict } from '@vue-ui-kit/ant'; // 在表单项中使用 { field: 'shortField', title: '姓名', // 2个字符 labelCol: labelColDict[2], } { field: 'longerField', title: '项目描述', // 4+个字符 labelCol: labelColDict[4], } ``` ### 自定义渲染器 注册自定义表单字段渲染器: ```tsx import UIKit from '@vue-ui-kit/ant'; import { Switch } from 'ant-design-vue'; UIKit.addRender('$switch', { renderItemContent( { props = {}, events = {} }, { data, field } ) { return ( <Switch v-model:checked={data[field]} {...props} onChange={(...args) => { events.change?.({ data, field }, ...args); }} /> ); }, }); ``` ### 自定义格式化器 为 PGrid 注册自定义单元格格式化器: ```ts UIKit.addFormatter({ currency: ({ cellValue }) => `¥${cellValue?.toLocaleString() || '0'}`, percentage: ({ cellValue }) => `${(cellValue * 100).toFixed(2)}%`, }); ``` ## 常见问题 ### 1. 使用 computed + v-bind 生成动态表格+表单时,表单选项更新导致表格重新渲染,如何解决? 答案:将 formConfig 分离为另一个计算属性 ```vue <p-grid v-bind="gridSetting" :form-config="computedFormConfig" /> ``` ### 2. 表格 ajax 目前只支持 multiDelete 和表格数据获取吗? 答案:编辑详情在大多数情况下无法与表格一一对应,所以没有开发意义。多行删除需要配合使用: ```ts selectConfig: { multiple: true, }, toolbarConfig: { buttons: { code: "multipleDelete" } } ``` ### 3. 为什么推荐 computed 方式? 答案:它简化了所有动态逻辑。对于复杂场景,您可以尝试使用 reactive 并自己维护,但在大多数情况下,computed 更方便。 ## TypeScript 支持 该库完全使用 TypeScript 编写,并提供全面的类型定义: ```ts import type { PFormProps, PFormItemProps, PFormGroupProps, PGridProps, ColumnProps } from '@vue-ui-kit/ant'; ``` ## 许可证 MIT