You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

205 lines
5.6 KiB
TypeScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import type { VueKey, VueText } from '#/types'
import type { SortOrder } from 'ant-design-vue/es/table/interface'
import type {
ActionType,
Bordered,
BorderedType,
ProColumns,
ProColumnType,
UseFetchDataAction
} from '../typing'
import type { TablePaginationConfig } from 'ant-design-vue'
import type { IntlType } from '#/provider'
import { arrayMoveImmutable } from '#/utils/array-move'
import type { Ref } from 'vue'
/**
* 合并用户 props 和 预设的 props
*/
export function mergePagination<T>(
pagination: TablePaginationConfig | boolean | undefined,
pageInfo: UseFetchDataAction<T>['pageInfo'] & {
setPageInfo: any
},
intl: IntlType
): TablePaginationConfig | false | undefined {
if (pagination === false) {
return false
}
const { total, current, pageSize, setPageInfo } = pageInfo
const defaultPagination: TablePaginationConfig = typeof pagination === 'object' ? pagination : {}
return {
showTotal: (all, range) =>
`${intl.getMessage('pagination.total.range', '第')} ${range[0]}-${range[1]} ${intl.getMessage(
'pagination.total.total',
'条/总共'
)} ${all} ${intl.getMessage('pagination.total.item', '条')}`,
total,
...(defaultPagination as TablePaginationConfig),
current,
pageSize,
showSizeChanger: true,
onChange: (page: number, newPageSize?: number) => {
const { onChange } = pagination as TablePaginationConfig
onChange?.(page, newPageSize || 10)
// pageSize 改变之后就没必要切换页码
if (newPageSize !== pageSize || current !== page) {
setPageInfo({ pageSize: newPageSize, current: page })
}
}
}
}
/**
* 获取用户的 action 信息
*/
export function useActionType<T>(
ref: Ref<ActionType | undefined>,
action: UseFetchDataAction<T>,
props: {
fullScreen: () => void
onCleanSelected: () => void
resetAll: () => void
editableUtils: any
}
) {
/** 这里生成action的映射保证 action 总是使用的最新 只需要渲染一次即可 */
const userAction: ActionType = {
...props.editableUtils,
pageInfo: action.pageInfo,
reload: async (resetPageIndex?: boolean) => {
// 如果为 true回到第一页
if (resetPageIndex) {
await action.setPageInfo({
current: 1
})
}
action?.reload()
},
reloadAndRest: async () => {
// reload 之后大概率会切换数据,清空一下选择。
props.onCleanSelected()
await action.setPageInfo({
current: 1
})
await action?.reload()
},
reset: async () => {
await props.resetAll()
await action?.reset?.()
await action?.reload()
},
fullScreen: () => props.fullScreen(),
clearSelected: () => props.onCleanSelected(),
// @ts-ignore
setPageInfo: rest => action.setPageInfo(rest)
}
ref.value = userAction
}
type PostDataType<T> = (data: T) => T
/**
* 一个转化的 pipeline 列表
*
* @param data
* @param pipeline
*/
export function postDataPipeline<T>(data: T, pipeline: PostDataType<T>[]) {
if (pipeline.filter(item => item).length < 1) {
return data
}
return pipeline.reduce((pre, postData) => {
return postData(pre)
}, data)
}
export const isBordered = (borderType: BorderedType, border?: Bordered) => {
if (border === undefined) {
return false
}
// debugger
if (typeof border === 'boolean') {
return border
}
return border[borderType]
}
export const isMergeCell = (
dom: any // 如果是合并单元格的,直接返回对象
) => dom && typeof dom === 'object' && dom?.props?.colSpan
/**
* 根据 key 和 dataIndex 生成唯一 id
*
* @param key 用户设置的 key
* @param index 序列号,理论上唯一
*/
export const genColumnKey = (key?: VueKey | undefined, index?: number): string => {
if (key) {
return Array.isArray(key) ? key.join('-') : key.toString()
}
return `${index}`
}
/**
* 将 ProTable - column - dataIndex 转为字符串形式
*
* @param dataIndex Column 中的 dataIndex
*/
function parseDataIndex(dataIndex: ProColumnType['dataIndex']): string | undefined {
if (Array.isArray(dataIndex)) {
return dataIndex.join(',')
}
return dataIndex?.toString()
}
/**
* 从 ProColumns 数组中取出默认的排序和筛选数据
*
* @param columns ProColumns
*/
export function parseDefaultColumnConfig<T, Value>(columns: ProColumns<T, Value>[]) {
const filter: Record<string, VueText[] | null> = {}
const sort: Record<string, SortOrder> = {}
columns.forEach(column => {
// 转换 dataIndex
const dataIndex = parseDataIndex(column.dataIndex)
if (!dataIndex) {
return
}
// 当 column 启用 filters 功能时,取出默认的筛选值
if (column.filters) {
const defaultFilteredValue = column.defaultFilteredValue as VueText[]
if (defaultFilteredValue === undefined) {
filter[dataIndex] = null
} else {
filter[dataIndex] = column.defaultFilteredValue as VueText[]
}
}
// 当 column 启用 sorter 功能时,取出默认的排序值
if (column.sorter && column.defaultSortOrder) {
sort[dataIndex] = column.defaultSortOrder!
}
})
return { sort, filter }
}
export type SortDataParams = { oldIndex: number; newIndex: number }
/**
* 数据排序核心逻辑
*
* @param oldIndex 原始位置
* @param newIndex 新位置
* @param data 原始数组
*/
export function sortData<T>({ oldIndex, newIndex }: SortDataParams, data: T[]): T[] | null {
if (oldIndex !== newIndex) {
const newData = arrayMoveImmutable([...(data || [])], oldIndex, newIndex).filter(el => !!el)
return [...newData]
}
return null
}