fastlion-amis
Version:
一种MIS页面生成工具
242 lines (229 loc) • 10.5 kB
text/typescript
import { Condition } from "../../components/table/SecondFilter/types"
import { sortFn, filterFn, translateNumber } from "../../utils/utils"
import { numberFormatter } from "../../utils/helper"
import { IColumn as ITableColumn } from "../table"
import { DATAKEYID } from "../crud"
import union from 'lodash/union'
import intersection from 'lodash/intersection'
import { isNil, flatMap, isEqual } from "lodash"
import { resolveVariable } from "../../utils/tpl-builtin"
type IColumn = ITableColumn
export const CROSS_SPLIT_CHAR = '·'
export function handleSort(items: any[], columnNames: string[], orderMap: Map<string, { order?: 'asc' | 'desc', map?: object }>, modifiedData?: any) {
if (columnNames.length > 0) {
const name = columnNames.pop() ?? ''
items = items.sort((pre, next) => {
const map = orderMap.get(name)?.map
const order = orderMap.get(name)?.order
// 如果有编辑数据 用编辑数据排序 否则用正常的数据排序
// 判断字段类型是否是map,是的话取map值来排序
const preData = modifiedData?.[pre[DATAKEYID]] ? modifiedData[pre[DATAKEYID]]?.[name] : map ? map[pre[name]] : pre[name]
const nextData = modifiedData?.[next[DATAKEYID]] ? modifiedData[next[DATAKEYID]]?.[name] : map ? map[next[name]] : next[name]
return sortFn(preData, nextData, order)
})
handleSort(items, columnNames, orderMap, modifiedData)
}
return items
}
export function handleFilter(items: any[], columnNames: string[], filterMap: Map<string, { condition: Condition, value1?: string, value2?: string, value3?: string, relation?: 'and' | 'or' }[]>, caseSensitive = false) {
if (columnNames.length > 0) {
const name = columnNames.pop() ?? ''
const filters = filterMap.get(name)
if (filters) {
let temps: any[] = []
for (let i = 0; i < filters.length; i++) {
const filter = filters[i]
const relation = filters[i - 1]?.relation
const arr = filterFn(items.slice(), name, filter.condition, filter.value3 ?? filter.value1, filter.value2, caseSensitive)
if (relation == 'and') {
temps = intersection(temps, arr)
} else if (relation == 'or') {
temps = union(temps, arr)
} else {
temps = arr
}
}
items = handleFilter(temps, columnNames, filterMap)
}
}
return items
}
export function getHeadRows(filtedColumns: IColumn[], saveHidden = false) {
if (filtedColumns.length <= 0) return []
const groupNames = filtedColumns.map(column => column.groupName.length > 0 ? column.groupName.split(',').length : 0)
const level = Math.max(...groupNames) + 1
const columns = filtedColumns.map((column, index) => {
if (column.type == '__checkme' || column.type == '__expandme' || column.type == '__pseudoColumn') {
const name = column.type == '__checkme' ? 'SF_CHECK' : 'SF_PSEUDO'
return { ...column, name: name, groupName: new Array(level - 1).fill(name).join(',') }
}
const name = column.name || ('空' + (index || ''))
const groupNameArr = column.groupName.split(',')
const diff = level - 1 - groupNameArr.length
const groupName = column.groupName.length == 0 ? new Array(level - 1).fill(name).join(',') : column.groupName.split(',').concat(new Array(diff).fill(groupNameArr[groupNameArr.length - 1])).join(',')
return { ...column, name, groupName: level > 1 ? groupName : '' }
})
const rows: { name: string, label: string, colspan: number, rowspan: number, column: IColumn, hidden: boolean }[][] = []
const array: { groupName: string, column: IColumn }[][] = []
for (let i = 0; i < level; i++) {
const row = columns.map(column => ({ groupName: (column.groupName.length > 0 ? column.groupName.split(',') : []).concat(column.name)[i], column }))
array.push(row)
}
const groupNamesArray = array.slice()
for (let rowIndex = 0; rowIndex < groupNamesArray.length; rowIndex++) {
const rowGroupNamesArray = groupNamesArray[rowIndex]
const rowResult = []
for (let colIndex = 0; colIndex < rowGroupNamesArray.length; colIndex++) {
const { groupName, column } = rowGroupNamesArray[colIndex]
const groupLabels = column.pristine.groupLabels ?? []
const label = groupLabels.length > 0 ? groupLabels[rowIndex] : groupName
if (rowIndex > 0) {
const upLevel = rows[rowIndex - 1][colIndex]
if (upLevel.name == groupName && upLevel.colspan == 1) {
rowResult.push({ name: groupName, label, rowspan: 1, colspan: 1, hidden: true, column })
continue
}
}
let rowspan = 1
const colGroupNamesArray = flatMap(groupNamesArray.slice(rowIndex + 1), (arr) => arr[colIndex])
for (let i = 0; i < colGroupNamesArray.length; i++) {
const item = colGroupNamesArray[i]
if (groupName == item.groupName) {
rowspan += 1
} else {
break
}
}
if (rowspan > 1) {
rowResult.push({ name: groupName, label, rowspan, colspan: 1, hidden: false, column })
continue
}
let colspan = 1
for (let i = colIndex + 1; i < rowGroupNamesArray.length; i++) {
const item = rowGroupNamesArray[i];
if (groupName == item.groupName) {
colspan += 1
} else {
break
}
}
colIndex += colspan - 1
for (let i = 1; i <= colspan; i++) {
rowResult.push({ name: groupName, label, rowspan, colspan, hidden: i > 1, column })
}
}
rows.push(rowResult)
}
return saveHidden ? rows : rows.map(row => row.filter(item => !item.hidden))
}
export function getCellValue(originValue: any, column?: IColumn, clearFormat: boolean = false, isCopyCell?: boolean) {
let value = originValue
const prefix = column?.pristine.prefix ?? ''
const suffix = column?.pristine.suffix ?? ''
if (column?.type === 'mapping') {
const delimiter = column.pristine.delimiter
if (typeof delimiter === 'string') {
const originValues = String(originValue).split(delimiter)
value = originValues.map(value => column?.map?.[value] ?? (value ?? '')).join(delimiter)
} else {
value = column?.map?.[originValue] ?? (originValue ?? '')
}
} else if (column?.type === 'number') {
if (isNil(value)) return ''
// 不需要清空格式化的逻辑
if (!clearFormat) {
const showUppercase = column?.pristine.showUppercase ?? 0
const kilobitSeparator = column?.pristine.kilobitSeparator ?? false
const precision = !isNil(column?.pristine.precision) ? column?.pristine.precision : (value + '').split('.')[1]?.length ?? 0
if (showUppercase !== 0) {
value = translateNumber(value, showUppercase)
} else if (kilobitSeparator && originValue != null) {
value = numberFormatter(originValue, precision)
} else if (originValue != null && typeof originValue == 'number') {
value = originValue.toFixed(precision)
} else if (typeof originValue === 'string') {
value = (+originValue).toFixed(precision)
}
return `${prefix || ''}${value}${suffix || ''}`
} else {
// 需要清空格式化的逻辑
if (suffix === '%') {
// 如果是百分比的逻辑
value = isNil(originValue) ? originValue : originValue / 100
}
return value
}
}
if (value != null) {
return typeof value == 'object' ? '[文件]' : `${clearFormat ? '' : prefix}${typeof value == 'string' && !isCopyCell ? value.replace(/\n|\r|<[^>]*>/g, '') : value}${clearFormat ? '' : suffix}`
}
return ''
}
/** 同步设置列信息 */
export const syncCrossColumnInfo = (columns: IColumn[], columnInfo?: Record<string, { index: number, hidden?: 0 | 1, fixed: string }>) => {
if (columnInfo && Object.keys(columnInfo).length) {
const newColumns = columns.slice()
const colsArr = Object.entries(columnInfo).sort((a, b) => a[1]?.index - b[1]?.index);
let newCols: any[] = []
colsArr.forEach(([k, v]) => {
const target = newColumns.find(colItem => colItem.name === k)
if (target) {
newCols.push({ ...target, ...(v as object) })
}
})
const restColumns = newColumns.filter(item => !newCols.find((col: any) => col.name === item.name))
return [...newCols, ...restColumns]
}
return columns
}
export const getColumnShowLabel = (column: IColumn) => {
const names = column.name?.split(CROSS_SPLIT_CHAR)
const label = column.label || column.name
const groupNames = column.groupName ? column.groupName.split(',') : []
if (names?.length == 1 && (groupNames.length == 0 || groupNames.every(item => item == names[0]))) {
return label
}
const labels = column.pristine.groupLabels ?? []
if (labels.length > 0) {
return labels.join(CROSS_SPLIT_CHAR) + CROSS_SPLIT_CHAR + label
}
if (groupNames.length > 0) {
return (column.groupName.includes(CROSS_SPLIT_CHAR) ? groupNames[groupNames.length - 1] : groupNames.join(CROSS_SPLIT_CHAR)) + CROSS_SPLIT_CHAR + label
}
return label
}
export const getColumnClassNameExprData = (column: IColumn, data: any) => {
const isCrossColumn = typeof column.name == 'string' && column.name.includes(CROSS_SPLIT_CHAR)
if (isCrossColumn && column.pristine.classNameExpr) {
const classNameExprData = { ...data }
const levelNames: any[] = column.name!.split(CROSS_SPLIT_CHAR)
const groupName = levelNames.slice(0, levelNames.length - 1).join(CROSS_SPLIT_CHAR)
Object.keys(classNameExprData).forEach(key => {
if (key.startsWith(groupName)) {
const name = key.replace(`${groupName}${CROSS_SPLIT_CHAR}`, '')
classNameExprData[name] = classNameExprData[key]
}
})
return classNameExprData
}
return data
}
export const combineCell = (arr: { rowSpans: Record<string, number>; [key: string]: any }[], combinedColumns: { name: string, combinedNull: boolean }[]) => {
for (const { name, combinedNull = true } of combinedColumns) {
let i = 0
while (i < arr.length) {
if (arr[i].rowSpans[name] !== 0) {
arr[i].rowSpans[name] = 1
}
let j = i + 1
while (j < arr.length &&
isEqual(combinedNull ? resolveVariable(name, arr[i]) : resolveVariable(name, arr[i]) ?? Math.random(), combinedNull ? resolveVariable(name, arr[j]) : resolveVariable(name, arr[j]) ?? Math.random())) {
arr[i].rowSpans[name]++
arr[j].rowSpans[name] = 0
j++
}
i = j
}
}
return arr
}