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

1051 lines
38 KiB

import XEUtils from 'xe-utils'
import { VxeUI } from '../../../ui'
import { isEnableConf } from '../../../ui/src/utils'
import { getCellValue, setCellValue, getRowid } from '../../src/util'
import { removeClass, addClass } from '../../../ui/src/dom'
import { warnLog, errLog } from '../../../ui/src/log'
import type { VxeTableConstructor, TableInternalData, VxeTableDefines, TableReactData, VxeTablePrivateMethods } from '../../../../types'
const { getConfig, renderer, getI18n } = VxeUI
const browseObj = XEUtils.browse()
function getEditColumnModel (row: any, column: VxeTableDefines.ColumnInfo) {
const { model, editRender } = column
if (editRender) {
model.value = getCellValue(row, column)
model.update = false
}
}
function setEditColumnModel (row: any, column: VxeTableDefines.ColumnInfo) {
const { model, editRender } = column
if (editRender && model.update) {
setCellValue(row, column, model.value)
model.update = false
model.value = null
}
}
function removeCellSelectedClass ($xeTable: VxeTableConstructor & VxeTablePrivateMethods) {
const el = $xeTable.$refs.refElem as HTMLDivElement
if (el) {
const cell = el.querySelector('.col--selected')
if (cell) {
removeClass(cell, 'col--selected')
}
}
}
function syncActivedCell ($xeTable: VxeTableConstructor & VxeTablePrivateMethods) {
const reactData = $xeTable as unknown as TableReactData
const { editStore, tableColumn } = reactData
const editOpts = $xeTable.computeEditOpts
const { actived } = editStore
const { row, column } = actived
if (row || column) {
if (editOpts.mode === 'row') {
tableColumn.forEach((column) => setEditColumnModel(row, column))
} else {
setEditColumnModel(row, column)
}
}
}
function insertTreeRow ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, newRecords: any[], isAppend: boolean) {
const internalData = $xeTable as unknown as TableInternalData
const { tableFullTreeData, afterFullData, fullDataRowIdData, fullAllDataRowIdData } = internalData
const treeOpts = $xeTable.computeTreeOpts
const { rowField, parentField, mapChildrenField } = treeOpts
const childrenField = treeOpts.children || treeOpts.childrenField
const funcName = isAppend ? 'push' : 'unshift'
newRecords.forEach((item) => {
const parentRowId = item[parentField]
const rowid = getRowid($xeTable, item)
const matchObj = parentRowId ? XEUtils.findTree(tableFullTreeData, (item) => parentRowId === item[rowField], { children: mapChildrenField }) : null
if (matchObj) {
const { item: parentRow } = matchObj
const parentRest = fullAllDataRowIdData[getRowid($xeTable, parentRow)]
const parentLevel = parentRest ? parentRest.level : 0
let parentChilds = parentRow[childrenField]
let mapChilds = parentRow[mapChildrenField]
if (!XEUtils.isArray(parentChilds)) {
parentChilds = parentRow[childrenField] = []
}
if (!XEUtils.isArray(mapChilds)) {
mapChilds = parentRow[childrenField] = []
}
parentChilds[funcName](item)
mapChilds[funcName](item)
const rest = { row: item, rowid, seq: -1, index: -1, _index: -1, $index: -1, treeIndex: -1, _tIndex: -1, items: parentChilds, parent: parentRow, level: parentLevel + 1, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 }
fullDataRowIdData[rowid] = rest
fullAllDataRowIdData[rowid] = rest
} else {
if (parentRowId) {
warnLog('vxe.error.unableInsert')
}
afterFullData[funcName](item)
tableFullTreeData[funcName](item)
const rest = { row: item, rowid, seq: -1, index: -1, _index: -1, $index: -1, treeIndex: -1, _tIndex: -1, items: tableFullTreeData, parent: null, level: 0, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 }
fullDataRowIdData[rowid] = rest
fullAllDataRowIdData[rowid] = rest
}
})
}
// function insertGroupRow ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, newRecords: any[], isAppend: boolean) {
// }
function handleInsertRowAt ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, records: any[], targetRow: any, isInsertNextRow?: any) {
const props = $xeTable
const reactData = $xeTable as unknown as TableReactData
const internalData = $xeTable as unknown as TableInternalData
const { treeConfig } = props
const { isRowGroupStatus } = reactData
const { tableFullTreeData, afterFullData, mergeBodyList, tableFullData, fullDataRowIdData, fullAllDataRowIdData, insertRowMaps } = internalData
const treeOpts = $xeTable.computeTreeOpts
const { transform, rowField, mapChildrenField } = treeOpts
const childrenField = treeOpts.children || treeOpts.childrenField
if (!XEUtils.isArray(records)) {
records = [records]
}
const newRecords: any[] = $xeTable.defineField(records.map(record => Object.assign(treeConfig && transform ? { [mapChildrenField]: [], [childrenField]: [] } : {}, record)))
if (XEUtils.eqNull(targetRow)) {
// 如果为虚拟树
if (treeConfig && transform) {
insertTreeRow($xeTable, newRecords, false)
} else if (isRowGroupStatus) {
// 如果分组
if (treeConfig) {
throw new Error(getI18n('vxe.error.noTree', ['insert']))
}
warnLog(getI18n('vxe.error.noGroup', ['remove']))
// insertGroupRow($xeTable, newRecords, false)
} else {
newRecords.forEach(item => {
const rowid = getRowid($xeTable, item)
const rest = { row: item, rowid, seq: -1, index: -1, _index: -1, $index: -1, treeIndex: -1, _tIndex: -1, items: afterFullData, parent: null, level: 0, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 }
fullDataRowIdData[rowid] = rest
fullAllDataRowIdData[rowid] = rest
afterFullData.unshift(item)
tableFullData.unshift(item)
})
// 刷新单元格合并
mergeBodyList.forEach((mergeItem: any) => {
const { row: mergeRowIndex } = mergeItem
if (mergeRowIndex >= 0) {
mergeItem.row = mergeRowIndex + newRecords.length
}
})
}
} else {
if (targetRow === -1) {
// 如果为虚拟树
if (treeConfig && transform) {
insertTreeRow($xeTable, newRecords, true)
} else if (isRowGroupStatus) {
// 如果分组
if (treeConfig) {
throw new Error(getI18n('vxe.error.noTree', ['insert']))
}
warnLog(getI18n('vxe.error.noGroup', ['remove']))
// insertGroupRow($xeTable, newRecords, true)
} else {
newRecords.forEach(item => {
const rowid = getRowid($xeTable, item)
const rest = { row: item, rowid, seq: -1, index: -1, _index: -1, $index: -1, treeIndex: -1, _tIndex: -1, items: afterFullData, parent: null, level: 0, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 }
fullDataRowIdData[rowid] = rest
fullAllDataRowIdData[rowid] = rest
afterFullData.push(item)
tableFullData.push(item)
})
}
} else {
// 如果为虚拟树
if (treeConfig && transform) {
const matchMapObj = XEUtils.findTree(tableFullTreeData, (item: any) => targetRow[rowField] === item[rowField], { children: mapChildrenField })
if (matchMapObj) {
const { parent: parentRow } = matchMapObj as any
const parentMapChilds = parentRow ? parentRow[mapChildrenField] : tableFullTreeData
const parentRest = fullAllDataRowIdData[getRowid($xeTable, parentRow)]
const parentLevel = parentRest ? parentRest.level : 0
newRecords.forEach((item: any, i: any) => {
const rowid = getRowid($xeTable, item)
if (item[treeOpts.parentField]) {
if (parentRow && item[treeOpts.parentField] !== parentRow[rowField]) {
errLog('vxe.error.errProp', [`${treeOpts.parentField}=${item[treeOpts.parentField]}`, `${treeOpts.parentField}=${parentRow[rowField]}`])
}
}
if (parentRow) {
item[treeOpts.parentField] = parentRow[rowField]
}
let targetIndex = matchMapObj.index + i
if (isInsertNextRow) {
targetIndex = targetIndex + 1
}
parentMapChilds.splice(targetIndex, 0, item)
const rest = { row: item, rowid, seq: -1, index: -1, _index: -1, $index: -1, treeIndex: -1, _tIndex: -1, items: parentMapChilds, parent: parentRow, level: parentLevel + 1, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 }
fullDataRowIdData[rowid] = rest
fullAllDataRowIdData[rowid] = rest
})
// 源
if (parentRow) {
const matchObj = XEUtils.findTree(tableFullTreeData, (item: any) => targetRow[rowField] === item[rowField], { children: childrenField })
if (matchObj) {
const parentChilds = matchObj.items
let targetIndex = matchObj.index
if (isInsertNextRow) {
targetIndex = targetIndex + 1
}
parentChilds.splice(targetIndex, 0, ...newRecords)
}
}
} else {
warnLog('vxe.error.unableInsert')
insertTreeRow($xeTable, newRecords, true)
}
} else if (isRowGroupStatus) {
// 如果分组
if (treeConfig) {
throw new Error(getI18n('vxe.error.noTree', ['insert']))
}
warnLog(getI18n('vxe.error.noGroup', ['remove']))
} else {
if (treeConfig) {
throw new Error(getI18n('vxe.error.noTree', ['insert']))
}
let afIndex = -1
// 如果是可视索引
if (XEUtils.isNumber(targetRow)) {
if (targetRow < afterFullData.length) {
afIndex = targetRow
}
} else {
afIndex = $xeTable.findRowIndexOf(afterFullData, targetRow)
}
// 如果是插入指定行的下一行
if (isInsertNextRow) {
afIndex = Math.min(afterFullData.length, afIndex + 1)
}
if (afIndex === -1) {
throw new Error(errLog('vxe.error.unableInsert'))
}
afterFullData.splice(afIndex, 0, ...newRecords)
const tfIndex = $xeTable.findRowIndexOf(tableFullData, targetRow)
if (tfIndex > -1) {
tableFullData.splice(tfIndex + (isInsertNextRow ? 1 : 0), 0, ...newRecords)
} else {
tableFullData.push(...newRecords)
}
// 刷新单元格合并
mergeBodyList.forEach((mergeItem: any) => {
const { row: mergeRowIndex, rowspan: mergeRowspan } = mergeItem
if (mergeRowIndex >= afIndex) {
mergeItem.row = mergeRowIndex + newRecords.length
} else if (isInsertNextRow ? (mergeRowIndex + mergeRowspan >= afIndex) : (mergeRowIndex + mergeRowspan > afIndex)) {
mergeItem.rowspan = mergeRowspan + newRecords.length
}
})
}
}
}
newRecords.forEach(newRow => {
const rowid = getRowid($xeTable, newRow)
insertRowMaps[rowid] = newRow
})
reactData.insertRowFlag++
$xeTable.cacheRowMap(false)
$xeTable.updateScrollYStatus()
$xeTable.handleTableData(treeConfig && transform)
if (!(treeConfig && transform)) {
$xeTable.updateAfterDataIndex()
}
$xeTable.updateFooter()
$xeTable.handleUpdateBodyMerge()
$xeTable.checkSelectionStatus()
if (reactData.scrollYLoad) {
$xeTable.updateScrollYSpace()
}
return $xeTable.$nextTick().then(() => {
$xeTable.updateCellAreas()
return $xeTable.recalculate(true)
}).then(() => {
return {
row: newRecords.length ? newRecords[newRecords.length - 1] : null,
rows: newRecords
}
})
}
function handleInsertChildRowAt ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, records: any, parentRow: any, targetRow: any, isInsertNextRow?: boolean) {
const props = $xeTable
const { treeConfig } = props
const treeOpts = $xeTable.computeTreeOpts
const { transform, rowField, parentField } = treeOpts
if (treeConfig && transform) {
if (!XEUtils.isArray(records)) {
records = [records]
}
return handleInsertRowAt($xeTable, records.map((item: any) => Object.assign({}, item, { [parentField]: parentRow[rowField] })), targetRow, isInsertNextRow)
} else {
errLog('vxe.error.errProp', ['tree-config.transform=false', 'tree-config.transform=true'])
}
return Promise.resolve({ row: null, rows: [] })
}
function handleClearEdit ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, evnt: Event | null, targetRow?: any) {
const reactData = $xeTable as unknown as TableReactData
const { editStore } = reactData
const { actived, focused } = editStore
const { row, column } = actived
const validOpts = $xeTable.computeValidOpts
if (row || column) {
if (targetRow && getRowid($xeTable, targetRow) !== getRowid($xeTable, row)) {
return $xeTable.$nextTick()
}
syncActivedCell($xeTable)
actived.args = null
actived.row = null
actived.column = null
$xeTable.updateFooter()
$xeTable.dispatchEvent('edit-closed', {
row,
rowIndex: $xeTable.getRowIndex(row),
$rowIndex: $xeTable.getVMRowIndex(row),
column,
columnIndex: $xeTable.getColumnIndex(column),
$columnIndex: $xeTable.getVMColumnIndex(column)
}, evnt || null)
}
focused.row = null
focused.column = null
if (validOpts.autoClear) {
if (validOpts.msgMode !== 'full' || getConfig().cellVaildMode === 'obsolete') {
if ($xeTable.clearValidate) {
return $xeTable.clearValidate()
}
}
}
return $xeTable.$nextTick().then(() => $xeTable.updateCellAreas())
}
function handleEditActive ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, params: any, evnt: Event | null, isFocus: boolean, isPos: boolean) {
const props = $xeTable
const reactData = $xeTable as unknown as TableReactData
const $xeGrid = $xeTable.$xeGrid
const { editConfig, mouseConfig } = props
const { editStore, tableColumn } = reactData
const editOpts = $xeTable.computeEditOpts
const { mode } = editOpts
const { actived, focused } = editStore
const { row, column } = params
const { editRender } = column
const cell = (params.cell || $xeTable.getCellElement(row, column))
const beforeEditMethod = editOpts.beforeEditMethod || editOpts.activeMethod
params.cell = cell
if (cell && isEnableConf(editConfig) && isEnableConf(editRender)) {
// 激活编辑
if (!$xeTable.isPendingByRow(row) && !$xeTable.isAggregateRecord(row)) {
if (actived.row !== row || (mode === 'cell' ? actived.column !== column : false)) {
// 判断是否禁用编辑
let type: 'edit-disabled' | 'edit-activated' = 'edit-disabled'
if (!beforeEditMethod || beforeEditMethod({ ...params, $table: $xeTable, $grid: $xeGrid })) {
if (mouseConfig) {
$xeTable.clearSelected()
if ($xeTable.clearCellAreas) {
$xeTable.clearCellAreas()
$xeTable.clearCopyCellArea()
}
}
$xeTable.closeTooltip()
if (actived.column) {
handleClearEdit($xeTable, evnt)
}
type = 'edit-activated'
column.renderHeight = cell.offsetHeight
actived.args = params
actived.row = row
actived.column = column
if (mode === 'row') {
tableColumn.forEach((column: any) => getEditColumnModel(row, column))
} else {
getEditColumnModel(row, column)
}
const afterEditMethod = editOpts.afterEditMethod
$xeTable.$nextTick(() => {
if (isFocus) {
$xeTable.handleFocus(params, evnt)
}
if (afterEditMethod) {
afterEditMethod({ ...params, $table: $xeTable, $grid: $xeGrid })
}
})
}
$xeTable.dispatchEvent(type, {
row,
rowIndex: $xeTable.getRowIndex(row),
$rowIndex: $xeTable.getVMRowIndex(row),
column,
columnIndex: $xeTable.getColumnIndex(column),
$columnIndex: $xeTable.getVMColumnIndex(column)
}, evnt)
// v4已废弃
if (type === 'edit-activated') {
$xeTable.dispatchEvent('edit-actived', {
row,
rowIndex: $xeTable.getRowIndex(row),
$rowIndex: $xeTable.getVMRowIndex(row),
column,
columnIndex: $xeTable.getColumnIndex(column),
$columnIndex: $xeTable.getVMColumnIndex(column)
}, evnt)
}
} else {
const { column: oldColumn } = actived
if (mouseConfig) {
$xeTable.clearSelected()
if ($xeTable.clearCellAreas) {
$xeTable.clearCellAreas()
$xeTable.clearCopyCellArea()
}
}
if (oldColumn !== column) {
const { model: oldModel } = oldColumn
if (oldModel.update) {
setCellValue(row, oldColumn, oldModel.value)
}
if ($xeTable.clearValidate) {
$xeTable.clearValidate(row, column)
}
}
column.renderHeight = cell.offsetHeight
actived.args = params
actived.column = column
if (isPos) {
setTimeout(() => {
$xeTable.handleFocus(params, evnt)
})
}
}
focused.column = null
focused.row = null
$xeTable.focus()
}
}
return $xeTable.$nextTick()
}
function handleEditCell ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, row: any, fieldOrColumn: string | VxeTableDefines.ColumnInfo, isPos: boolean) {
const props = $xeTable
const internalData = $xeTable as unknown as TableInternalData
const { editConfig } = props
const column = XEUtils.isString(fieldOrColumn) ? $xeTable.getColumnByField(fieldOrColumn) : fieldOrColumn
if (row && column && isEnableConf(editConfig) && isEnableConf(column.editRender) && !$xeTable.isAggregateRecord(row)) {
return Promise.resolve(isPos ? $xeTable.scrollToRow(row, column) : null).then(() => {
const cell = $xeTable.getCellElement(row, column)
if (cell) {
handleEditActive($xeTable, {
row,
rowIndex: $xeTable.getRowIndex(row),
column,
columnIndex: $xeTable.getColumnIndex(column),
cell,
$table: $xeTable
}, null, isPos, isPos)
internalData._lastCallTime = Date.now()
}
return $xeTable.$nextTick()
})
}
return $xeTable.$nextTick()
}
export default {
methods: {
/**
* 往表格中插入临时数据
*
* @param {*} records
*/
_insert (records: any) {
return handleInsertRowAt(this, records, null)
},
/**
* 往表格指定行中插入临时数据
* 如果 row 为空则从插入到顶部
* 如果 row 为 -1 则从插入到底部
* 如果 row 为有效行则插入到该行的位置
* @param {Object/Array} records 新的数据
* @param {Row} targetRow 指定行
* @returns
*/
_insertAt (records: any, targetRow: any) {
return handleInsertRowAt(this, records, targetRow)
},
_insertNextAt (records: any, targetRow: any) {
return handleInsertRowAt(this, records, targetRow, true)
},
_insertChild (records: any, parentRow: any) {
return handleInsertChildRowAt(this, records, parentRow, null)
},
_insertChildAt (records: any, parentRow: any, targetRow: any) {
return handleInsertChildRowAt(this, records, parentRow, targetRow)
},
_insertChildNextAt (records: any, parentRow: any, targetRow: any) {
return handleInsertChildRowAt(this, records, parentRow, targetRow, true)
},
/**
* 删除指定行数据
* 如果传 row 则删除一行
* 如果传 rows 则删除多行
* 如果为空则删除所有
*/
_remove (rows: any[]) {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
const props = $xeTable
const reactData = $xeTable as unknown as TableReactData
const internalData = $xeTable as unknown as TableInternalData
const { treeConfig } = props
const { editStore, isRowGroupStatus } = reactData
const { tableFullTreeData, selectCheckboxMaps, afterFullData, mergeBodyList, tableFullData, pendingRowMaps, insertRowMaps, removeRowMaps } = internalData
const checkboxOpts = $xeTable.computeCheckboxOpts
const treeOpts = $xeTable.computeTreeOpts
const { transform, mapChildrenField } = treeOpts
const childrenField = treeOpts.children || treeOpts.childrenField
const { actived } = editStore
const { checkField } = checkboxOpts
let delList: any[] = []
if (!rows) {
rows = tableFullData
} else if (!XEUtils.isArray(rows)) {
rows = [rows]
}
// 如果是新增,则保存记录
rows.forEach(row => {
if (!$xeTable.isInsertByRow(row)) {
const rowid = getRowid($xeTable, row)
removeRowMaps[rowid] = row
}
})
// 如果绑定了多选属性,则更新状态
if (!checkField) {
rows.forEach((row) => {
const rowid = getRowid(this, row)
if (selectCheckboxMaps[rowid]) {
delete selectCheckboxMaps[rowid]
}
})
reactData.updateCheckboxFlag++
}
// 从数据源中移除
if (tableFullData === rows) {
rows = delList = tableFullData.slice(0)
this.tableFullData = []
this.afterFullData = []
this.clearMergeCells()
} else {
// 如果为虚拟树
if (treeConfig && transform) {
rows.forEach((row) => {
const rowid = getRowid(this, row)
const matchMapObj = XEUtils.findTree(tableFullTreeData, item => rowid === getRowid(this, item), { children: mapChildrenField })
if (matchMapObj) {
const rItems = matchMapObj.items.splice(matchMapObj.index, 1)
delList.push(rItems[0])
}
const matchObj = XEUtils.findTree(tableFullTreeData, item => rowid === getRowid(this, item), { children: childrenField })
if (matchObj) {
matchObj.items.splice(matchObj.index, 1)
}
const afIndex = this.findRowIndexOf(afterFullData, row)
if (afIndex > -1) {
afterFullData.splice(afIndex, 1)
}
})
} else if (isRowGroupStatus) {
// 如果分组
warnLog(getI18n('vxe.error.noGroup', ['remove']))
} else {
rows.forEach((row: any) => {
const tfIndex = this.findRowIndexOf(tableFullData, row)
if (tfIndex > -1) {
const rItems = tableFullData.splice(tfIndex, 1)
delList.push(rItems[0])
}
const afIndex = this.findRowIndexOf(afterFullData, row)
if (afIndex > -1) {
// 刷新单元格合并
mergeBodyList.forEach((mergeItem: any) => {
const { row: mergeRowIndex, rowspan: mergeRowspan } = mergeItem
if (mergeRowIndex > afIndex) {
mergeItem.row = mergeRowIndex - 1
} else if (mergeRowIndex + mergeRowspan > afIndex) {
mergeItem.rowspan = mergeRowspan - 1
}
})
afterFullData.splice(afIndex, 1)
}
})
}
}
// 如果当前行被激活编辑,则清除激活状态
if (actived.row && $xeTable.findRowIndexOf(rows, actived.row) > -1) {
$xeTable.clearEdit()
}
// 从新增中移除已删除的数据
rows.forEach((row: any) => {
const rowid = getRowid($xeTable, row)
if (insertRowMaps[rowid]) {
delete insertRowMaps[rowid]
}
if (pendingRowMaps[rowid]) {
delete pendingRowMaps[rowid]
}
})
reactData.removeRowFlag++
reactData.insertRowFlag++
reactData.pendingRowFlag++
$xeTable.cacheRowMap(false)
$xeTable.handleTableData(treeConfig && transform)
$xeTable.updateFooter()
$xeTable.handleUpdateBodyMerge()
if (!(treeConfig && transform)) {
$xeTable.updateAfterDataIndex()
}
$xeTable.checkSelectionStatus()
if (reactData.scrollYLoad) {
$xeTable.updateScrollYSpace()
}
return this.$nextTick().then(() => {
this.updateCellAreas()
return this.recalculate(true)
}).then(() => {
return { row: delList.length ? delList[delList.length - 1] : null, rows: delList }
})
},
/**
* 删除复选框选中的数据
*/
_removeCheckboxRow () {
return this.remove(this.getCheckboxRecords()).then((params: any) => {
this.clearCheckboxRow()
return params
})
},
/**
* 删除单选框选中的数据
*/
_removeRadioRow () {
const radioRecord = this.getRadioRecord()
return this.remove(radioRecord || []).then((params: any) => {
this.clearRadioRow()
return params
})
},
/**
* 删除当前行选中的数据
*/
_removeCurrentRow () {
const currentRecord = this.getCurrentRecord()
return this.remove(currentRecord || []).then((params: any) => {
this.clearCurrentRow()
return params
})
},
/**
* 获取表格数据集,包含新增、删除、修改
*/
_getRecordset () {
const removeRecords = this.getRemoveRecords()
const pendingRecords = this.getPendingRecords()
const delRecords = removeRecords.concat(pendingRecords)
// 如果已经被删除,则无需放到更新数组
const updateRecords = this.getUpdateRecords().filter((row: any) => {
return !delRecords.some((item: any) => this.eqRow(item, row))
})
return {
insertRecords: this.getInsertRecords(),
removeRecords,
updateRecords,
pendingRecords
}
},
/**
* 获取新增的临时数据
*/
_getInsertRecords () {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
const internalData = $xeTable as unknown as TableInternalData
const { fullAllDataRowIdData, insertRowMaps } = internalData
const insertRecords: any[] = []
XEUtils.each(insertRowMaps, (row, rowid) => {
if (fullAllDataRowIdData[rowid]) {
insertRecords.push(row)
}
})
return insertRecords
},
/**
* 获取已删除的数据
*/
_getRemoveRecords () {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
const internalData = $xeTable as unknown as TableInternalData
const { removeRowMaps } = internalData
const removeRecords: any[] = []
XEUtils.each(removeRowMaps, (row) => {
removeRecords.push(row)
})
return removeRecords
},
/**
* 获取更新数据
* 只精准匹配 row 的更改
* 如果是树表格,子节点更改状态不会影响父节点的更新状态
*/
_getUpdateRecords () {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
const props = $xeTable
const internalData = $xeTable as unknown as TableInternalData
const { keepSource, treeConfig } = props
const { tableFullData } = internalData
const treeOpts = $xeTable.computeTreeOpts
if (keepSource) {
syncActivedCell($xeTable)
if (treeConfig) {
return XEUtils.filterTree(tableFullData, row => $xeTable.isUpdateByRow(row), treeOpts)
}
return tableFullData.filter((row) => $xeTable.isUpdateByRow(row))
}
return []
},
/**
* 处理激活编辑
*/
handleEdit (params: any, evnt: any) {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
return handleEditActive($xeTable, params, evnt, true, true)
},
/**
* @deprecated
*/
handleActived (params: any, evnt: any) {
return this.handleEdit(params, evnt)
},
_getColumnModel (row: any, column: VxeTableDefines.ColumnInfo) {
getEditColumnModel(row, column)
},
_setColumnModel (row: any, column: VxeTableDefines.ColumnInfo) {
setEditColumnModel(row, column)
},
_syncActivedCell () {
const $xeTable = this
syncActivedCell($xeTable)
},
_clearActived (row: any) {
warnLog('vxe.error.delFunc', ['clearActived', 'clearEdit'])
// 即将废弃
return this.clearEdit(row)
},
/**
* 清除激活的编辑
*/
_clearEdit (row: any) {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
return handleClearEdit($xeTable, null, row)
},
/**
* 取消编辑
*/
handleClearEdit (evnt: Event | null, targetRow?: any) {
const $xeTable = this
return handleClearEdit($xeTable, evnt, targetRow)
},
_getActiveRecord () {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
const reactData = $xeTable as unknown as TableReactData
const internalData = $xeTable as unknown as TableInternalData
warnLog('vxe.error.delFunc', ['getActiveRecord', 'getEditCell'])
const { editStore } = reactData
const { fullAllDataRowIdData } = internalData
const { args, row } = editStore.actived
if (args && row && fullAllDataRowIdData[getRowid($xeTable, row)]) {
return Object.assign({}, args, { row })
}
return null
},
_getEditRecord () {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
const reactData = $xeTable as unknown as TableReactData
const internalData = $xeTable as unknown as TableInternalData
warnLog('vxe.error.delFunc', ['getEditRecord', 'getEditCell'])
const { editStore } = reactData
const { fullAllDataRowIdData } = internalData
const { args, row } = editStore.actived
if (args && row && fullAllDataRowIdData[getRowid($xeTable, row)]) {
return Object.assign({}, args, { row })
}
return null
},
_getEditCell () {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
const reactData = $xeTable as unknown as TableReactData
const { editStore } = reactData
const { row, column } = editStore.actived
if (column && row) {
return { row, column }
}
return null
},
_isActiveByRow (row: any) {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
warnLog('vxe.error.delFunc', ['isActiveByRow', 'isEditByRow'])
// 即将废弃
return $xeTable.isEditByRow(row)
},
/**
* 判断行是否为激活编辑状态
* @param {Row} row 行对象
*/
_isEditByRow (row: any) {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
const reactData = $xeTable as unknown as TableReactData
const { editStore } = reactData
return editStore.actived.row === row
},
/**
* 处理聚焦
*/
handleFocus (params: any) {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
const { row, column, cell } = params
const { editRender } = column
const editOpts = $xeTable.computeEditOpts
if (isEnableConf(editRender)) {
const compRender = renderer.get(editRender.name)
let autoFocus = editRender.autofocus || editRender.autoFocus
let autoSelect = editRender.autoSelect || editRender.autoselect
let inputElem
// 是否启用聚焦
if (editOpts.autoFocus) {
if (!autoFocus && compRender) {
autoFocus = compRender.tableAutoFocus || compRender.tableAutofocus || (compRender as any).autoFocus || compRender.autofocus
}
if (!autoSelect && compRender) {
autoSelect = compRender.tableAutoSelect || (compRender as any).autoSelect || compRender.autoselect
}
// 如果指定了聚焦 class
if (XEUtils.isFunction(autoFocus)) {
inputElem = autoFocus.call($xeTable, params)
} else if (autoFocus) {
if (autoFocus === true) {
// 自动匹配模式,会自动匹配第一个可输入元素
inputElem = cell.querySelector('input,textarea')
} else {
inputElem = cell.querySelector(autoFocus)
}
if (inputElem) {
inputElem.focus()
}
}
}
if (inputElem) {
if (autoSelect) {
inputElem.select()
} else {
// 保持一致行为,光标移到末端
if (browseObj.msie) {
const textRange = inputElem.createTextRange()
textRange.collapse(false)
textRange.select()
}
}
} else {
// 是否自动定位
if (editOpts.autoPos) {
if (!column.fixed) {
// 显示到可视区中
$xeTable.scrollToRow(row, column)
}
}
}
}
},
_setActiveRow (row: any) {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
warnLog('vxe.error.delFunc', ['setActiveRow', 'setEditRow'])
// 即将废弃
return $xeTable.setEditRow(row)
},
/**
* 激活行编辑
*/
_setEditRow (row: any, fieldOrColumn: any) {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
let column = XEUtils.find(this.visibleColumn, column => isEnableConf(column.editRender))
let isPos = false
if (fieldOrColumn) {
isPos = true
if (fieldOrColumn !== true) {
column = XEUtils.isString(fieldOrColumn) ? $xeTable.getColumnByField(fieldOrColumn) : fieldOrColumn
}
}
return handleEditCell($xeTable, row, column, isPos)
},
_setActiveCell (row: any, fieldOrColumn: any) {
warnLog('vxe.error.delFunc', ['setActiveCell', 'setEditCell'])
// 即将废弃
return this.setEditCell(row, fieldOrColumn)
},
/**
* 激活单元格编辑
*/
_setEditCell (row: any, fieldOrColumn: any) {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
return handleEditCell($xeTable, row, fieldOrColumn, true)
},
/**
* 只对 trigger=dblclick 有效,选中单元格
*/
_setSelectCell (row: any, fieldOrColumn: string | VxeTableDefines.ColumnInfo) {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
const reactData = $xeTable as unknown as TableReactData
const { tableData } = reactData
const editOpts = $xeTable.computeEditOpts
const column = XEUtils.isString(fieldOrColumn) ? $xeTable.getColumnByField(fieldOrColumn) : fieldOrColumn
if (row && column && editOpts.trigger !== 'manual') {
const rowIndex = $xeTable.findRowIndexOf(tableData, row)
if (rowIndex > -1) {
const cell = $xeTable.getCellElement(row, column)
const params = {
row,
rowIndex,
column,
columnIndex: $xeTable.getColumnIndex(column),
cell
}
$xeTable.handleSelected(params, {})
}
}
return $xeTable.$nextTick()
},
/**
* 处理选中源
*/
handleSelected (params: any, evnt: any) {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
const props = $xeTable
const reactData = $xeTable as unknown as TableReactData
const { mouseConfig } = props
const { editStore } = reactData
const mouseOpts = $xeTable.computeMouseOpts
const editOpts = $xeTable.computeEditOpts
const { actived, selected } = editStore
const { row, column } = params
const isMouseSelected = mouseConfig && mouseOpts.selected
const selectMethod = () => {
if (isMouseSelected && (selected.row !== row || selected.column !== column)) {
if (actived.row !== row || (editOpts.mode === 'cell' ? actived.column !== column : false)) {
handleClearEdit($xeTable, evnt)
$xeTable.clearSelected()
if ($xeTable.clearCellAreas) {
$xeTable.clearCellAreas()
$xeTable.clearCopyCellArea()
}
selected.args = params
selected.row = row
selected.column = column
if (isMouseSelected) {
this.addCellSelectedClass()
}
$xeTable.focus()
if (evnt) {
$xeTable.dispatchEvent('cell-selected', params, evnt)
}
}
}
return $xeTable.$nextTick()
}
return selectMethod()
},
/**
* 获取选中的单元格
*/
_getSelectedCell () {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
const reactData = $xeTable as unknown as TableReactData
const { editStore } = reactData
const { row, column } = editStore.selected
if (row && column) {
return { row, column }
}
return null
},
/**
* 清除所选中源状态
*/
_clearSelected () {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
const reactData = $xeTable as unknown as TableReactData
const { editStore } = reactData
const { selected } = editStore
selected.row = null
selected.column = null
removeCellSelectedClass($xeTable)
return $xeTable.$nextTick()
},
reColTitleSdCls () {
const headerElem = this.elemStore['main-header-list']
if (headerElem) {
XEUtils.arrayEach(headerElem.querySelectorAll('.col--title-selected'), elem => removeClass(elem, 'col--title-selected'))
}
},
addCellSelectedClass () {
const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
const reactData = $xeTable as unknown as TableReactData
const { editStore } = reactData
const { selected } = editStore
const { row, column } = selected
removeCellSelectedClass($xeTable)
if (row && column) {
const cell = $xeTable.getCellElement(row, column)
if (cell) {
addClass(cell, 'col--selected')
}
}
}
} as any
} as any