通用组件使用文档
本文档介绍了项目中两个核心通用组件的使用方法:CommonPageList(通用列表组件)和 CommonFormCard(通用表单组件)。
目录
- [CommonPageList 通用列表组件](#CommonPageList 通用列表组件 "#commonpagelist-%E9%80%9A%E7%94%A8%E5%88%97%E8%A1%A8%E7%BB%84%E4%BB%B6")
- [CommonFormCard 通用表单组件](#CommonFormCard 通用表单组件 "#commonformcard-%E9%80%9A%E7%94%A8%E8%A1%A8%E5%8D%95%E7%BB%84%E4%BB%B6")
- 最佳实践
CommonPageList 通用列表组件
CommonPageList 是一个高度封装的列表页面组件,集成了搜索、表格展示、分页、操作按钮等功能。
基本用法
vue
<template>
<CommonPageList
:listUrl="'/api/list'"
:deleteUrl="'/api/delete'"
:searchConfig="searchConfig"
:tableButtons="tableButtons"
:middleButtons="middleButtons"
ref="pageListRef"
/>
</template>
<script setup lang="ts">
import { CommonPageList, type ICommonPageListRef } from '@/components/commonPageList'
import { ref } from 'vue'
import type {
ISearchConfigItem,
ITableButtons,
IMiddleButtons
} from '@/components/commonPageList/types'
const pageListRef = ref<ICommonPageListRef>()
// 搜索配置
const searchConfig: ISearchConfigItem[] = [
{
component: 'input',
label: '用户名',
fieldName: 'username'
},
{
component: 'select',
label: '状态',
fieldName: 'status',
options: [
{ label: '启用', value: '1' },
{ label: '禁用', value: '0' }
]
},
{
component: 'datePicker',
label: '创建时间',
fieldName: 'createTime'
}
]
// 表格操作按钮
const tableButtons: ITableButtons = [
{
text: '编辑',
code: ['system:user:edit'],
action: (row: any) => {
console.log('编辑用户:', row)
}
},
{
text: '删除',
code: ['system:user:delete'],
action: (row: any) => {
console.log('删除用户:', row)
}
}
]
// 中间操作按钮
const middleButtons: IMiddleButtons = [
{
text: '新增用户',
type: 'primary',
code: ['system:user:create'],
action: () => {
console.log('新增用户')
}
},
{
text: '批量删除',
type: 'delete',
code: ['system:user:delete']
}
]
</script>
属性配置
| 属性名 | 类型 | 默认值 | 必填 | 说明 |
|---|---|---|---|---|
listUrl |
string |
- | ✅ | 列表数据请求地址 |
deleteUrl |
string |
- | ❌ | 删除请求地址 |
searchConfig |
ISearchConfigItem[] |
[] |
✅ | 搜索表单配置 |
tabs |
`ITabItem[] | Function` | [] |
❌ |
defaultForm |
Record<string, any> |
{} |
❌ | 默认表单数据 |
middleButtons |
IMiddleButtons |
[] |
❌ | 页面中间按钮配置 |
tableButtons |
ITableButtons |
[] |
❌ | 表格行操作按钮配置 |
showSelection |
boolean |
false |
❌ | 是否显示选择列 |
searchExpandNum |
number |
3 |
❌ | 展开显示的搜索项数量 |
tabFieldName |
string |
'tab' |
❌ | 选项卡字段名 |
sortableLabels |
string[] |
[] |
❌ | 可排序的字段标签 |
listMethod |
`'get' | 'post'` | 'get' |
❌ |
tableOperateBtnUnhiddenNumber |
number |
2 |
❌ | 表格操作按钮显示数量 |
搜索配置 (ISearchConfigItem)
typescript
interface ISearchConfigItem {
component: 'input' | 'select' | 'datePicker' // 组件类型
label: string // 标签文本
fieldName: string // 字段名
options?: { label: string; value: string }[] // 下拉选项(select组件用)
maxLength?: number // 最大长度(input组件用)
multiple?: boolean // 是否多选(select组件用)
placeholder?: string // 占位符
virtual?: boolean // 是否虚拟滚动(select组件用)
// ... 其他自定义属性
}
选项卡配置 (ITabItem)
typescript
interface ITabItem {
label: string // 选项卡显示文本
value: string // 选项卡值
}
按钮配置
typescript
// 中间按钮配置
interface IMiddleButtons {
text?: string // 按钮文本
action?: (params: any) => void // 点击事件
code?: string[] // 权限标识
type?: string // 按钮类型
}
// 表格操作按钮配置
interface ITableButtons {
text?: string // 按钮文本
action?: (params: any) => void // 点击事件
code?: string[] // 权限标识
show?: boolean \| ((row: any) => boolean) // 显示条件
}
插槽说明
| 插槽名 | 参数 | 说明 |
|---|---|---|
table-col-{fieldName} |
{ value, row } |
自定义表格列渲染 |
default |
- | 默认插槽 |
vue
<!-- 自定义表格列 -->
<template #table-col-用户名="{ value, row }">
<el-tag>{{ value }}</el-tag>
</template>
暴露方法
| 方法名 | 参数 | 返回值 | 说明 |
|---|---|---|---|
refresh |
- | void |
刷新列表数据 |
vue
<script setup lang="ts">
import type { ICommonPageListRef } from '@/components/commonPageList'
const pageListRef = ref<ICommonPageListRef>()
// 刷新列表
const handleRefresh = () => {
pageListRef.value?.refresh()
}
</script>
CommonFormCard 通用表单组件
CommonFormCard 是一个功能完善的表单组件,支持多种表单控件、分组显示、弹窗/抽屉模式等。
基本用法
vue
<template>
<CommonFormCard
ref="formRef"
title="用户信息"
:config="formConfig"
:footerBtns="footerBtns"
:wrapper="'drawer'"
@change="handleChange"
/>
</template>
<script setup lang="ts">
import { CommonFormCard, type ICommonFormCardRef } from '@/components/commonFormCard'
import { ref } from 'vue'
import type { IFormCardItem, IFormCardFooters } from '@/components/commonFormCard/types'
const formRef = ref<ICommonFormCardRef>()
// 表单配置
const formConfig: IFormCardItem[] = [
{
title: '基本信息',
items: [
{
component: 'input',
label: '用户名',
fieldName: 'username',
required: true,
maxLength: 20
},
{
component: 'select',
label: '性别',
fieldName: 'gender',
options: [
{ label: '男', value: '1' },
{ label: '女', value: '2' }
]
}
]
},
{
title: '联系方式',
items: [
{
component: 'input',
label: '手机号',
fieldName: 'phone',
required: true
},
{
component: 'uploader',
label: '头像',
fieldName: 'avatar',
fileType: ['jpg', 'png'],
limit: 1
}
]
}
]
// 底部按钮
const footerBtns: IFormCardFooters = [
{
text: '取消',
type: 'default'
},
{
text: '保存',
type: 'primary',
action: ({ formRef }: { formRef: ICommonFormCardRef }) => {
formRef.valid((data: any) => {
console.log('表单数据:', data)
// 调用保存接口
})
}
}
]
// 打开表单
const openForm = () => {
formRef.value?.open({
username: '张三',
gender: '1'
})
}
</script>
属性配置
| 属性名 | 类型 | 默认值 | 必填 | 说明 |
|---|---|---|---|---|
config |
IFormCardItem[] |
[] |
✅ | 表单配置数组 |
title |
string |
'--' |
❌ | 弹窗/抽屉标题 |
mode |
`'edit' | 'detail'` | 'edit' |
❌ |
wrapper |
`'div' | 'dialog' | 'drawer'` | 'drawer' |
labelWidth |
string |
'82px' |
❌ | 标签宽度 |
width |
string |
'880px' |
❌ | 弹窗/抽屉宽度 |
footerBtns |
IFormCardFooters |
[] |
❌ | 底部按钮配置 |
class |
string |
'' |
❌ | 自定义样式类 |
wrapperClass |
string |
'' |
❌ | 包裹容器样式类 |
表单配置 (IFormCardItem)
typescript
interface IFormCardItem {
title?: string // 卡片标题
span?: number // 栅格占用份额
md?: number // 中等屏幕栅格
lg?: number // 大屏幕栅格
show?: boolean \| Function // 显示条件
items?: IFormConfigItem[] // 表单项数组
}
表单项配置 (IFormConfigItem)
typescript
interface IFormConfigItem {
component: 'input' \| 'select' \| 'datePicker' \| 'uploader' \| 'radio' \| 'checkbox' \| 'switch' // 组件类型
label: string // 标签文本
fieldName: string // 字段名
required?: boolean // 是否必填
span?: number // 栅格占用份额
placeholder?: string // 占位符
disabled?: boolean \| Function // 是否禁用
show?: boolean \| Function // 是否显示
forceEdit?: boolean \| Function // 强制编辑
options?: Array<{ // 选项数据
label: string \| number
value: string \| number
disabled?: boolean
}>
change?: (params: ItemChangeProps) => void // 值变化回调
// ... 其他组件特定属性
}
插槽说明
| 插槽名 | 参数 | 说明 |
|---|---|---|
default |
{ formData, setFormData } |
默认插槽 |
after |
{ formData, setFormData } |
表单底部插槽 |
{cardTitle} |
{ formData, setFormData } |
卡片内容插槽 |
{fieldName} |
{ formData, setFormData } |
表单项插槽 |
{cardTitle}@after |
{ formData, setFormData } |
卡片后置插槽 |
vue
<!-- 自定义表单项 -->
<template #phone="{ formData, setFormData }">
<el-input
v-model="formData.phone"
placeholder="请输入手机号"
@input="setFormData({ phone: $event })"
/>
</template>
<!-- 自定义卡片内容 -->
<template #基本信息="{ formData }">
<div class="custom-content">
<p>这是一个自定义内容区域</p>
</div>
</template>
暴露方法
| 方法名 | 参数 | 返回值 | 说明 |
|---|---|---|---|
valid |
(callback: Function) => Promise<void> |
Promise<void> |
表单校验 |
open |
(data?: Record<string, any>) => void |
void |
打开弹窗/抽屉 |
setFormData |
(data: Record<string, any>) => void |
void |
设置表单数据 |
close |
- | void |
关闭弹窗/抽屉 |
reset |
- | void |
重置表单 |
vue
<script setup lang="ts">
import type { ICommonFormCardRef } from '@/components/commonFormCard'
const formRef = ref<ICommonFormCardRef>()
// 打开表单并设置初始数据
const openForm = () => {
formRef.value?.open({
username: '张三',
email: 'zhangsan@example.com'
})
}
// 设置表单数据
const updateFormData = () => {
formRef.value?.setFormData({
status: 'active'
})
}
// 校验表单
const validateForm = () => {
formRef.value?.valid((data: any) => {
console.log('校验通过的表单数据:', data)
// 提交数据
})
}
// 重置表单
const resetForm = () => {
formRef.value?.reset()
}
</script>
最佳实践
1. 权限控制
使用 code 属性结合权限系统控制按钮显示:
typescript
import type { ITableButtons } from '@/components/commonPageList/types'
const tableButtons: ITableButtons = [
{
text: '编辑',
code: ['system:user:edit'], // 需要编辑权限
action: handleEdit
},
{
text: '删除',
code: ['system:user:delete'], // 需要删除权限
action: handleDelete
}
]
2. 表单联动
使用 change 回调实现表单联动:
typescript
import type { IFormCardItem, ItemChangeProps } from '@/components/commonFormCard/types'
const formConfig: IFormCardItem[] = [
{
title: '地区信息',
items: [
{
component: 'select',
label: '省份',
fieldName: 'province',
options: provinceOptions,
change: ({ value, setFormData, selectRefs }: ItemChangeProps) => {
// 清空城市选择
setFormData({ city: '' })
// 更新城市选项
selectRefs.city?.getOptions({ province: value })
}
},
{
component: 'select',
label: '城市',
fieldName: 'city',
remoteMethod: (params: any) => getCities(params.province)
}
]
}
]
3. 动态显示隐藏
使用函数控制组件的显示隐藏:
typescript
import type { IFormCardItem } from '@/components/commonFormCard/types'
const formConfig: IFormCardItem[] = [
{
title: '用户信息',
items: [
{
component: 'radio',
label: '用户类型',
fieldName: 'userType',
options: [
{ label: '普通用户', value: 'normal' },
{ label: 'VIP用户', value: 'vip' }
]
},
{
component: 'input',
label: 'VIP等级',
fieldName: 'vipLevel',
show: (formData: any) => formData.userType === 'vip' // 只有VIP用户才显示
}
]
}
]
4. 自定义渲染
对于复杂的业务场景,使用插槽进行自定义渲染:
vue
<template>
<CommonFormCard :config="formConfig">
<!-- 自定义用户状态显示 -->
<template #status="{ formData, setFormData }">
<el-tag :type="formData.status === 'active' ? 'success' : 'danger'">
{{ formData.status === 'active' ? '启用' : '禁用' }}
</el-tag>
</template>
<!-- 自定义表格列 -->
<template #table-col-用户状态="{ value }">
<el-tag :type="value === 1 ? 'success' : 'info'">
{{ value === 1 ? '启用' : '禁用' }}
</el-tag>
</template>
</CommonFormCard>
</template>
5. 组件组合使用
将两个组件结合使用构建完整的CRUD页面:
vue
<template>
<CommonPageList
ref="pageListRef"
:listUrl="listUrl"
:deleteUrl="deleteUrl"
:searchConfig="searchConfig"
:tableButtons="tableButtons"
:middleButtons="middleButtons"
/>
<CommonFormCard ref="formRef" title="用户管理" :config="formConfig" :footerBtns="footerBtns" />
</template>
<script setup lang="ts">
import type { ICommonPageListRef, ITableButtons } from '@/components/commonPageList'
import type { ICommonFormCardRef, IFormCardFooters } from '@/components/commonFormCard'
const pageListRef = ref<ICommonPageListRef>()
const formRef = ref<ICommonFormCardRef>()
// 表格操作按钮
const tableButtons: ITableButtons = [
{
text: '编辑',
action: (row: any) => {
formRef.value?.open(row)
}
}
]
// 底部按钮
const footerBtns: IFormCardFooters = [
{
text: '保存',
action: ({ formRef }: { formRef: ICommonFormCardRef }) => {
formRef.valid(async (data: any) => {
await saveUser(data)
formRef.close()
pageListRef.value?.refresh()
})
}
}
]
</script>
TypeScript 类型定义
类型导入
typescript
// CommonPageList 相关类型
import type {
ICommonPageListRef,
ISearchConfigItem,
ITableButtons,
IMiddleButtons,
ITabItem
} from '@/components/commonPageList/types'
// CommonFormCard 相关类型
import type {
ICommonFormCardRef,
IFormCardItem,
IFormConfigItem,
IFormCardFooters,
ItemChangeProps
} from '@/components/commonFormCard/types'
完整类型定义示例
typescript
<script setup lang="ts">
import { ref } from 'vue'
import { CommonPageList, CommonFormCard } from '@/components'
import type {
ICommonPageListRef,
ICommonFormCardRef,
ISearchConfigItem,
ITableButtons,
IMiddleButtons,
IFormCardItem,
IFormCardFooters,
ItemChangeProps
} from '@/components/types'
// 组件引用类型
const pageListRef = ref<ICommonPageListRef>()
const formRef = ref<ICommonFormCardRef>()
// 搜索配置类型
const searchConfig: ISearchConfigItem[] = [
{
component: 'input',
label: '用户名',
fieldName: 'username'
}
]
// 表格按钮类型
const tableButtons: ITableButtons = [
{
text: '编辑',
code: ['system:user:edit'],
action: (row: any) => {
formRef.value?.open(row)
}
}
]
// 中间按钮类型
const middleButtons: IMiddleButtons = [
{
text: '新增',
type: 'primary',
code: ['system:user:create'],
action: () => {
formRef.value?.open()
}
}
]
// 表单配置类型
const formConfig: IFormCardItem[] = [
{
title: '基本信息',
items: [
{
component: 'input',
label: '用户名',
fieldName: 'username',
required: true,
maxLength: 20
},
{
component: 'select',
label: '状态',
fieldName: 'status',
options: [
{ label: '启用', value: '1' },
{ label: '禁用', value: '0' }
],
change: ({ value, setFormData, selectRefs }: ItemChangeProps) => {
// 联动逻辑
setFormData({ role: '' })
selectRefs.role?.getOptions({ status: value })
}
}
]
}
]
// 底部按钮类型
const footerBtns: IFormCardFooters = [
{
text: '取消',
type: 'default',
show: true
},
{
text: '保存',
type: 'primary',
action: ({ formRef }: { formRef: ICommonFormCardRef }) => {
formRef.valid((data: any) => {
console.log('表单数据:', data)
// 保存逻辑
})
}
}
]
// 方法定义
const handleEdit = (row: any) => {
formRef.value?.open(row)
}
const handleSave = async (data: any) => {
try {
await saveData(data)
formRef.value?.close()
pageListRef.value?.refresh()
} catch (error) {
console.error('保存失败:', error)
}
}
</script>
自定义数据类型
typescript
// 用户数据类型
interface User {
id: number
username: string
email: string
status: 'active' | 'inactive'
createdAt: string
}
// 表单数据类型
interface UserFormData {
username?: string
email?: string
status?: string
role?: string
}
// 使用自定义类型
const handleTableAction = (row: User) => {
console.log('用户数据:', row)
}
const handleFormValid = (data: UserFormData) => {
console.log('表单数据:', data)
}
注意事项
- 权限控制 :确保按钮的
code属性与后端权限配置保持一致 - 数据格式:确保请求和响应的数据格式符合组件预期
- 性能优化:对于大量数据,建议使用虚拟滚动和分页
- 响应式布局 :合理使用栅格系统的
span、md、lg属性 - 表单校验 :复杂校验规则建议使用
rules属性配置
通过合理使用这两个通用组件,可以快速构建功能完善、交互友好的管理页面。