组件使用指南
作者:唐亚峰 | battcn
字数统计:1.4k 字
学习目标
掌握 Wemirr Platform 内置组件的使用方法
组件概览
Wemirr Platform 基于 Vben Admin 5.x 和 Ant Design Vue 4.x,提供了丰富的业务组件。
基础组件
| 组件 | 说明 |
|---|---|
BasicForm | 表单组件,支持动态表单 |
BasicTable | 表格组件,支持分页、筛选 |
BasicModal | 弹窗组件 |
BasicDrawer | 抽屉组件 |
业务组件
| 组件 | 说明 |
|---|---|
DictSelect | 字典下拉选择 |
TreeSelect | 树形选择器 |
Upload | 文件上传 |
Editor | 富文本编辑器 |
BasicForm 表单组件
基础用法
vue
<script setup lang="ts">
import { BasicForm, useForm } from '@vben/common-ui';
import type { FormSchema } from '@vben/common-ui';
const schemas: FormSchema[] = [
{
field: 'username',
label: '用户名',
component: 'Input',
required: true,
colProps: { span: 12 },
},
{
field: 'email',
label: '邮箱',
component: 'Input',
rules: [{ type: 'email', message: '请输入有效的邮箱地址' }],
colProps: { span: 12 },
},
{
field: 'status',
label: '状态',
component: 'Select',
componentProps: {
options: [
{ label: '启用', value: 1 },
{ label: '禁用', value: 0 },
],
},
},
{
field: 'remark',
label: '备注',
component: 'InputTextArea',
colProps: { span: 24 },
},
];
const [registerForm, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({
schemas,
labelWidth: 100,
showActionButtonGroup: true,
actionColOptions: { span: 24 },
submitButtonOptions: { text: '提交' },
resetButtonOptions: { text: '重置' },
});
async function handleSubmit() {
const values = await validate();
console.log('表单数据:', values);
}
</script>
<template>
<BasicForm @register="registerForm" @submit="handleSubmit" />
</template>表单配置项
typescript
interface FormSchema {
field: string; // 字段名
label: string; // 标签
component: string; // 组件类型
componentProps?: object; // 组件属性
required?: boolean; // 是否必填
rules?: Rule[]; // 校验规则
colProps?: object; // 栅格配置
slot?: string; // 自定义插槽
ifShow?: boolean | Fn; // 是否显示
dynamicDisabled?: boolean | Fn; // 是否禁用
defaultValue?: any; // 默认值
}支持的组件类型
| 类型 | 说明 |
|---|---|
Input | 输入框 |
InputNumber | 数字输入框 |
InputPassword | 密码输入框 |
InputTextArea | 文本域 |
Select | 下拉选择 |
TreeSelect | 树形选择 |
RadioGroup | 单选组 |
CheckboxGroup | 多选组 |
Switch | 开关 |
DatePicker | 日期选择 |
RangePicker | 日期范围 |
TimePicker | 时间选择 |
Upload | 上传 |
表单联动
typescript
const schemas: FormSchema[] = [
{
field: 'type',
label: '类型',
component: 'Select',
componentProps: {
options: [
{ label: '个人', value: 1 },
{ label: '企业', value: 2 },
],
},
},
{
field: 'companyName',
label: '公司名称',
component: 'Input',
// 仅当类型为企业时显示
ifShow: ({ values }) => values.type === 2,
},
{
field: 'idCard',
label: '身份证号',
component: 'Input',
// 仅当类型为个人时显示
ifShow: ({ values }) => values.type === 1,
},
];BasicTable 表格组件
基础用法
vue
<script setup lang="ts">
import { BasicTable, useTable } from '@vben/common-ui';
import type { BasicColumn } from '@vben/common-ui';
import { getUserList, deleteUser } from './api';
const columns: BasicColumn[] = [
{ title: 'ID', dataIndex: 'id', width: 80 },
{ title: '用户名', dataIndex: 'username', width: 120 },
{ title: '邮箱', dataIndex: 'email', width: 180 },
{
title: '状态',
dataIndex: 'status',
width: 100,
customRender: ({ record }) => {
return record.status === 1 ? '启用' : '禁用';
},
},
{ title: '创建时间', dataIndex: 'createTime', width: 180 },
];
const [registerTable, { reload, getSelectRows }] = useTable({
columns,
api: getUserList,
rowKey: 'id',
bordered: true,
showIndexColumn: true,
rowSelection: { type: 'checkbox' },
pagination: { pageSize: 10 },
actionColumn: {
title: '操作',
width: 150,
fixed: 'right',
},
});
function handleEdit(record) {
console.log('编辑:', record);
}
async function handleDelete(record) {
await deleteUser(record.id);
reload();
}
</script>
<template>
<BasicTable @register="registerTable">
<template #toolbar>
<a-button type="primary" @click="handleAdd">新增</a-button>
<a-button @click="handleBatchDelete">批量删除</a-button>
</template>
<template #action="{ record }">
<a-button type="link" size="small" @click="handleEdit(record)">
编辑
</a-button>
<a-popconfirm title="确定删除?" @confirm="handleDelete(record)">
<a-button type="link" size="small" danger>删除</a-button>
</a-popconfirm>
</template>
</BasicTable>
</template>表格配置项
typescript
interface TableProps {
columns: BasicColumn[]; // 列配置
api?: Function; // 数据接口
dataSource?: any[]; // 静态数据
rowKey?: string; // 行键
bordered?: boolean; // 是否显示边框
pagination?: object | false;// 分页配置
rowSelection?: object; // 行选择配置
showIndexColumn?: boolean; // 是否显示序号列
actionColumn?: object; // 操作列配置
searchInfo?: object; // 额外搜索参数
beforeFetch?: Function; // 请求前处理
afterFetch?: Function; // 请求后处理
}表格方法
| 方法 | 说明 |
|---|---|
reload(opt?) | 刷新表格数据 |
getSelectRows() | 获取选中行数据 |
getSelectRowKeys() | 获取选中行键 |
clearSelectedRowKeys() | 清空选中 |
setSelectedRowKeys(keys) | 设置选中行 |
getPaginationRef() | 获取分页信息 |
setPagination(info) | 设置分页 |
getDataSource() | 获取表格数据 |
setTableData(data) | 设置表格数据 |
BasicModal 弹窗组件
基础用法
vue
<script setup lang="ts">
import { BasicModal, useModal } from '@vben/common-ui';
const [registerModal, { openModal, closeModal, setModalProps }] = useModal();
function handleOpen() {
openModal(true, { id: 1 });
}
</script>
<template>
<a-button @click="handleOpen">打开弹窗</a-button>
<BasicModal
@register="registerModal"
title="用户详情"
:width="600"
@ok="handleSubmit"
>
<div>弹窗内容</div>
</BasicModal>
</template>弹窗方法
typescript
const [registerModal, {
openModal, // 打开弹窗,可传递数据
closeModal, // 关闭弹窗
setModalProps, // 设置弹窗属性
getVisible, // 获取显示状态
}] = useModal();
// 在子组件中接收数据
const [registerModal, { closeModal }] = useModalInner((data) => {
console.log('接收到的数据:', data);
});BasicDrawer 抽屉组件
基础用法
vue
<script setup lang="ts">
import { BasicDrawer, useDrawer } from '@vben/common-ui';
const [registerDrawer, { openDrawer }] = useDrawer();
</script>
<template>
<a-button @click="openDrawer(true, { id: 1 })">
打开抽屉
</a-button>
<BasicDrawer
@register="registerDrawer"
title="详情"
:width="500"
>
<div>抽屉内容</div>
</BasicDrawer>
</template>字典组件
DictSelect 字典下拉
vue
<script setup lang="ts">
import { DictSelect } from '@/components/Dict';
</script>
<template>
<!-- 基础用法 -->
<DictSelect v-model:value="formData.status" dict-code="sys_status" />
<!-- 多选 -->
<DictSelect
v-model:value="formData.tags"
dict-code="sys_tags"
mode="multiple"
/>
<!-- 在表单中使用 -->
<a-form-item label="状态">
<DictSelect v-model:value="formData.status" dict-code="sys_status" />
</a-form-item>
</template>DictTag 字典标签
vue
<template>
<!-- 显示字典标签 -->
<DictTag dict-code="sys_status" :value="record.status" />
</template>文件上传组件
基础用法
vue
<script setup lang="ts">
import { BasicUpload } from '@/components/Upload';
const fileList = ref([]);
function handleChange(list) {
fileList.value = list;
}
</script>
<template>
<!-- 单文件上传 -->
<BasicUpload
v-model:value="fileList"
:max-count="1"
:api="uploadApi"
@change="handleChange"
/>
<!-- 多文件上传 -->
<BasicUpload
v-model:value="fileList"
:max-count="5"
:api="uploadApi"
accept=".jpg,.png,.pdf"
:max-size="10"
/>
<!-- 图片上传 -->
<BasicUpload
v-model:value="fileList"
:api="uploadApi"
list-type="picture-card"
accept="image/*"
/>
</template>树形选择器
部门树选择
vue
<script setup lang="ts">
import { TreeSelect } from 'ant-design-vue';
import { getDeptTree } from '@/api/system/dept';
const treeData = ref([]);
const selectedDept = ref<number>();
onMounted(async () => {
treeData.value = await getDeptTree();
});
</script>
<template>
<TreeSelect
v-model:value="selectedDept"
:tree-data="treeData"
:field-names="{ label: 'name', value: 'id', children: 'children' }"
placeholder="请选择部门"
allow-clear
tree-default-expand-all
/>
</template>图标选择器
vue
<script setup lang="ts">
import { IconPicker } from '@/components/Icon';
const selectedIcon = ref('');
</script>
<template>
<IconPicker v-model:value="selectedIcon" />
</template>