254 lines
7.0 KiB
TypeScript
254 lines
7.0 KiB
TypeScript
import { CellStyle, ElMessage } from "element-plus"
|
||
import other from "/@/utils/other"
|
||
import { formatDate } from "../utils/formatTime"
|
||
|
||
/**
|
||
* 表格组件基础配置属性
|
||
*/
|
||
export interface BasicTableProps {
|
||
// 是否在创建页面时即调用数据列表接口,默认为true
|
||
createdIsNeed?: boolean
|
||
// 是否需要分页,默认为true
|
||
isPage?: boolean
|
||
// 查询条件表单对象,类型为any
|
||
queryForm?: any
|
||
// 数据列表数组
|
||
dataList?: any[]
|
||
// 分页属性对象
|
||
pagination?: Pagination
|
||
// 数据列表,loading状态标志,默认为false
|
||
dataListLoading?: boolean
|
||
// 数据列表多选项数组
|
||
dataListSelections?: any[]
|
||
// 数据列表查询接口api方法,接收任意数量参数,返回Promise
|
||
pageList?: (...arg: any) => Promise<any>
|
||
// loading标志,默认为false
|
||
loading?: Boolean
|
||
// 多选结果数组
|
||
selectObjs?: any[]
|
||
// 排序字段数组
|
||
descs?: string[]
|
||
// 排序方式数组
|
||
ascs?: string[]
|
||
// props属性对象,类型为any
|
||
props?: any
|
||
}
|
||
|
||
/**
|
||
* 表格样式。
|
||
*/
|
||
export interface TableStyle {
|
||
cellStyle: CellStyle<any>
|
||
headerCellStyle: CellStyle<any>
|
||
}
|
||
|
||
/**
|
||
* 分页属性配置接口
|
||
*/
|
||
export interface Pagination {
|
||
// 当前页码,默认为1
|
||
current?: number
|
||
// 每页显示条数,默认为10
|
||
size?: number
|
||
// 总条数,默认为0
|
||
total?: number
|
||
// 每页显示条数选择器的选项数组,默认为[10,20,30,40]
|
||
pageSizes?: any[]
|
||
// 分页组件布局方式,可选值有 total,sizes,prev,jump,next,默认为'total,sizes,prev,jump,next'
|
||
layout?: String
|
||
}
|
||
|
||
export function useTable(options?: BasicTableProps) {
|
||
const defaultOptions: BasicTableProps = {
|
||
// 列表数据是否正在加载中,默认为false
|
||
dataListLoading: false,
|
||
// 是否需要自动请求创建接口来获取表格数据,默认为true
|
||
createdIsNeed: true,
|
||
// 是否展示分页组件,默认为true
|
||
isPage: true,
|
||
// 查询表单对象,用于提交条件查询时的参数传递,默认为空对象
|
||
queryForm: {},
|
||
// 表格展示的数据数组,默认为空数组
|
||
dataList: [],
|
||
// 分页组件属性配置,如当前页码、每页展示数据条数等,默认值为 {current:1, size:10,total:0,pageSizes:[1, 10, 20, 50, 100, 200],layout:'total, sizes, prev, pager, next, jumper'}
|
||
pagination: {
|
||
current: 1,
|
||
size: 10,
|
||
total: 0,
|
||
pageSizes: [1, 10, 20, 50, 100, 200],
|
||
layout: "total, sizes, prev, pager, next, jumper",
|
||
} as Pagination,
|
||
// 当前选中的数据项,默认为空数组
|
||
dataListSelections: [],
|
||
// 是否正在从服务器加载数据,默认为false
|
||
loading: false,
|
||
// 表格数据项的选择数据,默认为空数组
|
||
selectObjs: [],
|
||
// 排序时使用的字段名数组,如 ['id','name'],默认为空数组
|
||
descs: [],
|
||
// 排序方向数组,如 ['asc', 'desc'],默认为空数组
|
||
ascs: [],
|
||
// props属性配置对象,用于自定义数据属性,默认值为 {item:'records',totalCount:'total'}
|
||
props: {
|
||
item: "records",
|
||
totalCount: "total",
|
||
},
|
||
}
|
||
|
||
/**
|
||
* 合并默认属性配置和自定义属性配置
|
||
* @param options 默认属性配置对象
|
||
* @param props 自定义属性配置对象
|
||
* @returns 合并后的属性配置对象
|
||
*/
|
||
const mergeDefaultOptions = (options: any, props: any): BasicTableProps => {
|
||
for (const key in options) {
|
||
if (!Object.getOwnPropertyDescriptor(props, key)) {
|
||
props[key] = options[key]
|
||
}
|
||
}
|
||
return props
|
||
}
|
||
|
||
// 覆盖默认值
|
||
const state = mergeDefaultOptions(defaultOptions, options)
|
||
|
||
/**
|
||
* 发起分页查询,并设置表格数据和分页信息
|
||
*/
|
||
const query = async () => {
|
||
// 判断是否存在state.pageList属性
|
||
if (state.pageList) {
|
||
try {
|
||
// 开始加载数据,设置state.loading为true
|
||
state.loading = true
|
||
|
||
// 调用state.pageList方法发起分页查询
|
||
const res = await state.pageList({
|
||
...state.queryForm,
|
||
current: state.pagination?.current,
|
||
size: state.pagination?.size,
|
||
descs: state.descs?.join(","),
|
||
ascs: state.ascs?.join(","),
|
||
})
|
||
|
||
// 设置表格展示的数据数组
|
||
state.dataList = state.isPage ? res.data[state.props.item] : res.data
|
||
// 设置分页信息中的总数据条数
|
||
state.pagination!.total = state.isPage ? res.data[state.props.totalCount] : 0
|
||
} catch (err: any) {
|
||
// 捕获异常并显示错误提示
|
||
ElMessage.error(err.msg || err.data.msg)
|
||
} finally {
|
||
// 结束加载数据,设置state.loading为false
|
||
state.loading = false
|
||
}
|
||
}
|
||
}
|
||
|
||
onMounted(() => {
|
||
if (state.createdIsNeed) {
|
||
query()
|
||
}
|
||
})
|
||
|
||
/**
|
||
* 分页大小改变事件处理函数
|
||
* @param val 新的分页大小
|
||
*/
|
||
const sizeChangeHandle = (val: number) => {
|
||
// 修改state.pagination中的size属性
|
||
state.pagination!.size = val
|
||
// 再次发起查询操作
|
||
query()
|
||
}
|
||
|
||
/**
|
||
* 当前页码改变事件处理函数
|
||
* @param val 新的页码
|
||
*/
|
||
const currentChangeHandle = (val: number) => {
|
||
// 修改state.pagination中的current属性
|
||
state.pagination!.current = val
|
||
// 再次发起查询操作
|
||
query()
|
||
}
|
||
|
||
// 排序触发事件
|
||
const sortChangeHandle = (column: any) => {
|
||
const prop = other.toUnderline(column.prop)
|
||
if (column.order === "descending") {
|
||
state.descs?.push(prop)
|
||
if (state.ascs!.includes(prop)) {
|
||
state.ascs?.splice(state.ascs.indexOf(prop), 1)
|
||
}
|
||
} else if (column.order === "ascending") {
|
||
state.ascs?.push(prop)
|
||
if (state.descs!.includes(prop)) {
|
||
state.descs?.splice(state.descs.indexOf(prop), 1)
|
||
}
|
||
} else {
|
||
if (state.ascs!.includes(prop)) {
|
||
state.ascs?.splice(state.ascs.indexOf(prop), 1)
|
||
}
|
||
if (state.descs!.includes(prop)) {
|
||
state.descs?.splice(state.descs.indexOf(prop), 1)
|
||
}
|
||
}
|
||
query()
|
||
}
|
||
|
||
/**
|
||
* 获取数据列表,并可选择是否刷新当前页码
|
||
* 刷新后不跳转第一页,则入参 getDataList(false)
|
||
* @param refresh 是否刷新当前页码
|
||
*/
|
||
const getDataList = (refresh?: any) => {
|
||
// 如果需要刷新,则将state.pagination.current重置为1
|
||
if (refresh !== false) {
|
||
state.pagination!.current = 1
|
||
}
|
||
// 再次发起查询操作
|
||
query()
|
||
}
|
||
|
||
/**
|
||
* 下载文件
|
||
* @param url 文件下载地址
|
||
* @param query 请求参数(可能包含token)
|
||
* @param fileName 文件名
|
||
* @returns 返回一个Promise对象,用于异步处理结果
|
||
*/
|
||
const downBlobFile = (url: string, query: any, fileName: string) => {
|
||
ElMessage.info("下载中,请稍后")
|
||
return other.downBlobFile(url, query, formatDate(new Date(), "YYYY年mm月dd日 HH时MM分SS秒 ") + fileName)
|
||
}
|
||
|
||
const postDownBlobFile = (url: string, data: any, fileName: string) => {
|
||
return other.postDownBlobFile(url, data, formatDate(new Date(), "YYYY年mm月dd日 HH时MM分SS秒 ") + fileName)
|
||
}
|
||
|
||
/**
|
||
* 定义表格通用样式
|
||
* @returns css
|
||
*/
|
||
const tableStyle: TableStyle = {
|
||
cellStyle: { textAlign: "center" },
|
||
headerCellStyle: {
|
||
textAlign: "center",
|
||
background: "var(--el-table-row-hover-bg-color)",
|
||
color: "var(--el-text-color-primary)",
|
||
},
|
||
}
|
||
|
||
return {
|
||
tableStyle,
|
||
getDataList,
|
||
sizeChangeHandle,
|
||
currentChangeHandle,
|
||
sortChangeHandle,
|
||
downBlobFile,
|
||
postDownBlobFile,
|
||
}
|
||
}
|