RequestChartTable 组件使用文档
组件概述
RequestChartTable 是一个集成了查询数据表格、图表展示和相关操作的复合组件卡片,封装了包含查询栏、操作栏、表格、图表、分页、导出功能等,定义了 params 查询参数,request 接口请求,legend 图表图例等参数,并提供了统一的数据请求和处理机制,通过简单配置即可完成常用的数据表格或图表查询展示功能。
基本用法
1. 基础表格展示
vue
<template>
<RequestChartTable title="用户列表" :request="getUserList" :params="{ status: 1 }">
<template #table="{ query, getList, apiConfirm, goRoute }">
<el-table-column prop="userName" label="用户名" />
<el-table-column prop="nickName" label="昵称" />
<el-table-column prop="email" label="邮箱" />
<el-table-column label="操作" fixed="right">
<template #default="{ row }">
<el-button @click="goRoute(row.id, '/user/edit')">编辑</el-button>
<el-button @click="handleDelete(row.id)">删除</el-button>
</template>
</el-table-column>
</template>
</RequestChartTable>
</template>
<script setup>
const getUserList = (params) => {
return userService.getList(params)
}
const handleDelete = (id) => {
// 使用组件提供的删除方法
this.$refs.chartTable.del(userService.delete, id)
}
</script>2. 图表展示
vue
<template>
<RequestChartTable
title="销售统计"
type="lineChart"
:request="getSalesData"
:legend="['销售额', '订单数']"
:option="{ tooltip: { trigger: 'axis' } }">
<!-- 可以添加自定义查询条件 -->
<template #query="{ query }">
<el-form-item label="产品类型">
<el-select v-model="query.productType">
<el-option label="全部" value="" />
<el-option label="电子产品" value="1" />
<el-option label="服装" value="2" />
</el-select>
</el-form-item>
</template>
</RequestChartTable>
</template>Props 参数详解
基础配置
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| title | String/Object | - | 组件标题 |
| type | String | 'table' | 展示类型:'table'(表格)、'lineChart'(折线图)、'barChart'(柱状图) |
| params | Object | {} | 额外的查询参数 |
| isPageQuery | Boolean | true | 是否启用分页查询 |
| request | Function | - | 必填 数据请求函数 |
| isCreateRequest | Boolean | true | 创建时是否自动发起请求 |
| dataKey | String | 'id' | 数据主键字段名 |
查询相关
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| isTimeQuery | Boolean | false | 是否显示快捷时间查询 |
| dealQueryFun | Function | null | 自定义查询参数处理函数 |
| dealDataFun | Function | null | 自定义返回数据处理函数 |
导出功能
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| requestExport | Function | null | 导出数据请求函数 |
| exportFileName | String | - | 导出文件名(需包含后缀) |
图表配置
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| legend | Array/String | null | 图表图例 |
| option | Object | null | 自定义图表配置项 |
| tableOprateWidth | String | '150' | 表格操作列宽度 |
Slots 插槽说明
查询区域插槽
query
顶部查询表单插槽
vue
<template #query="{ query }">
<el-form-item label="姓名">
<el-input v-model="query.name" placeholder="请输入姓名" />
</el-form-item>
<el-form-item label="状态">
<el-select v-model="query.status">
<el-option label="启用" value="1" />
<el-option label="禁用" value="0" />
</el-select>
</el-form-item>
</template>queryMiddle
中间查询区域插槽
vue
<template #queryMiddle="{ query }">
<el-form-item label="分类">
<el-cascader v-model="query.category" :options="categoryOptions" />
</el-form-item>
</template>表格插槽
table
主要表格列定义插槽
vue
<template #table="{ query, getList, apiConfirm, goRoute }">
<el-table-column prop="name" label="名称" />
<el-table-column prop="status" label="状态">
<template #default="{ row }">
<el-tag :type="row.status === 1 ? 'success' : 'danger'">
{{ row.status === 1 ? '启用' : '禁用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="{ row }">
<el-button @click="goRoute(row.id)">编辑</el-button>
<el-button @click="apiConfirm(deleteUser, row.id, '确定删除吗?')">删除</el-button>
</template>
</el-table-column>
</template>tableView
简单表格视图插槽(当不需要复杂操作时使用)
vue
<template #tableView>
<el-table-column prop="name" label="名称" />
<el-table-column prop="createTime" label="创建时间" />
</template>tableOperation
表格操作列插槽
vue
<template #tableOperation="{ row }">
<el-button size="small" @click="handleEdit(row)">编辑</el-button>
<el-button size="small" type="danger" @click="handleDelete(row)">删除</el-button>
</template>其他插槽
operation
操作按钮区域插槽
vue
<template #operation="{ selectedIds, response }">
<el-button type="primary" @click="handleAdd">新增</el-button>
<el-button type="danger" :disabled="!selectedIds.length" @click="handleBatchDelete(selectedIds)">
批量删除
</el-button>
</template>empty
空数据状态插槽
vue
<template #empty>
<div class="empty-state">
<i class="el-icon-document"></i>
<p>暂无数据</p>
</div>
</template>pagination
自定义分页插槽
vue
<template #pagination="{ total, query, getList }">
<custom-pagination :total="total" v-model:current-page="query.pageNum" @change="getList" />
</template>方法说明
组件提供了一些实用的方法,可以通过 ref 调用:
getList(page)
手动触发数据请求
javascript
// 获取第一页数据
chartTableRef.value.getList(1)
// 获取当前页数据
chartTableRef.value.getList()del(delApi, id)
删除操作(支持单个和批量)
javascript
// 删除单条数据
chartTableRef.value.del(userService.delete, userId)
// 批量删除(使用选中的数据)
chartTableRef.value.del(userService.batchDelete)download(download, filename, tips, type)
文件下载功能
javascript
// 下载Excel文件
chartTableRef.value.download(userService.exportData, '用户数据.xlsx', '确认导出用户数据?')
// 下载其他类型文件
chartTableRef.value.download(fileService.downloadZip, '附件.zip', '确认下载附件?', 'zip')goRoute(idOrQuery, path)
路由跳转
javascript
// 跳转到编辑页面,传递ID
chartTableRef.value.goRoute(userId, '/user/edit')
// 跳转并传递多个参数
chartTableRef.value.goRoute({ id: userId, tab: 'info' }, '/user/detail')apiConfirm(apiRequest, id, tips)
通用确认操作
javascript
// 启用用户
chartTableRef.value.apiConfirm(userService.enable, userId, '确认启用该用户?')
// 批量审核
chartTableRef.value.apiConfirm(orderService.batchApprove, null, '确认批量审核选中的订单?')数据处理函数
dealQueryFun(query)
自定义查询参数处理
javascript
const dealQueryFun = (query) => {
// 添加固定查询条件
query.companyId = currentUser.companyId
// 格式化日期范围
if (query.dateRange) {
query.startTime = formatDate(query.dateRange[0])
query.endTime = formatDate(query.dateRange[1])
}
// 删除不必要的参数
delete query.unusedParam
}dealDataFun(data, response)
自定义返回数据处理
javascript
// 表格数据处理
const dealDataFun = (data, response) => {
// 数据格式转换
data.forEach((item) => {
item.statusText = getStatusText(item.status)
item.amount = formatMoney(item.amount)
})
// 设置额外的响应数据
this.extraInfo = response.extraInfo
}
// 图表数据处理
const dealDataFun = (data, series, xData, response) => {
// 处理X轴数据
xData.value = data.map((item) => item.date)
// 处理系列数据
series.value = [
{
name: '销售额',
type: 'line',
data: data.map((item) => item.sales),
},
{
name: '订单数',
type: 'bar',
data: data.map((item) => item.orders),
},
]
}完整示例
用户管理页面
vue
<template>
<RequestChartTable
ref="userTable"
title="用户管理"
:request="getUserList"
:request-export="exportUsers"
export-file-name="用户列表.xlsx"
:deal-query-fun="dealQuery"
:deal-data-fun="dealData"
@selection-change="handleSelectionChange">
<!-- 查询条件 -->
<template #query="{ query }">
<el-form-item label="用户名">
<el-input v-model="query.userName" placeholder="请输入用户名" />
</el-form-item>
<el-form-item label="状态">
<el-select v-model="query.status" clearable>
<el-option label="启用" value="1" />
<el-option label="禁用" value="0" />
</el-select>
</el-form-item>
</template>
<!-- 表格列定义 -->
<template #table="{ query, getList, apiConfirm, goRoute }">
<el-table-column prop="userName" label="用户名" />
<el-table-column prop="nickName" label="昵称" />
<el-table-column prop="email" label="邮箱" />
<el-table-column prop="status" label="状态" width="80">
<template #default="{ row }">
<el-tag :type="row.status === 1 ? 'success' : 'danger'">
{{ row.status === 1 ? '启用' : '禁用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="200">
<template #default="{ row }">
<el-button size="small" @click="goRoute(row.id, '/user/edit')"> 编辑 </el-button>
<el-button
size="small"
type="danger"
@click="apiConfirm(disableUser, row.id, '确认禁用该用户?')"
v-if="row.status === 1">
禁用
</el-button>
<el-button size="small" type="success" @click="apiConfirm(enableUser, row.id, '确认启用该用户?')" v-else>
启用
</el-button>
</template>
</el-table-column>
</template>
<!-- 操作按钮 -->
<template #operation="{ selectedIds }">
<el-button type="primary" @click="handleAdd">新增用户</el-button>
<el-button type="danger" :disabled="!selectedIds.length" @click="handleBatchDelete(selectedIds)">
批量删除
</el-button>
</template>
</RequestChartTable>
</template>
<script setup>
import { ref } from 'vue'
import { userService } from '@/api/user'
const userTable = ref()
// 查询函数
const getUserList = (params) => {
return userService.getList(params)
}
// 导出函数
const exportUsers = (params) => {
return userService.export(params)
}
// 查询参数处理
const dealQuery = (query) => {
// 添加默认排序
query.orderBy = 'createTime'
query.orderType = 'desc'
}
// 数据处理
const dealData = (data) => {
data.forEach((item) => {
item.createTime = formatDate(item.createTime)
})
}
// 事件处理
const handleSelectionChange = (selection) => {
console.log('选中的数据:', selection)
}
const handleAdd = () => {
router.push('/user/add')
}
const handleBatchDelete = (ids) => {
userTable.value.del(userService.batchDelete, ids.join(','))
}
const disableUser = (id) => {
return userService.updateStatus({ id, status: 0 })
}
const enableUser = (id) => {
return userService.updateStatus({ id, status: 1 })
}
</script>注意事项
- request 函数必须返回 Promise,且返回的数据结构应该包含
rows或data字段 - 当使用分页查询时,返回数据还应该包含
total字段 - 图表类型的数据处理函数签名与表格不同,需要注意区分
- 组件内部已经处理了 loading 状态,无需额外处理
- 时间范围查询会自动转换为 beginTime 和 endTime 参数
- 所有删除和确认操作都会弹出确认对话框
常见问题
Q: 如何自定义分页组件?
A: 使用 pagination 插槽可以完全自定义分页组件的样式和行为。
Q: 图表数据如何处理?
A: 使用 dealDataFun 函数处理,注意图表类型的处理函数参数与表格不同。
Q: 如何实现复杂的筛选条件?
A: 可以结合 query 和 queryMiddle 插槽实现多层筛选条件。
Q: 组件加载很慢怎么办?
A: 可以设置 isCreateRequest 为 false,在合适的时机手动调用 getList() 方法。