物业代码生成

This commit is contained in:
2025-06-18 11:03:42 +08:00
commit 1262d4c745
1881 changed files with 249599 additions and 0 deletions

View File

@@ -0,0 +1,166 @@
---
outline: deep
---
# Vben Alert 轻量提示框
框架提供的一些用于轻量提示的弹窗仅使用js代码即可快速动态创建提示而不需要在template写任何代码。
::: info 应用场景
Alert提供的功能与Modal类似但只适用于简单应用场景。例如临时性、动态地弹出模态确认框、输入框等。如果对弹窗有更复杂的需求请使用VbenModal
:::
::: tip 注意
Alert提供的快捷方法alert、confirm、prompt动态创建的弹窗在已打开的情况下不支持HMR热更新代码变更后需要关闭这些弹窗后重新打开。
:::
::: tip README
下方示例代码中的,存在一些主题色未适配、样式缺失的问题,这些问题只在文档内会出现,实际使用并不会有这些问题,可忽略,不必纠结。
:::
## 基础用法
使用 `alert` 创建只有一个确认按钮的提示框。
<DemoPreview dir="demos/vben-alert/alert" />
使用 `confirm` 创建有确认和取消按钮的提示框。
<DemoPreview dir="demos/vben-alert/confirm" />
使用 `prompt` 创建有确认和取消按钮、接受用户输入的提示框。
<DemoPreview dir="demos/vben-alert/prompt" />
## useAlertContext
当弹窗的content、footer、icon使用自定义组件时在这些组件中可以使用 `useAlertContext` 获取当前弹窗的上下文对象,用来主动控制弹窗。
::: tip 注意
`useAlertContext`只能用在setup或者函数式组件中。
:::
### Methods
| 方法 | 描述 | 类型 | 版本要求 |
| --------- | ------------------ | -------- | -------- |
| doConfirm | 调用弹窗的确认操作 | ()=>void | >5.5.4 |
| doCancel | 调用弹窗的取消操作 | ()=>void | >5.5.4 |
## 类型说明
```ts
/** 预置的图标类型 */
export type IconType = 'error' | 'info' | 'question' | 'success' | 'warning';
export type BeforeCloseScope = {
/** 是否为点击确认按钮触发的关闭 */
isConfirm: boolean;
};
/**
* alert 属性
*/
export type AlertProps = {
/** 关闭前的回调如果返回false则终止关闭 */
beforeClose?: (
scope: BeforeCloseScope,
) => boolean | Promise<boolean | undefined> | undefined;
/** 边框 */
bordered?: boolean;
/** 按钮对齐方式 */
buttonAlign?: 'center' | 'end' | 'start';
/** 取消按钮的标题 */
cancelText?: string;
/** 是否居中显示 */
centered?: boolean;
/** 确认按钮的标题 */
confirmText?: string;
/** 弹窗容器的额外样式 */
containerClass?: string;
/** 弹窗提示内容 */
content: Component | string;
/** 弹窗内容的额外样式 */
contentClass?: string;
/** 执行beforeClose回调期间在内容区域显示一个loading遮罩*/
contentMasking?: boolean;
/** 弹窗底部内容(与按钮在同一个容器中) */
footer?: Component | string;
/** 弹窗的图标(在标题的前面) */
icon?: Component | IconType;
/**
* 弹窗遮罩模糊效果
*/
overlayBlur?: number;
/** 是否显示取消按钮 */
showCancel?: boolean;
/** 弹窗标题 */
title?: string;
};
/** prompt 属性 */
export type PromptProps<T = any> = {
/** 关闭前的回调如果返回false则终止关闭 */
beforeClose?: (scope: {
isConfirm: boolean;
value: T | undefined;
}) => boolean | Promise<boolean | undefined> | undefined;
/** 用于接受用户输入的组件 */
component?: Component;
/** 输入组件的属性 */
componentProps?: Recordable<any>;
/** 输入组件的插槽 */
componentSlots?: Recordable<Component>;
/** 默认值 */
defaultValue?: T;
/** 输入组件的值属性名 */
modelPropName?: string;
} & Omit<AlertProps, 'beforeClose'>;
/**
* 函数签名
* alert和confirm的函数签名相同。
* confirm默认会显示取消按钮而alert默认只有一个按钮
* */
export function alert(options: AlertProps): Promise<void>;
export function alert(
message: string,
options?: Partial<AlertProps>,
): Promise<void>;
export function alert(
message: string,
title?: string,
options?: Partial<AlertProps>,
): Promise<void>;
/**
* 弹出输入框的函数签名。
* beforeClose的参数会传入用户当前输入的值
* component指定接受用户输入的组件默认为Input
* componentProps 为输入组件设置的属性数据
* defaultValue 默认的值
* modelPropName 输入组件的值属性名称。默认为modelValue
*/
export async function prompt<T = any>(
options: Omit<AlertProps, 'beforeClose'> & {
beforeClose?: (
scope: BeforeCloseScope & {
/** 输入组件的当前值 */
value: T;
},
) => boolean | Promise<boolean | undefined> | undefined;
component?: Component;
componentProps?: Recordable<any>;
defaultValue?: T;
modelPropName?: string;
},
): Promise<T | undefined>;
```

View File

@@ -0,0 +1,173 @@
---
outline: deep
---
# Vben ApiComponent Api组件包装器
框架提供的API“包装器”它一般不独立使用主要用于包装其它组件为目标组件提供自动获取远程数据的能力但仍然保持了目标组件的原始用法。
::: info 写在前面
我们在各个应用的组件适配器中使用ApiComponent包装了Select、TreeSelect组件使得这些组件可以自动获取远程数据并生成选项。其它类似的组件比如Cascader如有需要也可以参考示例代码自行进行包装。
:::
## 基础用法
通过 `component` 传入其它组件的定义,并配置相关的其它属性(主要是一些名称映射)。包装组件将通过`api`获取数据(`beforerFetch``afterFetch`将分别在`api`运行前、运行后被调用),使用`resultField`从中提取数组,使用`valueField``labelField`等来从数据中提取value和label如果提供了`childrenField`,会将其作为树形结构递归处理每一级数据),之后将处理好的数据通过`optionsPropName`指定的属性传递给目标组件。
::: details 包装级联选择器,点击下拉时开始加载远程数据
```vue
<script lang="ts" setup>
import { ApiComponent } from '@vben/common-ui';
import { Cascader } from 'ant-design-vue';
const treeData: Record<string, any> = [
{
label: '浙江',
value: 'zhejiang',
children: [
{
value: 'hangzhou',
label: '杭州',
children: [
{
value: 'xihu',
label: '西湖',
},
{
value: 'sudi',
label: '苏堤',
},
],
},
{
value: 'jiaxing',
label: '嘉兴',
children: [
{
value: 'wuzhen',
label: '乌镇',
},
{
value: 'meihuazhou',
label: '梅花洲',
},
],
},
{
value: 'zhoushan',
label: '舟山',
children: [
{
value: 'putuoshan',
label: '普陀山',
},
{
value: 'taohuadao',
label: '桃花岛',
},
],
},
],
},
{
label: '江苏',
value: 'jiangsu',
children: [
{
value: 'nanjing',
label: '南京',
children: [
{
value: 'zhonghuamen',
label: '中华门',
},
{
value: 'zijinshan',
label: '紫金山',
},
{
value: 'yuhuatai',
label: '雨花台',
},
],
},
],
},
];
/**
* 模拟请求接口
*/
function fetchApi(): Promise<Record<string, any>> {
return new Promise((resolve) => {
setTimeout(() => {
resolve(treeData);
}, 1000);
});
}
</script>
<template>
<ApiComponent
:api="fetchApi"
:component="Cascader"
:immediate="false"
children-field="children"
loading-slot="suffixIcon"
visible-event="onDropdownVisibleChange"
/>
</template>
```
:::
## 并发和缓存
有些场景下可能需要使用多个ApiComponent它们使用了相同的远程数据源例如用在可编辑的表格中。如果直接将请求后端接口的函数传递给api属性则每一个实例都会访问一次接口这会造成资源浪费是完全没有必要的。Tanstack Query提供了并发控制、缓存、重试等诸多特性我们可以将接口请求函数用useQuery包装一下再传递给ApiComponent这样的话无论页面有多少个使用相同数据源的ApiComponent实例都只会发起一次远程请求。演示效果请参考 [Playground vue-query](https://www.vben.pro/#/demos/features/vue-query),具体代码请查看项目文件[concurrency-caching](https://github.com/vbenjs/vue-vben-admin/blob/main/playground/src/views/demos/features/vue-query/concurrency-caching.vue)
## API
### Props
| 属性名 | 描述 | 类型 | 默认值 | 版本要求 |
| --- | --- | --- | --- | --- |
| modelValue(v-model) | 当前值 | `any` | - | - |
| component | 欲包装的组件(以下称为目标组件) | `Component` | - | - |
| numberToString | 是否将value从数字转为string | `boolean` | `false` | - |
| api | 获取数据的函数 | `(arg?: any) => Promise<OptionsItem[] \| Record<string, any>>` | - | - |
| params | 传递给api的参数 | `Record<string, any>` | - | - |
| resultField | 从api返回的结果中提取options数组的字段名 | `string` | - | - |
| labelField | label字段名 | `string` | `label` | - |
| childrenField | 子级数据字段名,需要层级数据的组件可用 | `string` | `` | - |
| valueField | value字段名 | `string` | `value` | - |
| optionsPropName | 目标组件接收options数据的属性名称 | `string` | `options` | - |
| modelPropName | 目标组件的双向绑定属性名默认为modelValue。部分组件可能为value | `string` | `modelValue` | - |
| immediate | 是否立即调用api | `boolean` | `true` | - |
| alwaysLoad | 每次`visibleEvent`事件发生时都重新请求数据 | `boolean` | `false` | - |
| beforeFetch | 在api请求之前的回调函数 | `AnyPromiseFunction<any, any>` | - | - |
| afterFetch | 在api请求之后的回调函数 | `AnyPromiseFunction<any, any>` | - | - |
| options | 直接传入选项数据也作为api返回空数据时的后备数据 | `OptionsItem[]` | - | - |
| visibleEvent | 触发重新请求数据的事件名 | `string` | - | - |
| loadingSlot | 目标组件的插槽名称,用来显示一个"加载中"的图标 | `string` | - | - |
| autoSelect | 自动设置选项 | `'first' \| 'last' \| 'one'\| ((item: OptionsItem[]) => OptionsItem) \| false` | `false` | >5.5.4 |
#### autoSelect 自动设置选项
如果当前值为undefined在选项数据成功加载之后自动从备选项中选择一个作为当前值。默认值为`false`,即不自动选择选项。注意:该属性不应用于多选组件。可选值有:
- `"first"`:自动选择第一个选项
- `"last"`:自动选择最后一个选项
- `"one"`:有且仅有一个选项时,自动选择它
- `自定义函数`自定义选择逻辑函数的参数为options返回值为选择的选项
- `false`:不自动选择选项
### Methods
| 方法 | 描述 | 类型 | 版本要求 |
| --- | --- | --- | --- |
| getComponentRef | 获取被包装的组件的实例 | ()=>T | >5.5.4 |
| updateParam | 设置接口请求参数将与params属性合并 | (newParams: Record<string, any>)=>void | >5.5.4 |
| getOptions | 获取已加载的选项数据 | ()=>OptionsItem[] | >5.5.4 |
| getValue | 获取当前值 | ()=>any | >5.5.4 |

View File

@@ -0,0 +1,59 @@
---
outline: deep
---
# Vben CountToAnimator 数字动画
框架提供的数字动画组件,支持数字动画效果。
> 如果文档内没有参数说明,可以尝试在在线示例内寻找
::: info 写在前面
如果你觉得现有组件的封装不够理想,或者不完全符合你的需求,大可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由。
:::
## 基础用法
通过 `start-val``end-val`设置数字动画的开始值和结束值, 持续时间`3000`ms。
<DemoPreview dir="demos/vben-count-to-animator/basic" />
## 自定义前缀及分隔符
通过 `prefix``separator` 设置数字动画的前缀和分隔符。
<DemoPreview dir="demos/vben-count-to-animator/custom" />
### Props
| 属性名 | 描述 | 类型 | 默认值 |
| ---------- | -------------- | --------- | -------- |
| startVal | 起始值 | `number` | `0` |
| endVal | 结束值 | `number` | `2021` |
| duration | 动画持续时间 | `number` | `1500` |
| autoplay | 自动执行 | `boolean` | `true` |
| prefix | 前缀 | `string` | - |
| suffix | 后缀 | `string` | - |
| separator | 分隔符 | `string` | `,` |
| color | 字体颜色 | `string` | - |
| useEasing | 是否开启动画 | `boolean` | `true` |
| transition | 动画效果 | `string` | `linear` |
| decimals | 保留小数点位数 | `number` | `0` |
### Events
| 事件名 | 描述 | 类型 |
| -------------- | -------------- | -------------- |
| started | 动画已开始 | `()=>void` |
| finished | 动画已结束 | `()=>void` |
| ~~onStarted~~ | ~~动画已开始~~ | ~~`()=>void`~~ |
| ~~onFinished~~ | ~~动画已结束~~ | ~~`()=>void`~~ |
### Methods
| 方法名 | 描述 | 类型 |
| ------ | ------------ | ---------- |
| start | 开始执行动画 | `()=>void` |
| reset | 重置 | `()=>void` |

View File

@@ -0,0 +1,156 @@
---
outline: deep
---
# Vben Drawer 抽屉
框架提供的抽屉组件,支持`自动高度``loading`等功能。
> 如果文档内没有参数说明,可以尝试在在线示例内寻找
::: info 写在前面
如果你觉得现有组件的封装不够理想,或者不完全符合你的需求,大可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由。
:::
::: tip README
下方示例代码中的,存在一些国际化、主题色未适配问题,这些问题只在文档内会出现,实际使用并不会有这些问题,可忽略,不必纠结。
:::
## 基础用法
使用 `useVbenDrawer` 创建最基础的模态框。
<DemoPreview dir="demos/vben-drawer/basic" />
## 组件抽离
Drawer 内的内容一般业务中,会比较复杂,所以我们可以将 drawer 内的内容抽离出来,也方便复用。通过 `connectedComponent` 参数,可以将内外组件进行连接,而不用其他任何操作。
<DemoPreview dir="demos/vben-drawer/extra" />
## 自动计算高度
弹窗会自动计算内容高度,超过一定高度会出现滚动条,同时结合 `loading` 效果以及使用 `prepend-footer` 插槽。
<DemoPreview dir="demos/vben-drawer/auto-height" />
## 使用 Api
通过 `drawerApi` 可以调用 drawer 的方法以及使用 `setState` 更新 drawer 的状态。
<DemoPreview dir="demos/vben-drawer/dynamic" />
## 数据共享
如果你使用了 `connectedComponent` 参数,那么内外组件会共享数据,比如一些表单回填等操作。可以用 `drawerApi` 来获取数据和设置数据,配合 `onOpenChange`,可以满足大部分的需求。
<DemoPreview dir="demos/vben-drawer/shared-data" />
::: info 注意
- `VbenDrawer` 组件对与参数的处理优先级是 `slot` > `props` > `state`(通过api更新的状态以及useVbenDrawer参数)。如果你已经传入了 `slot` 或者 `props`,那么 `setState` 将不会生效,这种情况下你可以通过 `slot` 或者 `props` 来更新状态。
- 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenDrawer`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onConfirm`,那么以内部的 `onConfirm` 为准。`onOpenChange`事件除外,内外都会触发。
- 使用了`connectedComponent`参数时,可以配置`destroyOnClose`属性来决定当关闭弹窗时,是否要销毁`connectedComponent`组件(重新创建`connectedComponent`组件,这将会把其内部所有的变量、状态、数据等恢复到初始状态。)。
- 如果抽屉的默认行为不符合你的预期,可以在`src\bootstrap.ts`中修改`setDefaultDrawerProps`的参数来设置默认的属性如默认隐藏全屏按钮修改默认ZIndex等。
:::
## API
```ts
// Drawer 为弹窗组件
// drawerApi 为弹窗的方法
const [Drawer, drawerApi] = useVbenDrawer({
// 属性
// 事件
});
```
### Props
所有属性都可以传入 `useVbenDrawer` 的第一个参数中。
| 属性名 | 描述 | 类型 | 默认值 |
| --- | --- | --- | --- |
| appendToMain | 是否挂载到内容区域默认挂载到body | `boolean` | `false` |
| connectedComponent | 连接另一个Modal组件 | `Component` | - |
| destroyOnClose | 关闭时销毁 | `boolean` | `false` |
| title | 标题 | `string\|slot` | - |
| titleTooltip | 标题提示信息 | `string\|slot` | - |
| description | 描述信息 | `string\|slot` | - |
| isOpen | 弹窗打开状态 | `boolean` | `false` |
| loading | 弹窗加载状态 | `boolean` | `false` |
| closable | 显示关闭按钮 | `boolean` | `true` |
| closeIconPlacement | 关闭按钮位置 | `'left'\|'right'` | `right` |
| modal | 显示遮罩 | `boolean` | `true` |
| header | 显示header | `boolean` | `true` |
| footer | 显示footer | `boolean\|slot` | `true` |
| confirmLoading | 确认按钮loading状态 | `boolean` | `false` |
| closeOnClickModal | 点击遮罩关闭弹窗 | `boolean` | `true` |
| closeOnPressEscape | esc 关闭弹窗 | `boolean` | `true` |
| confirmText | 确认按钮文本 | `string\|slot` | `确认` |
| cancelText | 取消按钮文本 | `string\|slot` | `取消` |
| placement | 抽屉弹出位置 | `'left'\|'right'\|'top'\|'bottom'` | `right` |
| showCancelButton | 显示取消按钮 | `boolean` | `true` |
| showConfirmButton | 显示确认按钮文本 | `boolean` | `true` |
| class | modal的class宽度通过这个配置 | `string` | - |
| contentClass | modal内容区域的class | `string` | - |
| footerClass | modal底部区域的class | `string` | - |
| headerClass | modal顶部区域的class | `string` | - |
| zIndex | 抽屉的ZIndex层级 | `number` | `1000` |
| overlayBlur | 遮罩模糊度 | `number` | - |
::: info appendToMain
`appendToMain`可以指定将抽屉挂载到内容区域打开抽屉时内容区域以外的部分标签栏、导航菜单等等不会被遮挡。默认情况下抽屉会挂载到body上。但是挂载到内容区域时作为页面根容器的`Page`组件,需要设置`auto-content-height`属性,以便抽屉能够正确计算高度。
:::
### Event
以下事件,只有在 `useVbenDrawer({onCancel:()=>{}})` 中传入才会生效。
| 事件名 | 描述 | 类型 | 版本限制 |
| --- | --- | --- | --- |
| onBeforeClose | 关闭前触发,返回 `false`则禁止关闭 | `()=>boolean` | --- |
| onCancel | 点击取消按钮触发 | `()=>void` | --- |
| onClosed | 关闭动画播放完毕时触发 | `()=>void` | >5.5.2 |
| onConfirm | 点击确认按钮触发 | `()=>void` | --- |
| onOpenChange | 关闭或者打开弹窗时触发 | `(isOpen:boolean)=>void` | --- |
| onOpened | 打开动画播放完毕时触发 | `()=>void` | >5.5.2 |
### Slots
除了上面的属性类型包含`slot`,还可以通过插槽来自定义弹窗的内容。
| 插槽名 | 描述 |
| -------------- | -------------------------------------------------- |
| default | 默认插槽 - 弹窗内容 |
| prepend-footer | 取消按钮左侧 |
| center-footer | 取消按钮和确认按钮中间(不使用 footer 插槽时有效) |
| append-footer | 确认按钮右侧 |
| close-icon | 关闭按钮图标 |
| extra | 额外内容(标题右侧) |
### drawerApi
| 方法 | 描述 | 类型 | 版本限制 |
| --- | --- | --- | --- |
| setState | 动态设置弹窗状态属性 | `(((prev: ModalState) => Partial<ModalState>)\| Partial<ModalState>)=>drawerApi` |
| open | 打开弹窗 | `()=>void` | --- |
| close | 关闭弹窗 | `()=>void` | --- |
| setData | 设置共享数据 | `<T>(data:T)=>drawerApi` | --- |
| getData | 获取共享数据 | `<T>()=>T` | --- |
| useStore | 获取可响应式状态 | - | --- |
| lock | 将抽屉标记为提交中,锁定当前状态 | `(isLock:boolean)=>drawerApi` | >5.5.3 |
| unlock | lock方法的反操作解除抽屉的锁定状态也是lock(false)的别名 | `()=>drawerApi` | >5.5.3 |
::: info lock
`lock`方法用于锁定抽屉的状态一般用于提交数据的过程中防止用户重复提交或者抽屉被意外关闭、表单数据被改变等等。当处于锁定状态时抽屉的确认按钮会变为loading状态同时禁用取消按钮和关闭按钮、禁止ESC或者点击遮罩等方式关闭抽屉、开启抽屉的spinner动画以遮挡弹窗内容。调用`close`方法关闭处于锁定状态的抽屉时,会自动解锁。要主动解除这种状态,可以调用`unlock`方法或者再次调用lock方法并传入false参数。
:::

View File

@@ -0,0 +1,64 @@
---
outline: deep
---
# Vben EllipsisText 省略文本
框架提供的文本展示组件可配置超长省略、tooltip提示、展开收起等功能。
> 如果文档内没有参数说明,可以尝试在在线示例内寻找
## 基础用法
通过默认插槽设置文本内容,`maxWidth`属性设置最大宽度。
<DemoPreview dir="demos/vben-ellipsis-text/line" />
## 可折叠的文本块
通过`line`设置折叠后的行数,`expand`属性设置是否支持展开收起。
<DemoPreview dir="demos/vben-ellipsis-text/expand" />
## 自定义提示浮层
通过名为`tooltip`的插槽定制提示信息。
<DemoPreview dir="demos/vben-ellipsis-text/tooltip" />
## 自动显示 tooltip
通过`tooltip-when-ellipsis`设置,仅在文本长度超出导致省略号出现时才触发 tooltip。
<DemoPreview dir="demos/vben-ellipsis-text/auto-display" />
## API
### Props
| 属性名 | 描述 | 类型 | 默认值 |
| --- | --- | --- | --- |
| expand | 支持点击展开或收起 | `boolean` | `false` |
| line | 文本最大行数 | `number` | `1` |
| maxWidth | 文本区域最大宽度 | `number \| string` | `'100%'` |
| placement | 提示浮层的位置 | `'bottom'\|'left'\|'right'\|'top'` | `'top'` |
| tooltip | 启用文本提示 | `boolean` | `true` |
| tooltipWhenEllipsis | 内容超出,自动启用文本提示 | `boolean` | `false` |
| ellipsisThreshold | 设置 tooltipWhenEllipsis 后才生效,文本截断检测的像素差异阈值,越大则判断越严格,如果碰见异常情况可以自己设置阈值 | `number` | `3` |
| tooltipBackgroundColor | 提示文本的背景颜色 | `string` | - |
| tooltipColor | 提示文本的颜色 | `string` | - |
| tooltipFontSize | 提示文本的大小 | `string` | - |
| tooltipMaxWidth | 提示浮层的最大宽度。如不设置则保持与文本宽度一致 | `number` | - |
| tooltipOverlayStyle | 提示框内容区域样式 | `CSSProperties` | `{ textAlign: 'justify' }` |
### Events
| 事件名 | 描述 | 类型 |
| ------------ | ------------ | -------------------------- |
| expandChange | 展开状态改变 | `(isExpand:boolean)=>void` |
### Slots
| 插槽名 | 描述 |
| ------- | -------------------------------- |
| tooltip | 启用文本提示时,用来定制提示内容 |

View File

@@ -0,0 +1,560 @@
---
outline: deep
---
# Vben Form 表单
框架提供的表单组件,可适配 `Element Plus``Ant Design Vue``Naive UI` 等框架。
> 如果文档内没有参数说明,可以尝试在在线示例内寻找
::: info 写在前面
如果你觉得现有组件的封装不够理想,或者不完全符合你的需求,大可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由。
:::
## 适配器
表单底层使用 [vee-validate](https://vee-validate.logaretm.com/v4/) 进行表单验证,所以你可以使用 `vee-validate` 的所有功能。对于不同的 UI 框架,我们提供了适配器,以便更好的适配不同的 UI 框架。
### 适配器说明
每个应用都有不同的 UI 框架,所以在应用的 `src/adapter/form``src/adapter/component` 内部,你可以根据自己的需求,进行组件适配。下面是 `Ant Design Vue` 的适配器示例代码,可根据注释查看说明:
::: details ant design vue 表单适配器
```ts
import type {
VbenFormSchema as FormSchema,
VbenFormProps,
} from '@vben/common-ui';
import type { ComponentType } from './component';
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
import { $t } from '@vben/locales';
setupVbenForm<ComponentType>({
config: {
// ant design vue组件库默认都是 v-model:value
baseModelPropName: 'value',
// 一些组件是 v-model:checked 或者 v-model:fileList
modelPropNameMap: {
Checkbox: 'checked',
Radio: 'checked',
Switch: 'checked',
Upload: 'fileList',
},
},
defineRules: {
// 输入项目必填国际化适配
required: (value, _params, ctx) => {
if (value === undefined || value === null || value.length === 0) {
return $t('ui.formRules.required', [ctx.label]);
}
return true;
},
// 选择项目必填国际化适配
selectRequired: (value, _params, ctx) => {
if (value === undefined || value === null) {
return $t('ui.formRules.selectRequired', [ctx.label]);
}
return true;
},
},
});
const useVbenForm = useForm<ComponentType>;
export { useVbenForm, z };
export type VbenFormSchema = FormSchema<ComponentType>;
export type { VbenFormProps };
```
:::
::: details ant design vue 组件适配器
```ts
/**
* 通用组件共同的使用的基础组件,原先放在 adapter/form 内部,限制了使用范围,这里提取出来,方便其他地方使用
* 可用于 vben-form、vben-modal、vben-drawer 等组件使用,
*/
import type { BaseFormComponentType } from '@vben/common-ui';
import type { Component, SetupContext } from 'vue';
import { h } from 'vue';
import { globalShareState, IconPicker } from '@vben/common-ui';
import { $t } from '@vben/locales';
import {
AutoComplete,
Button,
Checkbox,
CheckboxGroup,
DatePicker,
Divider,
Input,
InputNumber,
InputPassword,
Mentions,
notification,
Radio,
RadioGroup,
RangePicker,
Rate,
Select,
Space,
Switch,
Textarea,
TimePicker,
TreeSelect,
Upload,
} from 'ant-design-vue';
const withDefaultPlaceholder = <T extends Component>(
component: T,
type: 'input' | 'select',
) => {
return (props: any, { attrs, slots }: Omit<SetupContext, 'expose'>) => {
const placeholder = props?.placeholder || $t(`ui.placeholder.${type}`);
return h(component, { ...props, ...attrs, placeholder }, slots);
};
};
// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
export type ComponentType =
| 'AutoComplete'
| 'Checkbox'
| 'CheckboxGroup'
| 'DatePicker'
| 'DefaultButton'
| 'Divider'
| 'Input'
| 'InputNumber'
| 'InputPassword'
| 'Mentions'
| 'PrimaryButton'
| 'Radio'
| 'RadioGroup'
| 'RangePicker'
| 'Rate'
| 'Select'
| 'Space'
| 'Switch'
| 'Textarea'
| 'TimePicker'
| 'TreeSelect'
| 'Upload'
| 'IconPicker';
| BaseFormComponentType;
async function initComponentAdapter() {
const components: Partial<Record<ComponentType, Component>> = {
// 如果你的组件体积比较大,可以使用异步加载
// Button: () =>
// import('xxx').then((res) => res.Button),
AutoComplete,
Checkbox,
CheckboxGroup,
DatePicker,
// 自定义默认按钮
DefaultButton: (props, { attrs, slots }) => {
return h(Button, { ...props, attrs, type: 'default' }, slots);
},
Divider,
IconPicker,
Input: withDefaultPlaceholder(Input, 'input'),
InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
Mentions: withDefaultPlaceholder(Mentions, 'input'),
// 自定义主要按钮
PrimaryButton: (props, { attrs, slots }) => {
return h(Button, { ...props, attrs, type: 'primary' }, slots);
},
Radio,
RadioGroup,
RangePicker,
Rate,
Select: withDefaultPlaceholder(Select, 'select'),
Space,
Switch,
Textarea: withDefaultPlaceholder(Textarea, 'input'),
TimePicker,
TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'),
Upload,
};
// 将组件注册到全局共享状态中
globalShareState.setComponents(components);
// 定义全局共享状态中的消息提示
globalShareState.defineMessage({
// 复制成功消息提示
copyPreferencesSuccess: (title, content) => {
notification.success({
description: content,
message: title,
placement: 'bottomRight',
});
},
});
}
export { initComponentAdapter };
```
:::
## 基础用法
::: tip README
下方示例代码中的,存在一些国际化、主题色未适配问题,这些问题只在文档内会出现,实际使用并不会有这些问题,可忽略,不必纠结。
:::
使用 `useVbenForm` 创建最基础的表单。
<DemoPreview dir="demos/vben-form/basic" />
## 查询表单
查询表单是一种特殊的表单,用于查询数据。查询表单不会触发表单验证,只会触发查询事件。
<DemoPreview dir="demos/vben-form/query" />
## 表单校验
表单校验是一个非常重要的功能,可以通过 `rules` 属性进行校验。
<DemoPreview dir="demos/vben-form/rules" />
## 表单联动
表单联动是一个非常常见的功能,可以通过 `dependencies` 属性进行联动。
_注意_ 需要指定 `dependencies``triggerFields` 属性,设置由谁的改动来触发,以便表单组件能够正确的联动。
<DemoPreview dir="demos/vben-form/dynamic" />
## 自定义组件
如果你的业务组件库没有提供某个组件,你可以自行封装一个组件,然后加到表单内部。
<DemoPreview dir="demos/vben-form/custom" />
## 操作
一些常见的表单操作。
<DemoPreview dir="demos/vben-form/api" />
## API
`useVbenForm` 返回一个数组,第一个元素是表单组件,第二个元素是表单的方法。
```vue
<script setup lang="ts">
import { useVbenForm } from '#/adapter/form';
// Form 为弹窗组件
// formApi 为弹窗的方法
const [Form, formApi] = useVbenForm({
// 属性
// 事件
});
</script>
<template>
<Form />
</template>
```
### FormApi
useVbenForm 返回的第二个参数,是一个对象,包含了一些表单的方法。
| 方法名 | 描述 | 类型 | 版本号 |
| --- | --- | --- | --- |
| submitForm | 提交表单 | `(e:Event)=>Promise<Record<string,any>>` | - |
| validateAndSubmitForm | 提交并校验表单 | `(e:Event)=>Promise<Record<string,any>>` | - |
| resetForm | 重置表单 | `()=>Promise<void>` | - |
| setValues | 设置表单值, 默认会过滤不在schema中定义的field, 可通过filterFields形参关闭过滤 | `(fields: Record<string, any>, filterFields?: boolean, shouldValidate?: boolean) => Promise<void>` | - |
| getValues | 获取表单值 | `(fields:Record<string, any>,shouldValidate: boolean = false)=>Promise<void>` | - |
| validate | 表单校验 | `()=>Promise<void>` | - |
| validateField | 校验指定字段 | `(fieldName: string)=>Promise<ValidationResult<unknown>>` | - |
| isFieldValid | 检查某个字段是否已通过校验 | `(fieldName: string)=>Promise<boolean>` | - |
| resetValidate | 重置表单校验 | `()=>Promise<void>` | - |
| updateSchema | 更新formSchema | `(schema:FormSchema[])=>void` | - |
| setFieldValue | 设置字段值 | `(field: string, value: any, shouldValidate?: boolean)=>Promise<void>` | - |
| setState | 设置组件状态props | `(stateOrFn:\| ((prev: VbenFormProps) => Partial<VbenFormProps>)\| Partial<VbenFormProps>)=>Promise<void>` | - |
| getState | 获取组件状态props | `()=>Promise<VbenFormProps>` | - |
| form | 表单对象实例,可以操作表单,见 [useForm](https://vee-validate.logaretm.com/v4/api/use-form/) | - | - |
| getFieldComponentRef | 获取指定字段的组件实例 | `<T=unknown>(fieldName: string)=>T` | >5.5.3 |
| getFocusedField | 获取当前已获得焦点的字段 | `()=>string\|undefined` | >5.5.3 |
## Props
所有属性都可以传入 `useVbenForm` 的第一个参数中。
| 属性名 | 描述 | 类型 | 默认值 |
| --- | --- | --- | --- |
| layout | 表单项布局 | `'horizontal' \| 'vertical'` | `horizontal` |
| showCollapseButton | 是否显示折叠按钮 | `boolean` | `false` |
| wrapperClass | 表单的布局基于tailwindcss | `any` | - |
| actionWrapperClass | 表单操作区域class | `any` | - |
| handleReset | 表单重置回调 | `(values: Record<string, any>,) => Promise<void> \| void` | - |
| handleSubmit | 表单提交回调 | `(values: Record<string, any>,) => Promise<void> \| void` | - |
| handleValuesChange | 表单值变化回调 | `(values: Record<string, any>, fieldsChanged: string[]) => void` | - |
| actionButtonsReverse | 调换操作按钮位置 | `boolean` | `false` |
| resetButtonOptions | 重置按钮组件参数 | `ActionButtonOptions` | - |
| submitButtonOptions | 提交按钮组件参数 | `ActionButtonOptions` | - |
| showDefaultActions | 是否显示默认操作按钮 | `boolean` | `true` |
| collapsed | 是否折叠,在`showCollapseButton``true`时生效 | `boolean` | `false` |
| collapseTriggerResize | 折叠时,触发`resize`事件 | `boolean` | `false` |
| collapsedRows | 折叠时保持的行数 | `number` | `1` |
| fieldMappingTime | 用于将表单内的数组值映射成 2 个字段 | `[string, [string, string],Nullable<string>\|[string,string]\|((any,string)=>any)?][]` | - |
| commonConfig | 表单项的通用配置,每个配置都会传递到每个表单项,表单项可覆盖 | `FormCommonConfig` | - |
| schema | 表单项的每一项配置 | `FormSchema[]` | - |
| submitOnEnter | 按下回车健时提交表单 | `boolean` | false |
| submitOnChange | 字段值改变时提交表单(内部防抖,这个属性一般用于表格的搜索表单) | `boolean` | false |
| compact | 是否紧凑模式(忽略为校验信息所预留的空间) | `boolean` | false |
::: tip handleValuesChange
`handleValuesChange` 回调函数的第一个参数`values`装载了表单改变后的当前值对象,第二个参数`fieldsChanged`是一个数组包含了所有被改变的字段名。注意第二个参数仅在v5.5.4(不含)以上版本可用并且传递的是已在schema中定义的字段名。如果你使用了字段映射并且需要检查是哪些字段发生了变化的话请注意该参数并不会包含映射后的字段名。
:::
::: tip fieldMappingTime
此属性用于将表单内的数组值映射成 2 个字段它应当传入一个数组数组的每一项是一个映射规则规则的第一个成员是一个字符串表示需要映射的字段名第二个成员是一个数组表示映射后的字段名第三个成员是一个可选的格式掩码用于格式化日期时间字段也可以提供一个格式化函数参数分别为当前值和当前字段名返回格式化后的值。如果明确地将格式掩码设为null则原值映射而不进行格式化适用于非日期时间字段。例如`[['timeRange', ['startTime', 'endTime'], 'YYYY-MM-DD']]``timeRange`应当是一个至少具有2个成员的数组类型的值。Form会将`timeRange`的值前两个值分别按照格式掩码`YYYY-MM-DD`格式化后映射到`startTime``endTime`字段上。每一项的第三个参数是一个可选的格式掩码,
:::
### TS 类型说明
::: details ActionButtonOptions
```ts
export interface ActionButtonOptions {
/** 样式 */
class?: ClassType;
/** 是否禁用 */
disabled?: boolean;
/** 是否加载中 */
loading?: boolean;
/** 按钮大小 */
size?: ButtonVariantSize;
/** 按钮类型 */
variant?: ButtonVariants;
/** 是否显示 */
show?: boolean;
/** 按钮文本 */
content?: string;
/** 任意属性 */
[key: string]: any;
}
```
:::
::: details FormCommonConfig
```ts
export interface FormCommonConfig {
/**
* 所有表单项的props
*/
componentProps?: ComponentProps;
/**
* 所有表单项的控件样式
*/
controlClass?: string;
/**
* 在表单项的Label后显示一个冒号
*/
colon?: boolean;
/**
* 所有表单项的禁用状态
* @default false
*/
disabled?: boolean;
/**
* 所有表单项的控件样式
* @default {}
*/
formFieldProps?: Partial<typeof Field>;
/**
* 所有表单项的栅格布局
* @default ""
*/
formItemClass?: string;
/**
* 隐藏所有表单项label
* @default false
*/
hideLabel?: boolean;
/**
* 是否隐藏必填标记
* @default false
*/
hideRequiredMark?: boolean;
/**
* 所有表单项的label样式
* @default ""
*/
labelClass?: string;
/**
* 所有表单项的label宽度
*/
labelWidth?: number;
/**
* 所有表单项的model属性名。使用自定义组件时可通过此配置指定组件的model属性名。已经在modelPropNameMap中注册的组件不受此配置影响
* @default "modelValue"
*/
modelPropName?: string;
/**
* 所有表单项的wrapper样式
*/
wrapperClass?: string;
}
```
:::
::: details FormSchema
```ts
export interface FormSchema<
T extends BaseFormComponentType = BaseFormComponentType,
> extends FormCommonConfig {
/** 组件 */
component: Component | T;
/** 组件参数 */
componentProps?: ComponentProps;
/** 默认值 */
defaultValue?: any;
/** 依赖 */
dependencies?: FormItemDependencies;
/** 描述 */
description?: string;
/** 字段名,也作为自定义插槽的名称 */
fieldName: string;
/** 帮助信息 */
help?: CustomRenderType;
/** 表单的标签如果是一个string会用于默认必选规则的消息提示 */
label?: CustomRenderType;
/** 自定义组件内部渲染 */
renderComponentContent?: RenderComponentContentType;
/** 字段规则 */
rules?: FormSchemaRuleType;
/** 后缀 */
suffix?: CustomRenderType;
}
```
:::
### 表单联动
表单联动需要通过 schema 内的 `dependencies` 属性进行联动,允许您添加字段之间的依赖项,以根据其他字段的值控制字段。
```ts
dependencies: {
// 触发字段。只有这些字段值变动时,联动才会触发
triggerFields: ['name'],
// 动态判断当前字段是否需要显示,不显示则直接销毁
if(values,formApi){},
// 动态判断当前字段是否需要显示不显示用css隐藏
show(values,formApi){},
// 动态判断当前字段是否需要禁用
disabled(values,formApi){},
// 字段变更时,都会触发该函数
trigger(values,formApi){},
// 动态rules
rules(values,formApi){},
// 动态必填
required(values,formApi){},
// 动态组件参数
componentProps(values,formApi){},
}
```
### 表单校验
表单校验需要通过 schema 内的 `rules` 属性进行配置。
rules的值可以是字符串预定义的校验规则名称也可以是一个zod的schema。
#### 预定义的校验规则
```ts
// 表示字段必填默认会根据适配器的required进行国际化
{
rules: 'required';
}
// 表示字段必填默认会根据适配器的required进行国际化用于下拉选择之类
{
rules: 'selectRequired';
}
```
#### zod
rules也支持 zod 的 schema可以进行更复杂的校验zod 的使用请查看 [zod文档](https://zod.dev/)。
```ts
import { z } from '#/adapter/form';
// 基础类型
{
rules: z.string().min(1, { message: '请输入字符串' });
}
// 可选(可以是undefined)并且携带默认值。注意zod的optional不包括空字符串''
{
rules: z.string().default('默认值').optional();
}
// 可以是空字符串、undefined或者一个邮箱地址(两种不同的用法)
{
rules: z.union([z.string().email().optional(), z.literal('')]);
}
{
rules: z.string().email().or(z.literal('')).optional();
}
// 复杂校验
{
z.string()
.min(1, { message: '请输入' })
.refine((value) => value === '123', {
message: '值必须为123',
});
}
```
## Slots
可以使用以下插槽在表单中插入自定义的内容
| 插槽名 | 描述 |
| ------------- | ------------------ |
| reset-before | 重置按钮之前的位置 |
| submit-before | 提交按钮之前的位置 |
| expand-before | 展开按钮之前的位置 |
| expand-after | 展开按钮之后的位置 |
::: tip 字段插槽
除了以上内置插槽之外,`schema`属性中每个字段的`fieldName`都可以作为插槽名称,这些字段插槽的优先级高于`component`定义的组件。也就是说,当提供了与`fieldName`同名的插槽时,这些插槽的内容将会作为这些字段的组件,此时`component`的值将会被忽略。
:::

View File

@@ -0,0 +1,164 @@
---
outline: deep
---
# Vben Modal 模态框
框架提供的模态框组件,支持`拖拽``全屏``自动高度``loading`等功能。
> 如果文档内没有参数说明,可以尝试在在线示例内寻找
::: info 写在前面
如果你觉得现有组件的封装不够理想,或者不完全符合你的需求,大可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由。
:::
::: tip README
下方示例代码中的,存在一些国际化、主题色未适配问题,这些问题只在文档内会出现,实际使用并不会有这些问题,可忽略,不必纠结。
:::
## 基础用法
使用 `useVbenModal` 创建最基础的模态框。
<DemoPreview dir="demos/vben-modal/basic" />
## 组件抽离
Modal 内的内容一般业务中,会比较复杂,所以我们可以将 modal 内的内容抽离出来,也方便复用。通过 `connectedComponent` 参数,可以将内外组件进行连接,而不用其他任何操作。
<DemoPreview dir="demos/vben-modal/extra" />
## 开启拖拽
通过 `draggable` 参数,可开启拖拽功能。
<DemoPreview dir="demos/vben-modal/draggable" />
## 自动计算高度
弹窗会自动计算内容高度,超过一定高度会出现滚动条,同时结合 `loading` 效果以及使用 `prepend-footer` 插槽。
<DemoPreview dir="demos/vben-modal/auto-height" />
## 使用 Api
通过 `modalApi` 可以调用 modal 的方法以及使用 `setState` 更新 modal 的状态。
<DemoPreview dir="demos/vben-modal/dynamic" />
## 数据共享
如果你使用了 `connectedComponent` 参数,那么内外组件会共享数据,比如一些表单回填等操作。可以用 `modalApi` 来获取数据和设置数据,配合 `onOpenChange`,可以满足大部分的需求。
<DemoPreview dir="demos/vben-modal/shared-data" />
::: info 注意
- `VbenModal` 组件对与参数的处理优先级是 `slot` > `props` > `state`(通过api更新的状态以及useVbenModal参数)。如果你已经传入了 `slot` 或者 `props`,那么 `setState` 将不会生效,这种情况下你可以通过 `slot` 或者 `props` 来更新状态。
- 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenModal`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onConfirm`,那么以内部的 `onConfirm` 为准。`onOpenChange`事件除外,内外都会触发。另外,如果设置了`destroyOnClose`内部Modal及其子组件会在被关闭后<b>完全销毁</b>
- 如果弹窗的默认行为不符合你的预期,可以在`src\bootstrap.ts`中修改`setDefaultModalProps`的参数来设置默认的属性如默认隐藏全屏按钮修改默认ZIndex等。
:::
## API
```ts
// Modal 为弹窗组件
// modalApi 为弹窗的方法
const [Modal, modalApi] = useVbenModal({
// 属性
// 事件
});
```
### Props
所有属性都可以传入 `useVbenModal` 的第一个参数中。
| 属性名 | 描述 | 类型 | 默认值 |
| --- | --- | --- | --- |
| appendToMain | 是否挂载到内容区域默认挂载到body | `boolean` | `false` |
| connectedComponent | 连接另一个Modal组件 | `Component` | - |
| destroyOnClose | 关闭时销毁 | `boolean` | `false` |
| title | 标题 | `string\|slot` | - |
| titleTooltip | 标题提示信息 | `string\|slot` | - |
| description | 描述信息 | `string\|slot` | - |
| isOpen | 弹窗打开状态 | `boolean` | `false` |
| loading | 弹窗加载状态 | `boolean` | `false` |
| fullscreen | 全屏显示 | `boolean` | `false` |
| fullscreenButton | 显示全屏按钮 | `boolean` | `true` |
| draggable | 可拖拽 | `boolean` | `false` |
| closable | 显示关闭按钮 | `boolean` | `true` |
| centered | 居中显示 | `boolean` | `false` |
| modal | 显示遮罩 | `boolean` | `true` |
| header | 显示header | `boolean` | `true` |
| footer | 显示footer | `boolean\|slot` | `true` |
| confirmDisabled | 禁用确认按钮 | `boolean` | `false` |
| confirmLoading | 确认按钮loading状态 | `boolean` | `false` |
| closeOnClickModal | 点击遮罩关闭弹窗 | `boolean` | `true` |
| closeOnPressEscape | esc 关闭弹窗 | `boolean` | `true` |
| confirmText | 确认按钮文本 | `string\|slot` | `确认` |
| cancelText | 取消按钮文本 | `string\|slot` | `取消` |
| showCancelButton | 显示取消按钮 | `boolean` | `true` |
| showConfirmButton | 显示确认按钮 | `boolean` | `true` |
| class | modal的class宽度通过这个配置 | `string` | - |
| contentClass | modal内容区域的class | `string` | - |
| footerClass | modal底部区域的class | `string` | - |
| headerClass | modal顶部区域的class | `string` | - |
| bordered | 是否显示border | `boolean` | `false` |
| zIndex | 弹窗的ZIndex层级 | `number` | `1000` |
| overlayBlur | 遮罩模糊度 | `number` | - |
| submitting | 标记为提交中,锁定弹窗当前状态 | `boolean` | `false` |
::: info appendToMain
`appendToMain`可以指定将弹窗挂载到内容区域打开这种弹窗时内容区域以外的部分标签栏、导航菜单等等不会被遮挡。默认情况下弹窗会挂载到body上。但是挂载到内容区域时作为页面根容器的`Page`组件,需要设置`auto-content-height`属性,以便弹窗能够正确计算高度。
:::
### Event
以下事件,只有在 `useVbenModal({onCancel:()=>{}})` 中传入才会生效。
| 事件名 | 描述 | 类型 | 版本号 |
| --- | --- | --- | --- |
| onBeforeClose | 关闭前触发,返回 `false`或者被`reject`则禁止关闭 | `()=>Promise<boolean>\|boolean` | >5.5.2支持Promise |
| onCancel | 点击取消按钮触发 | `()=>void` | |
| onClosed | 关闭动画播放完毕时触发 | `()=>void` | >5.4.3 |
| onConfirm | 点击确认按钮触发 | `()=>void` | |
| onOpenChange | 关闭或者打开弹窗时触发 | `(isOpen:boolean)=>void` | |
| onOpened | 打开动画播放完毕时触发 | `()=>void` | >5.4.3 |
### Slots
除了上面的属性类型包含`slot`,还可以通过插槽来自定义弹窗的内容。
| 插槽名 | 描述 |
| -------------- | -------------------------------------------------- |
| default | 默认插槽 - 弹窗内容 |
| prepend-footer | 取消按钮左侧 |
| center-footer | 取消按钮和确认按钮中间(不使用 footer 插槽时有效) |
| append-footer | 确认按钮右侧 |
### modalApi
| 方法 | 描述 | 类型 | 版本 |
| --- | --- | --- | --- |
| setState | 动态设置弹窗状态属性 | `(((prev: ModalState) => Partial<ModalState>)\| Partial<ModalState>)=>modalApi` | - |
| open | 打开弹窗 | `()=>void` | - |
| close | 关闭弹窗 | `()=>void` | - |
| setData | 设置共享数据 | `<T>(data:T)=>modalApi` | - |
| getData | 获取共享数据 | `<T>()=>T` | - |
| useStore | 获取可响应式状态 | - | - |
| lock | 将弹窗标记为提交中,锁定当前状态 | `(isLock:boolean)=>modalApi` | >5.5.2 |
| unlock | lock方法的反操作解除弹窗的锁定状态也是lock(false)的别名 | `()=>modalApi` | >5.5.3 |
::: info lock
`lock`方法用于锁定当前弹窗的状态一般用于提交数据的过程中防止用户重复提交或者弹窗被意外关闭、表单数据被改变等等。当处于锁定状态时弹窗的确认按钮会变为loading状态同时禁用取消按钮和关闭按钮、禁止ESC或者点击遮罩等方式关闭弹窗、开启弹窗的spinner动画以遮挡弹窗内容。调用`close`方法关闭处于锁定状态的弹窗时,会自动解锁。要主动解除这种状态,可以调用`unlock`方法或者再次调用lock方法并传入false参数。
:::

View File

@@ -0,0 +1,276 @@
---
outline: deep
---
# Vben Vxe Table 表格
框架提供的Table 列表组件基于 [vxe-table](https://vxetable.cn/v4/#/grid/api?apiKey=grid),结合`Vben Form 表单`进行了二次封装。
其中,表头的 **表单搜索** 部分采用了`Vben Form表单`,表格主体部分使用了`vxe-grid`组件,支持表格的分页、排序、筛选等功能。
> 如果文档内没有参数说明,可以尝试在在线示例或者在 [vxe-grid 官方API 文档](https://vxetable.cn/v4/#/grid/api?apiKey=grid) 内寻找
::: info 写在前面
如果你觉得现有组件的封装不够理想,或者不完全符合你的需求,大可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由。
:::
## 适配器
表格底层使用 [vxe-table](https://vxetable.cn/#/start/install) 进行实现,所以你可以使用 `vxe-table` 的所有功能。对于不同的 UI 框架,我们提供了适配器,以便更好的适配不同的 UI 框架。
### 适配器说明
每个应用都可以自己配置`vxe-table`的适配器,你可以根据自己的需求。下面是一个简单的配置示例:
::: details vxe-table 表格适配器
```ts
import { h } from 'vue';
import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table';
import { Button, Image } from 'ant-design-vue';
import { useVbenForm } from './form';
setupVbenVxeTable({
configVxeTable: (vxeUI) => {
vxeUI.setConfig({
grid: {
align: 'center',
border: false,
columnConfig: {
resizable: true,
},
minHeight: 180,
formConfig: {
// 全局禁用vxe-table的表单配置使用formOptions
enabled: false,
},
proxyConfig: {
autoLoad: true,
response: {
result: 'items',
total: 'total',
list: 'items',
},
showActiveMsg: true,
showResponseMsg: false,
},
round: true,
showOverflow: true,
size: 'small',
},
});
// 表格配置项可以用 cellRender: { name: 'CellImage' },
vxeUI.renderer.add('CellImage', {
renderTableDefault(_renderOpts, params) {
const { column, row } = params;
return h(Image, { src: row[column.field] });
},
});
// 表格配置项可以用 cellRender: { name: 'CellLink' },
vxeUI.renderer.add('CellLink', {
renderTableDefault(renderOpts) {
const { props } = renderOpts;
return h(
Button,
{ size: 'small', type: 'link' },
{ default: () => props?.text },
);
},
});
// 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
// vxeUI.formats.add
},
useVbenForm,
});
export { useVbenVxeGrid };
export type * from '@vben/plugins/vxe-table';
```
:::
## 基础表格
使用 `useVbenVxeGrid` 创建最基础的表格。
<DemoPreview dir="demos/vben-vxe-table/basic" />
## 远程加载
通过指定 `proxyConfig.ajax``query` 方法,可以实现远程加载数据。
<DemoPreview dir="demos/vben-vxe-table/remote" />
## 树形表格
树形表格的数据源为扁平结构,可以指定`treeConfig`配置项,实现树形表格。
```typescript
treeConfig: {
transform: true, // 指定表格为树形表格
parentField: 'parentId', // 父节点字段名
rowField: 'id', // 行数据字段名
},
```
<DemoPreview dir="demos/vben-vxe-table/tree" />
## 固定表头/列
列固定可选参数: `'left' | 'right' | '' | null`
<DemoPreview dir="demos/vben-vxe-table/fixed" />
## 自定义单元格
自定义单元格有两种实现方式
- 通过 `slots` 插槽
- 通过 `customCell` 自定义单元格,但是要先添加渲染器
```typescript
// 表格配置项可以用 cellRender: { name: 'CellImage' },
vxeUI.renderer.add('CellImage', {
renderDefault(_renderOpts, params) {
const { column, row } = params;
return h(Image, { src: row[column.field] } as any); // 注意此处的Image 组件来源于Antd需要自行引入,否则会使用js的Image类
},
});
// 表格配置项可以用 cellRender: { name: 'CellLink' },
vxeUI.renderer.add('CellLink', {
renderDefault(renderOpts) {
const { props } = renderOpts;
return h(
Button,
{ size: 'small', type: 'link' },
{ default: () => props?.text },
);
},
});
```
<DemoPreview dir="demos/vben-vxe-table/custom-cell" />
## 搜索表单
**表单搜索** 部分采用了`Vben Form 表单`,参考 [Vben Form 表单文档](/components/common-ui/vben-form)。
当启用了表单搜索时可以在toolbarConfig中配置`search``true`来让表格在工具栏区域显示一个搜索表单控制按钮。表格的所有以`form-`开头的命名插槽都会被传递给搜索表单。
### 定制分隔条
当你启用表单搜索时在表单和表格之间会显示一个分隔条。这个分隔条使用了默认的组件背景色并且横向贯穿整个Vben Vxe Table在视觉上融入了页面的默认背景中。如果你在Vben Vxe Table的外层包裹了一个不同背景色的容器如将其放在一个Card内默认的表单和表格之间的分隔条可能就显得格格不入了下面的代码演示了如何定制这个分隔条。
```ts
const [Grid] = useVbenVxeGrid({
formOptions: {},
gridOptions: {},
// 完全移除分隔条
separator: false,
// 你也可以使用下面的代码来移除分隔条
// separator: { show: false },
// 或者使用下面的代码来改变分隔条的颜色
// separator: { backgroundColor: 'rgba(100,100,0,0.5)' },
});
```
<DemoPreview dir="demos/vben-vxe-table/form" />
## 单元格编辑
通过指定`editConfig.mode``cell`,可以实现单元格编辑。
<DemoPreview dir="demos/vben-vxe-table/edit-cell" />
## 行编辑
通过指定`editConfig.mode``row`,可以实现行编辑。
<DemoPreview dir="demos/vben-vxe-table/edit-row" />
## 虚拟滚动
通过 scroll-y.enabled 与 scroll-y.gt 组合开启,其中 enabled 为总开关gt 是指当总行数大于指定行数时自动开启。
> 参考 [vxe-table 官方文档 - 虚拟滚动](https://vxetable.cn/v4/#/component/grid/scroll/vertical)。
<DemoPreview dir="demos/vben-vxe-table/virtual" />
## API
`useVbenVxeGrid` 返回一个数组,第一个元素是表格组件,第二个元素是表格的方法。
```vue
<script setup lang="ts">
import { useVbenVxeGrid } from '#/adapter/vxe-table';
// Grid 为表格组件
// gridApi 为表格的方法
const [Grid, gridApi] = useVbenVxeGrid({
gridOptions: {},
formOptions: {},
gridEvents: {},
// 属性
// 事件
});
</script>
<template>
<Grid />
</template>
```
### GridApi
useVbenVxeGrid 返回的第二个参数,是一个对象,包含了一些表单的方法。
| 方法名 | 描述 | 类型 | 说明 |
| --- | --- | --- | --- |
| setLoading | 设置loading状态 | `(loading)=>void` | - |
| setGridOptions | 设置vxe-table grid组件参数 | `(options: Partial<VxeGridProps['gridOptions'])=>void` | - |
| reload | 重载表格,会进行初始化 | `(params:any)=>void` | - |
| query | 重载表格,会保留当前分页 | `(params:any)=>void` | - |
| grid | vxe-table grid实例 | `VxeGridInstance` | - |
| formApi | vbenForm api实例 | `FormApi` | - |
| toggleSearchForm | 设置搜索表单显示状态 | `(show?: boolean)=>boolean` | 当省略参数时,则将表单在显示和隐藏两种状态之间切换 |
## Props
所有属性都可以传入 `useVbenVxeGrid` 的第一个参数中。
| 属性名 | 描述 | 类型 | 版本要求 |
| --- | --- | --- | --- |
| tableTitle | 表格标题 | `string` | - |
| tableTitleHelp | 表格标题帮助信息 | `string` | - |
| gridClass | grid组件的class | `string` | - |
| gridOptions | grid组件的参数 | `VxeTableGridProps` | - |
| gridEvents | grid组件的触发的事件 | `VxeGridListeners` | - |
| formOptions | 表单参数 | `VbenFormProps` | - |
| showSearchForm | 是否显示搜索表单 | `boolean` | - |
| separator | 搜索表单与表格主体之间的分隔条 | `boolean\|SeparatorOptions` | >5.5.4 |
## Slots
大部分插槽的说明请参考 [vxe-table 官方文档](https://vxetable.cn/v4/#/grid/api),但工具栏部分由于做了一些定制封装,需使用以下插槽定制表格的工具栏:
| 插槽名 | 描述 |
| --------------- | -------------------------------------------- |
| toolbar-actions | 工具栏左侧部分(表格标题附近) |
| toolbar-tools | 工具栏右侧部分vxeTable原生工具按钮的左侧 |
| table-title | 表格标题插槽 |
::: info 搜索表单的插槽
对于使用了搜索表单的表格来说,所有以`form-`开头的命名插槽都会传递给表单。
:::

View File

@@ -0,0 +1,15 @@
# 介绍
::: info README
该文档介绍的是框架组件的使用方法、属性、事件等。如果你觉得现有组件的封装不够理想,或者不完全符合你的需求,大可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由。
:::
## 布局组件
布局组件一般在页面内容区域用作顶层容器组件,提供一些统一的布局样式和基本功能。
## 通用组件
通用组件是一些常用的组件,比如弹窗、抽屉、表单等。大部分基于 `Tailwind CSS` 实现,可适用于不同 UI 组件库的应用。

View File

@@ -0,0 +1,44 @@
---
outline: deep
---
# Page 常规页面组件
提供一个常规页面布局的组件,包括头部、内容区域、底部三个部分。
::: info 写在前面
本组件是一个基本布局组件。如果有更多的通用页面布局需求(比如双列布局等),可以根据实际需求自行封装。
:::
## 基础用法
`Page`作为你的业务页面的根组件即可。
### Props
| 属性名 | 描述 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- | --- |
| title | 页面标题 | `string\|slot` | - | - |
| description | 页面描述(标题下的内容) | `string\|slot` | - | - |
| contentClass | 内容区域的class | `string` | - | - |
| headerClass | 头部区域的class | `string` | - | - |
| footerClass | 底部区域的class | `string` | - | - |
| autoContentHeight | 自动调整内容区域的高度 | `boolean` | `false` | - |
::: tip 注意
如果`title``description``extra`三者均未提供有效内容(通过`props`或者`slots`均可),则页面头部区域不会渲染。
:::
### Slots
| 插槽名称 | 描述 |
| ----------- | ------------ |
| default | 页面内容 |
| title | 页面标题 |
| description | 页面描述 |
| extra | 页面头部右侧 |
| footer | 页面底部 |