diff --git a/apps/web-antd/src/adapter/component/index.ts b/apps/web-antd/src/adapter/component/index.ts
index aa96740d..a43a8280 100644
--- a/apps/web-antd/src/adapter/component/index.ts
+++ b/apps/web-antd/src/adapter/component/index.ts
@@ -8,7 +8,7 @@ import type { BaseFormComponentType } from '@vben/common-ui';
import type { Component, SetupContext } from 'vue';
import { h } from 'vue';
-import { ApiSelect, globalShareState, IconPicker } from '@vben/common-ui';
+import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui';
import { $t } from '@vben/locales';
import {
@@ -82,7 +82,7 @@ async function initComponentAdapter() {
// import('xxx').then((res) => res.Button),
ApiSelect: (props, { attrs, slots }) => {
return h(
- ApiSelect,
+ ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
@@ -97,7 +97,7 @@ async function initComponentAdapter() {
},
ApiTreeSelect: (props, { attrs, slots }) => {
return h(
- ApiSelect,
+ ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
diff --git a/apps/web-ele/src/adapter/component/index.ts b/apps/web-ele/src/adapter/component/index.ts
index 6c8667cd..818c8c4e 100644
--- a/apps/web-ele/src/adapter/component/index.ts
+++ b/apps/web-ele/src/adapter/component/index.ts
@@ -9,7 +9,7 @@ import type { Recordable } from '@vben/types';
import type { Component, SetupContext } from 'vue';
import { h } from 'vue';
-import { ApiSelect, globalShareState, IconPicker } from '@vben/common-ui';
+import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui';
import { $t } from '@vben/locales';
import {
@@ -70,7 +70,7 @@ async function initComponentAdapter() {
// import('xxx').then((res) => res.Button),
ApiSelect: (props, { attrs, slots }) => {
return h(
- ApiSelect,
+ ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
@@ -84,7 +84,7 @@ async function initComponentAdapter() {
},
ApiTreeSelect: (props, { attrs, slots }) => {
return h(
- ApiSelect,
+ ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
diff --git a/apps/web-naive/src/adapter/component/index.ts b/apps/web-naive/src/adapter/component/index.ts
index aed92b73..545a6199 100644
--- a/apps/web-naive/src/adapter/component/index.ts
+++ b/apps/web-naive/src/adapter/component/index.ts
@@ -8,7 +8,7 @@ import type { BaseFormComponentType } from '@vben/common-ui';
import type { Component, SetupContext } from 'vue';
import { h } from 'vue';
-import { ApiSelect, globalShareState, IconPicker } from '@vben/common-ui';
+import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui';
import { $t } from '@vben/locales';
import {
@@ -70,7 +70,7 @@ async function initComponentAdapter() {
ApiSelect: (props, { attrs, slots }) => {
return h(
- ApiSelect,
+ ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
@@ -83,7 +83,7 @@ async function initComponentAdapter() {
},
ApiTreeSelect: (props, { attrs, slots }) => {
return h(
- ApiSelect,
+ ApiComponent,
{
placeholder: $t('ui.placeholder.select'),
...props,
diff --git a/docs/.vitepress/config/zh.mts b/docs/.vitepress/config/zh.mts
index 27fb96c0..25e93ced 100644
--- a/docs/.vitepress/config/zh.mts
+++ b/docs/.vitepress/config/zh.mts
@@ -162,6 +162,10 @@ function sidebarComponents(): DefaultTheme.SidebarItem[] {
collapsed: false,
text: '通用组件',
items: [
+ {
+ link: 'common-ui/vben-api-component',
+ text: 'ApiComponent Api组件包装器',
+ },
{
link: 'common-ui/vben-modal',
text: 'Modal 模态框',
diff --git a/docs/src/components/common-ui/vben-api-component.md b/docs/src/components/common-ui/vben-api-component.md
new file mode 100644
index 00000000..f9db74e4
--- /dev/null
+++ b/docs/src/components/common-ui/vben-api-component.md
@@ -0,0 +1,150 @@
+---
+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
+
+
+
+
+```
+
+:::
+
+### Props
+
+| 属性名 | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| component | 欲包装的组件 | `Component` | - |
+| numberToString | 是否将value从数字转为string | `boolean` | `false` |
+| api | 获取数据的函数 | `(arg?: any) => Promise>` | - |
+| params | 传递给api的参数 | `Record` | - |
+| 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` | - |
+| afterFetch | 在api请求之后的回调函数 | `AnyPromiseFunction` | - |
+| options | 直接传入选项数据,也作为api返回空数据时的后备数据 | `OptionsItem[]` | - |
+| visibleEvent | 触发重新请求数据的事件名 | `string` | - |
+| loadingSlot | 组件的插槽名称,用来显示一个"加载中"的图标 | `string` | - |
+
+```
+
+```
diff --git a/docs/src/demos/vben-api-component/cascader/index.vue b/docs/src/demos/vben-api-component/cascader/index.vue
new file mode 100644
index 00000000..957964cd
--- /dev/null
+++ b/docs/src/demos/vben-api-component/cascader/index.vue
@@ -0,0 +1,100 @@
+
+
+
+
diff --git a/packages/effects/common-ui/src/components/api-select/api-select.vue b/packages/effects/common-ui/src/components/api-component/api-component.vue
similarity index 97%
rename from packages/effects/common-ui/src/components/api-select/api-select.vue
rename to packages/effects/common-ui/src/components/api-component/api-component.vue
index 71e1f125..d1d42ad7 100644
--- a/packages/effects/common-ui/src/components/api-select/api-select.vue
+++ b/packages/effects/common-ui/src/components/api-component/api-component.vue
@@ -1,7 +1,7 @@