# Dynamic Components
基于 Vue 3 和 Naive UI 的动态表单和表格组件库,提供灵活的配置式 UI 开发方案。
## 目录
- [安装](#安装)
- [快速开始](#快速开始)
- [核心功能](#核心功能)
- [组件和 Hooks](#组件和-hooks)
- [useForm](#useform)
- [useTable](#usetable)
- [useTabs](#usetabs)
- [FormDesigner](#formdesigner)
- [FormBuilder](#formbuilder)
## 安装
```bash
# 使用 npm
npm install dynamic-components
# 使用 yarn
yarn add dynamic-components
# 使用 pnpm
pnpm add dynamic-components
```
## 快速开始
### 基础依赖
本组件库基于 Vue 3 和 Naive UI 构建,请确保您的项目中已安装以下依赖:
```json
{
"dependencies": {
"@vicons/tabler": "^0.13.0",
"@vueuse/core": "^10.7.0",
"naive-ui": "^2.37.3",
"vue": "^3.4.0"
}
}
```
### 基本用法
```vue
提交
```
## 核心功能
- **配置式表单**:通过 JSON 配置快速构建复杂表单
- **动态表格**:支持自定义列、排序、筛选等功能
- **表单设计器**:可视化拖拽设计表单
- **标签页管理**:简化多标签页应用开发
## 组件和 Hooks
### useForm
`useForm` 是一个强大的表单 Hook,用于创建动态表单。
#### 基本用法
```js
import { useForm } from '@baota/naive-ui/hooks'
const form = useForm({
config: [
{
type: 'formItem',
label: '姓名',
children: [
{
type: 'input',
field: 'name',
},
],
},
],
defaultValues: {
name: '',
},
requestFn: async (data) => {
// 提交表单数据的请求函数
return await api.submitForm(data)
},
})
```
#### 参数说明
| 参数 | 类型 | 必填 | 说明 |
| ------------- | --------------------------- | ---- | ------------------------------ |
| config | FormConfig | 是 | 表单配置 |
| defaultValues | Record | 否 | 表单默认值 |
| requestFn | (data: any) => Promise | 否 | 表单提交请求函数 |
| immediate | boolean | 否 | 是否立即执行请求,默认为 false |
#### 返回值
| 属性 | 类型 | 说明 |
| ------------- | ------------------------ | ------------ |
| loading | Ref | 加载状态 |
| formData | Ref> | 表单数据 |
| formRef | Ref | 表单实例引用 |
| submit | () => Promise | 提交方法 |
| reset | () => void | 重置方法 |
| validate | () => Promise | 验证方法 |
| FormComponent | () => JSX.Element | 表单渲染组件 |
#### 支持的表单元素
| 类型 | 说明 | 对应 Naive UI 组件 |
| ------------- | ---------- | ------------------ |
| input | 输入框 | NInput |
| inputNumber | 数字输入框 | NInputNumber |
| inputGroup | 输入框组 | NInputGroup |
| select | 选择器 | NSelect |
| radio | 单选框组 | NRadioGroup |
| radioButton | 单选按钮 | NRadioButton |
| checkbox | 复选框组 | NCheckboxGroup |
| switch | 开关 | NSwitch |
| datepicker | 日期选择器 | NDatePicker |
| timepicker | 时间选择器 | NTimePicker |
| colorPicker | 颜色选择器 | NColorPicker |
| slider | 滑块 | NSlider |
| rate | 评分 | NRate |
| transfer | 穿梭框 | NTransfer |
| mention | 提及 | NMention |
| dynamicInput | 动态输入 | NDynamicInput |
| dynamicTags | 动态标签 | NDynamicTags |
| autoComplete | 自动完成 | NAutoComplete |
| cascader | 级联选择 | NCascader |
| treeSelect | 树选择 | NTreeSelect |
| upload | 上传 | NUpload |
| uploadDragger | 拖拽上传 | NUploadDragger |
| slot | 插槽 | - |
| render | 自定义渲染 | - |
#### 栅格布局
```js
const formConfig = [
{
type: 'grid',
cols: 24,
xGap: 12,
children: [
{
type: 'formItemGi',
label: '姓名',
span: 12,
children: [
{
type: 'input',
field: 'firstName',
},
],
},
{
type: 'formItemGi',
label: '姓氏',
span: 12,
children: [
{
type: 'input',
field: 'lastName',
},
],
},
],
},
]
```
#### 自定义插槽
```vue
{{
customSlot,
}}
```
### useTable
`useTable` 是一个用于创建动态表格的 Hook。
#### 基本用法
```js
import { useTable } from '@baota/naive-ui/hooks'
import { h } from 'vue'
// 定义表格列
const columns = [
{
title: 'ID',
key: 'id',
},
{
title: '姓名',
key: 'name',
},
{
title: '操作',
key: 'actions',
render: (row) =>
h('div', [
h('button', { onClick: () => handleEdit(row) }, '编辑'),
h('button', { onClick: () => handleDelete(row) }, '删除'),
]),
},
]
// 创建表格实例
const table = useTable({
columns,
requestFn: async (params) => {
// 获取表格数据的请求函数
const res = await api.getList(params)
return {
list: res.data.list,
}
},
defaultParams: {
page: 1,
pageSize: 10,
},
})
```
#### 参数说明
| 参数 | 类型 | 必填 | 说明 |
| ------------- | ------------------------------------------------------ | ---- | ----------------------------- |
| columns | DataTableColumns | 是 | 表格列配置 |
| requestFn | (params: TableRequestParams) => Promise | 是 | 数据请求函数 |
| defaultParams | Ref | 否 | 默认请求参数 |
| immediate | boolean | 否 | 是否立即执行请求,默认为 true |
#### 返回值
| 属性 | 类型 | 说明 |
| -------------- | ------------------- | ------------ |
| loading | Ref | 加载状态 |
| data | Ref | 表格数据 |
| params | TableRequestParams | 查询参数 |
| refresh | () => Promise | 刷新方法 |
| reset | () => Promise | 重置方法 |
| tableRef | Ref | 表格引用 |
| TableComponent | () => JSX.Element | 表格渲染组件 |
### useTabs
`useTabs` 是一个用于管理标签页的 Hook,特别适合基于路由的多标签页应用。
#### 基本用法
```vue
```
#### 参数说明
| 参数 | 类型 | 必填 | 说明 |
| -------------- | ------- | ---- | --------------------------------------------- |
| defaultToFirst | boolean | 否 | 是否在初始化时自动选中第一个标签,默认为 true |
#### 返回值
| 属性 | 类型 | 说明 |
| --------------- | --------------------- | ---------------- |
| activeKey | string | 当前激活的标签值 |
| childRoutes | RouteRecordRaw[] | 子路由列表 |
| handleTabChange | (key: string) => void | 切换标签页方法 |
| TabsComponent | () => JSX.Element | 标签页渲染组件 |
### FormDesigner
`FormDesigner` 是一个可视化表单设计器组件,支持拖拽设计表单。
#### 基本用法
```vue
```
#### 功能特点
- 支持拖拽添加表单组件
- 支持编辑组件属性
- 支持导入/导出表单配置
- 实时预览表单效果
### FormBuilder
`FormBuilder` 是一个简化版的表单构建器组件,适合快速创建简单表单。
#### 基本用法
```vue
```
#### 功能特点
- 拖拽式表单构建
- 支持导出表单配置
- 简单直观的操作界面
## 类型定义
组件库提供了完整的 TypeScript 类型定义,可以在开发时获得良好的类型提示。
```ts
import type {
FormConfig,
FormItemConfig,
FormElement,
UseFormOptions,
FormInstance,
TableRequestParams,
TableResponse,
UseTableOptions,
TableInstance,
} from '@baota/naive-ui/hooks'
```
## 示例
### 完整的表单示例
```vue
提交
```
### 完整的表格示例
```vue
```
## 贡献
欢迎提交 Issue 或 Pull Request 来帮助改进这个组件库。
## 许可证
[ISC](LICENSE)
# @baota/naive-ui
基于 Naive UI 的扩展库,提供一系列增强功能和实用工具。
## 主要功能
- 统一的主题管理
- 扩展的 hooks 工具集
- 支持组件内和组件外使用的 API
## 安装
```bash
# npm
npm install @baota/naive-ui
# yarn
yarn add @baota/naive-ui
# pnpm
pnpm add @baota/naive-ui
```
## Message 消息提示
### 组件内使用 useMessage
在 Vue 组件内,可以直接使用 `useMessage` hook:
```tsx
import { defineComponent } from 'vue'
import { useMessage } from '@baota/naive-ui/hooks'
export default defineComponent({
setup() {
const message = useMessage()
// 基本使用
const showMessage = () => {
message.success('操作成功')
message.error('操作失败')
message.warning('警告提示')
message.info('信息提示')
}
// 处理请求结果
const handleApiResponse = (response) => {
message.request(response) // 自动根据 status 判断显示成功或失败消息
}
return { showMessage, handleApiResponse }
},
})
```
### 非组件环境使用 createAllApi
在非组件环境(如工具函数、API 请求拦截器等)中,可以使用 `createAllApi` 创建全局可用的 API 实例:
```ts
// api/index.ts
import { createAllApi } from '@baota/naive-ui/hooks'
// 创建全局API实例
export const globalApi = createAllApi()
// 在任何地方使用
export function handleApiResponse(response) {
// 自动根据 status 判断显示成功或失败消息
globalApi.message.request(response)
}
// 也可以直接调用特定类型的消息
export function showSuccessMessage(content: string) {
globalApi.message.success(content)
}
```
### 整合 createDiscreteApi 的完整方案
`createAllApi` 整合了 Naive UI 的 `createDiscreteApi`,包含了 message、notification、dialog 和 loadingBar 功能,并且扩展了 request 方法:
```ts
import { createAllApi } from '@baota/naive-ui/hooks'
// 创建全局API实例
const { message, notification, dialog, loadingBar } = createAllApi()
// 使用 message
message.success('操作成功')
message.error('操作失败')
message.request({ status: true, message: '请求成功' })
// 使用 dialog
dialog.info({
title: '提示',
content: '这是一个对话框',
})
dialog.request({ status: false, message: '操作失败' })
// 使用 notification
notification.success({
title: '成功',
content: '操作已完成',
})
// 使用 loadingBar
loadingBar.start()
// 操作完成后
loadingBar.finish()
```
## 自定义主题
可以通过传入配置来自定义主题:
```ts
import { createAllApi } from '@baota/naive-ui/hooks'
import { darkTheme } from 'naive-ui'
// 使用暗色主题
const api = createAllApi({
configProviderProps: {
theme: darkTheme,
},
})
```
## 常见问题
### 为什么需要同时支持 useMessage 和 createAllApi?
- `useMessage` 适合在组件内使用,可以访问组件上下文
- `createAllApi` 适用于非组件环境,如工具函数、API 请求拦截器等
### message.request 方法是什么?
这是我们扩展的便捷方法,用于统一处理 API 响应结果:
```ts
// API响应格式
interface ApiResponse {
status: boolean
message: string
}
// 自动根据status显示成功或失败消息
message.request(apiResponse)
```