import { arrayEach, findIndexOf, find } from '../grid/static'
export const computedGridColumns = (props) => () => {
const { popseletor, gridOp, multi, valueField, textField } = props
const { columns = [] } = gridOp || {}
let gridColumns = []
if (popseletor === 'grid') {
const operColType = multi ? 'selection' : 'radio'
if (columns.length) {
const operColIndex = findIndexOf(columns, (column) => column.type === operColType)
gridColumns = columns.slice(0)
if (!~operColIndex) {
gridColumns = [{ type: operColType, width: 60 }, ...columns.slice(0)]
}
} else {
gridColumns = [
{ type: operColType, width: 60 },
{ field: valueField, title: String(valueField).toUpperCase() },
{ field: textField, title: String(textField).toUpperCase() }
]
}
}
return gridColumns
}
export const queryGridData =
({ api, props, state }) =>
() => {
const { popseletor, remoteSearch } = props
if (popseletor === 'grid') {
if (typeof remoteSearch === 'function') {
state.multiGridStore.loading = true
state.temporary.final = true
const onFinally = () => {
if (state.temporary.final) {
state.temporary.final = false
state.multiGridStore.loading = false
state.multiGridStore.inited = true
}
}
remoteSearch()
.then(() => {
state.multiGridStore.loading = false
api.setChecked()
})
.then(onFinally)
.catch(onFinally)
} else {
state.multiGridStore.inited = true
}
}
}
export const multiGridSelectAll =
({ api, props, state }) =>
({ selection, checked, $table }, event) => {
if (checked) {
arrayEach(selection, (item) => {
const index = findIndexOf(state.selectedValues, (val) => val === item[props.valueField])
if (!~index) {
state.selectedValues = [...state.selectedValues, item[props.valueField]]
state.selectedDatas = [...state.selectedDatas, item]
state.selectedChanged = true
}
})
} else {
const { data = [] } = props.gridOp || {}
data.forEach((item) => {
const selectedItem = state.selectedValues.find((i) => i === item[props.valueField])
if (selectedItem) {
const index = state.selectedValues.indexOf(selectedItem)
state.selectedValues.splice(index, 1)
state.selectedDatas.splice(index, 1)
}
})
state.selectedChanged = true
}
api.selectedBoxInit()
if (props.gridOp?.events?.selectAll) {
props.gridOp.events.selectAll({ selection, checked, $table }, event)
}
}
export const multiGridSelectChange =
({ api, props, state, vm }) =>
({ row, checked, $table }, event) => {
const property = props.valueField
const grid = vm.$refs?.multiGrid
const selectedRows = grid.getSelectRecords()
if (checked) {
const addSelectedRows = selectedRows.filter((row) => !state.selectedValues.includes(row[property]))
if (addSelectedRows.length > 0) {
state.selectedValues = [...state.selectedValues, ...addSelectedRows.map((row) => row[property])]
state.selectedDatas = [...state.selectedDatas, ...addSelectedRows]
state.selectedChanged = true
}
} else {
const childrenKey = props.gridOp?.treeConfig?.children
const checkStrictly = props.gridOp?.selectConfig?.checkStrictly
const getCancelRows = (row, arr) => {
arr.push(row)
if (row[childrenKey]?.length > 0) {
row[childrenKey].forEach((childRow) => getCancelRows(childRow, arr))
}
return arr
}
let cancelRows = checkStrictly ? [row] : getCancelRows(row, [])
cancelRows = cancelRows.filter((row) => state.selectedValues.includes(row[property]))
if (cancelRows.length > 0) {
cancelRows.forEach((row) => {
const index = state.selectedValues.indexOf(row[property])
state.selectedValues.splice(index, 1)
state.selectedDatas.splice(index, 1)
})
state.selectedChanged = true
}
}
api.selectedBoxInit()
if (props.gridOp?.events?.selectChange) {
props.gridOp.events.selectChange({ row, checked, $table }, event)
}
}
export const selectedBoxInit =
({ props, vm, nextTick }) =>
() => {
const { multi, showSelectedBox } = props
if (multi && showSelectedBox && vm.$refs.selectedBox) {
nextTick(() => {
vm.$refs.selectedBox.init()
})
}
}
export const selectedBoxClear =
({ props, state, vm, emit }) =>
() => {
const { multi, popseletor } = props
if (multi && popseletor === 'grid') {
vm.$refs.multiGrid.clearSelection()
}
if (multi && popseletor === 'tree') {
arrayEach(state.selectedValues, (value) => vm.$refs.multiTree.setCheckedByNodeKey(value, false))
}
state.selectedValues = []
state.selectedDatas = []
state.selectedChanged = true
emit('clear')
}
export const setTreeSelection =
({ api, state, vm, props }) =>
(keys, value) => {
const tree = vm.$refs.multiTree
if (!tree) {
return
}
if (value) {
keys.forEach((key) => {
if (!state.selectedValues.includes(key)) {
tree.setCheckedByNodeKey(key, true)
const datas = getTreeSelect({ vm, props })
const values = datas.map((item) => item[props.valueField])
state.selectedDatas = datas
state.selectedValues = values
}
})
} else {
keys.forEach((key) => {
if (state.selectedValues.includes(key)) {
tree.setCheckedByNodeKey(key, false)
const datas = getTreeSelect({ vm, props })
const values = datas.map((item) => item[props.valueField])
state.selectedDatas = datas
state.selectedValues = values
}
})
}
api.selectedBoxInit()
}
export const setGridSelection =
({ api, state, vm }) =>
(keys, value) => {
const grid = vm.$refs.multiGrid
if (!grid) {
return
}
const gridRows = []
if (value) {
keys.forEach((key) => {
if (!state.selectedValues.includes(key)) {
const row = grid.getRowById(key)
state.selectedValues = [...state.selectedValues, key]
state.selectedDatas = [...state.selectedDatas, row]
gridRows.push(row)
}
})
} else {
keys.forEach((key) => {
if (state.selectedValues.includes(key)) {
const index = state.selectedValues.indexOf(key)
state.selectedValues.splice(index, 1)
state.selectedDatas.splice(index, 1)
gridRows.push(grid.getRowById(key))
}
})
}
grid.setSelection(gridRows, Boolean(value))
api.selectedBoxInit()
}
export const setSelection =
({ props, api }) =>
(data, value) => {
const { multi, popseletor, valueField } = props
if (!multi) {
return
}
const dataArr = Array.isArray(data) ? data : [data]
const keys = dataArr.map((i) => i[valueField]).filter((i) => i)
if (keys.length === 0) {
return
}
if (popseletor === 'grid') {
return api.setGridSelection(keys, value)
}
if (popseletor === 'tree') {
return api.setTreeSelection(keys, value)
}
}
export const getSelection =
({ state }) =>
() =>
state.selectedDatas
export const selectedBoxDelete =
({ props, state, vm, emit }) =>
({ option: row }) => {
const { multi, popseletor } = props
if (multi && popseletor === 'grid') {
vm.$refs.multiGrid.setSelection(
find(vm.$refs.multiGrid.$refs.tinyTable.selection, (item) => item[props.valueField] === row[props.valueField]),
false
)
}
if (multi && popseletor === 'tree') {
vm.$refs.multiTree.setCheckedByNodeKey(row[props.valueField], false)
}
const index = findIndexOf(state.selectedValues, (val) => val === row[props.valueField])
if (~index) {
state.selectedValues = [...state.selectedValues.slice(0, index), ...state.selectedValues.slice(index + 1)]
state.selectedDatas = [...state.selectedDatas.slice(0, index), ...state.selectedDatas.slice(index + 1)]
state.selectedChanged = true
}
emit('delete', row)
}
export const selectedBoxDrag =
({ props, state }) =>
({ state: { select } }) => {
if (select && select.length) {
const datas = select
.map((opt) => String(opt[props.valueField]))
.map((strVal) => state.selectedDatas.find((opt) => strVal === String(opt[props.valueField])))
const values = datas.map((opt) => opt[props.valueField])
state.selectedDatas = datas
state.selectedValues = values
state.selectedChanged = true
}
}
export const doMultiTreeFilter =
({ props, state, nextTick, vm }) =>
() => {
const { popseletor, treeOp = {} } = props
if (popseletor === 'tree') {
if (state.multiTreeStore.filterText) {
if (treeOp.queryPidsBySearch) {
treeOp.queryPidsBySearch(state.multiTreeStore.filterText, (expandedKeys) => {
if (state.multiTreeStore.expandedKeys && state.multiTreeStore.expandedKeys.length) {
state.multiTreeStore.lastValidExpandedKeys = state.multiTreeStore.expandedKeys
}
state.multiTreeStore.viewType = 'plain'
state.multiTreeStore.expandedKeys = expandedKeys
vm.$refs.multiTree.filter(state.multiTreeStore.filterText)
})
}
} else {
state.multiTreeStore.viewType = 'tree'
if (state.multiTreeStore.expandedKeys && state.multiTreeStore.expandedKeys.length) {
const currentValidExpandedKeys = state.multiTreeStore.expandedKeys
state.multiTreeStore.expandedKeys = []
nextTick(() => {
state.multiTreeStore.expandedKeys = currentValidExpandedKeys
})
} else {
state.multiTreeStore.expandedKeys = state.multiTreeStore.lastValidExpandedKeys
}
vm.$refs.multiTree.filter('')
}
}
}
export const multiTreeAfterLoad =
({ api, props, state, vm }) =>
() => {
const { popseletor, treeOp = {}, valueField } = props
const { lookupStore } = state
if (popseletor === 'tree') {
vm.$refs.multiTree.filter(state.multiTreeStore.filterText)
if (state.multiTreeStore.inited) {
state.multiTreeStore.checkedKeys = state.selectedValues
} else {
const checkedKeys = lookupStore.datas.map((row) => row[valueField])
state.multiTreeStore.checkedKeys = checkedKeys
if (treeOp.queryPidsByIds && checkedKeys.length) {
treeOp.queryPidsByIds(checkedKeys, (expandedKeys) => {
state.multiTreeStore.expandedKeys = expandedKeys.slice(0)
api.setChecked()
state.multiTreeStore.inited = true
})
} else {
api.setChecked()
state.multiTreeStore.inited = true
}
}
}
}
export const multiTreeFilterNode = (props) => (value, data) => {
const { popseletor } = props
if (popseletor === 'tree') {
if (!value) return true
return ~data.label.indexOf(value)
}
return true
}
export const multiTreeFilterPlain =
({ api, props, state }) =>
(data) => {
const { popseletor } = props
if (popseletor === 'tree') {
return api.multiTreeFilterNode(state.multiTreeStore.filterText, data)
}
return true
}
export const multiTreeLeavePlain =
({ props, state }) =>
(plainNode) => {
const { popseletor } = props
if (popseletor === 'tree') {
state.multiTreeStore.viewType = 'tree'
state.multiTreeStore.expandedKeys = plainNode.parentNodeKeys
state.multiTreeStore.highlight = plainNode.nodeKey
}
}
const getTreeSelect = ({ vm, props }) => {
const { selectedBoxOp } = props
const { pkField = 'id', showField = [] } = (selectedBoxOp || {}).config || {}
const keyNames = [pkField, ...showField]
const checkedNodes = vm.$refs.multiTree.state.store.getCheckedNodes()
const { nodes: plainNodes } = vm.$refs.multiTree.state.plainNodeStore
const datas = []
arrayEach(checkedNodes, (item) => {
const plainNode = find(plainNodes, (plainNode) => plainNode.node.data[props.valueField] === item[props.valueField])
const tmp = { _$title: plainNode.title, _$auxi: plainNode.auxi }
arrayEach(keyNames, (keyName) => (tmp[keyName] = item[keyName]))
datas.push(tmp)
})
return datas
}
const getTreeRadio = (vm) => {
const { nodes: plainNodes } = vm.$refs.multiTree.state.plainNodeStore
const currentRadio = vm.$refs.multiTree.state.currentRadio
const plainNode = find(plainNodes, (plainNode) => plainNode.node.id === currentRadio.value)
return plainNode?.node ? [plainNode.node.data] : []
}
export const multiTreeCheck =
({ api, props, state, vm, nextTick }) =>
() => {
const { multi, popseletor } = props
if (popseletor === 'tree') {
nextTick(() => {
const datas = multi ? getTreeSelect({ vm, props }) : getTreeRadio(vm)
const values = datas.map((item) => item[props.valueField])
state.selectedDatas = datas
state.selectedValues = values
state.selectedChanged = true
multi && api.selectedBoxInit()
})
}
}
export const emitChange =
({ props, state, emit }) =>
() => {
if (state.selectedChanged) {
const { valueField, textField } = props
const { selectedDatas } = state
const texts = []
const values = []
arrayEach(selectedDatas, (item) => {
texts.push(item[textField])
values.push(item[valueField])
})
emit('change', values, texts, selectedDatas)
state.selectedChanged = false
}
}
export const onFooterCancel =
({ api, props }) =>
() => {
if (!props.beforeClose || props.beforeClose('cancel')) {
api.emitClose()
}
}
export const onFooterConfirm =
({ api, props }) =>
() => {
if (!props.beforeClose || props.beforeClose('confirm')) {
api.emitChange()
api.emitClose()
}
}
export const emitClose = (emit) => () => emit('update:visible', false)
export const setChecked =
({ api, props, state }) =>
() => {
const { multi, popseletor, valueField } = props
const { multiGridStore, multiTreeStore, lookupStore } = state
if ((popseletor === 'grid' && !multiGridStore.inited) || (popseletor === 'tree' && !multiTreeStore.inited)) {
if (lookupStore.datas && lookupStore.datas.length) {
state.selectedDatas = lookupStore.datas
state.selectedValues = lookupStore.datas.map((row) => row[valueField])
} else {
state.selectedDatas = []
state.selectedValues = []
}
multi && api.selectedBoxInit()
}
}
export const computedConfig =
({ props, state }) =>
(type) => {
const { multi, popseletor, gridOp } = props
const { selectConfig = {}, radioConfig = {} } = gridOp || {}
const { selectedValues } = state
let config = {}
const checkRowKeys = selectedValues.length ? selectedValues : selectConfig.checkRowKeys
if (popseletor === 'grid') {
if (multi && type === 'select') {
config = Object.assign(config, selectConfig, { checkRowKeys: state.selectedChanged ? [] : checkRowKeys })
}
if (!multi && type === 'radio') {
config = Object.assign(config, radioConfig, { checkRowKey: selectedValues[0] })
}
}
return config
}
export const doAutoLookup =
({ props, state, emit }) =>
() => {
const { autoLookup, lookupMethod, multi, popseletor, valueField, textField } = props
if (autoLookup && lookupMethod) {
let rowKeys = []
if (popseletor === 'grid') {
const { gridOp } = props
const { selectConfig, radioConfig } = gridOp || {}
const { checkRowKeys = [] } = selectConfig || {}
const { checkRowKey = '' } = radioConfig || {}
rowKeys = multi ? checkRowKeys : [checkRowKey]
}
if (popseletor === 'tree') {
const { treeOp } = props
const { defaultCheckedKeys = [] } = treeOp || {}
rowKeys = defaultCheckedKeys
}
lookupMethod(rowKeys).then((datas) => {
state.lookupStore.datas = datas
const values = datas.map((row) => row[valueField])
const texts = datas.map((row) => row[textField])
emit('change', values, texts, datas)
})
}
}
export const multiTreeRadio =
({ api, props }) =>
() => {
const { multi, popseletor } = props
if (!multi && popseletor === 'tree') {
api.multiTreeCheck()
}
}
export const multiGridRadioChange =
({ props, state }) =>
({ row, $table }, event) => {
state.selectedValues = [row[props.valueField]]
state.selectedDatas = [row]
state.selectedChanged = true
if (props.gridOp?.events?.radioChange) {
props.gridOp.events.radioChange({ row, $table }, event)
}
}
export const watchMulti =
({ api, state, props }) =>
() => {
state.splitValue = props.multi && props.showSelectedBox ? 0.7 : 1
state.selectedChanged = false
state.selectedDatas = []
state.selectedValues = []
state.multiGridStore.inited = false
state.multiGridStore.loading = false
state.multiTreeStore.viewType = 'tree'
state.multiTreeStore.expandedKeys = []
state.multiTreeStore.checkedKeys = []
state.multiTreeStore.highlight = null
state.multiTreeStore.filterText = ''
state.multiTreeStore.inited = false
state.lookupStore.datas = []
api.doAutoLookup()
}
export const clearStatus = (api) => () => api.watchMulti()