通用组件使用文档

通用组件使用文档

本文档介绍了项目中两个核心通用组件的使用方法:CommonPageList(通用列表组件)和 CommonFormCard(通用表单组件)。

目录


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)
}

注意事项

  1. 权限控制 :确保按钮的 code 属性与后端权限配置保持一致
  2. 数据格式:确保请求和响应的数据格式符合组件预期
  3. 性能优化:对于大量数据,建议使用虚拟滚动和分页
  4. 响应式布局 :合理使用栅格系统的 spanmdlg 属性
  5. 表单校验 :复杂校验规则建议使用 rules 属性配置

通过合理使用这两个通用组件,可以快速构建功能完善、交互友好的管理页面。

相关推荐
前端小张同学3 小时前
餐饮小程序需要你们
java·前端·后端
码农胖大海4 小时前
微前端架构(一):基础入门
前端
同聘云4 小时前
阿里云国际站服务器gpu服务器与cpu服务器的区别,gpu服务器如何使用?
服务器·前端·阿里云·云计算
lionliu05194 小时前
执行上下文 (Execution Context)
开发语言·前端·javascript
几何心凉4 小时前
openFuyao多样化算力使能
前端
方安乐4 小时前
vue3 el-select懒加载以及自定义指令
javascript·vue.js·elementui
文心快码BaiduComate4 小时前
给 AI 装上“员工手册”:如何用Rules 给文心快码 (Comate) 赋能提效?
前端·程序员·前端框架
哆啦A梦15884 小时前
商城后台管理系统 06 Mock.js模拟数据
开发语言·javascript·ecmascript