import { find } from '@opentiny/utils'
const updateBaseSelect = ({ vm, props, data, label }: any) => {
if (!vm.$refs.baseSelectRef) {
return
}
vm.$refs.baseSelectRef.updateSelectedData(data)
if (!props.multiple) {
const baseState = vm.$refs.baseSelectRef.state
if (!baseState) {
return
}
const currentLabel =
label ??
(data && !Array.isArray(data) ? (data.state?.currentLabel ?? data.currentLabel ?? data[props.textField]) : '')
baseState.selectedLabel = currentLabel || ''
if (props.filterable || props.searchable) {
baseState.query = currentLabel || ''
}
}
}
export const syncGridSelection =
({ props, vm, state, nextTick }) =>
() => {
if (!vm.$refs.gridRef) {
return
}
nextTick(() => {
try {
const tableData = vm.$refs.gridRef.getTableData()
const fullData = tableData?.fullData || []
if (props.multiple) {
if (Array.isArray(state.modelValue) && state.modelValue.length > 0) {
const rowsToSelect = fullData.filter((row: any) => state.modelValue.includes(row[props.valueField]))
vm.$refs.gridRef.clearSelection()
if (rowsToSelect.length > 0) {
vm.$refs.gridRef.setSelection(rowsToSelect, true)
}
} else {
vm.$refs.gridRef.clearSelection()
}
} else {
if (state.modelValue) {
const rowToSelect = fullData.find((row: any) => row[props.valueField] === state.modelValue)
vm.$refs.gridRef.clearRadioRow()
if (rowToSelect) {
vm.$refs.gridRef.setRadioRow(rowToSelect)
state.currentKey = rowToSelect[props.valueField]
}
} else {
vm.$refs.gridRef.clearRadioRow()
state.currentKey = ''
}
}
} catch (e) {
}
})
}
export const handleVisibleChange =
({ api, state, props }) =>
(visible: boolean) => {
if (visible && state.isMounted) {
api.syncGridSelection()
if (props.remote && props.remoteConfig?.autoSearch && state.firstAutoSearch !== false) {
api.filter('')
state.firstAutoSearch = false
}
}
}
export const buildSelectConfig =
({ props, state }) =>
() => {
const selectConfig = props.selectConfig
const rawCheckRowKeys = state.gridCheckedData
const checkRowKeys = Array.isArray(rawCheckRowKeys)
? rawCheckRowKeys
: rawCheckRowKeys && Array.isArray(rawCheckRowKeys.value)
? rawCheckRowKeys.value
: []
return Object.assign({}, selectConfig, { checkRowKeys })
}
export const buildRadioConfig =
({ props, state }) =>
() => {
const checkRowKey = state.currentKey
const highlight = true
const radioConfig = props.radioConfig
return Object.assign({}, radioConfig, { checkRowKey, highlight })
}
export const filter =
({ props, state, vm }) =>
async (value) => {
const { multiple, valueField, filterMethod, remote, remoteMethod } = props
if ((props.filterable || props.searchable) && typeof filterMethod === 'function') {
const table = vm.$refs.gridRef.$refs.tinyTable
const fullData = table.getTableData().fullData
vm.$refs.gridRef.scrollTo(null, 0)
await table.loadData(filterMethod(value, fullData) || [])
vm.$refs.gridRef.handleTableData(!value)
state.previousQuery = value
} else if (remote && typeof remoteMethod === 'function') {
state.previousQuery = value
remoteMethod(value, props.extraQueryParams).then((data) => {
if (multiple) {
const selectedIds = Array.isArray(state.selected) ? state.selected.map((sel: any) => sel[valueField]) : []
vm.$refs.gridRef.clearSelection()
const selectedRows = data.filter((row: any) => selectedIds.includes(row[valueField]))
if (selectedRows.length > 0) {
vm.$refs.gridRef.setSelection(selectedRows, true)
}
state.remoteData = data
} else {
vm.$refs.gridRef.clearRadioRow()
const selectedRow = find(data, (item: any) => props.modelValue === item[props.valueField])
if (selectedRow) {
vm.$refs.gridRef.setRadioRow(selectedRow)
}
state.remoteData = data
}
vm.$refs.gridRef.$refs.tinyTable.lastScrollTop = 0
vm.$refs.gridRef.loadData(data)
vm.$refs.gridRef.handleTableData(!value)
})
}
}
* 多选,获取已选中的行 value 数组,用于初始化表格的勾选状态
* @return 示例:[9, 6]
*/
export const getcheckedData =
({ props, state }) =>
() => {
const checkedKey: any[] = []
if (!Array.isArray(state.selected)) {
return props.modelValue
? [props.modelValue]
: state.selected && state.selected[props.valueField]
? [state.selected[props.valueField]]
: []
} else {
state.selected.length > 0 &&
state.selected.forEach((item: any) => {
checkedKey.push(item[props.valueField])
})
return checkedKey
}
}
* 多选,获取匹配的表格行
* @params value 表格行 value
* @return 完整的表格行数据
*/
export const getPluginOption =
({ api, props, state }) =>
(value) => {
const isRemote =
(props.filterable || props.searchable) &&
props.remote &&
(typeof props.remoteMethod === 'function' || typeof props.initQuery === 'function')
const { textField, valueField } = props
const sourceData: any[] = isRemote
? state.remoteData
: Array.isArray(state.gridData)
? state.gridData
: state.gridData?.data || []
const selNode = find(sourceData, (item: any) => item[valueField] === value)
const items: any[] = []
if (selNode) {
selNode.currentLabel = selNode[textField]
items.push(selNode)
}
return items
}
export const initQuery =
({ props, state, vm }) =>
(options: any = {}) => {
const { init } = options
const isRemote =
(props.filterable || props.searchable) &&
props.remote &&
(typeof props.remoteMethod === 'function' || typeof props.initQuery === 'function')
let selected
if (isRemote && props.initQuery) {
let initData = props.initQuery(props.modelValue, props.extraQueryParams, !!init)
if (initData && initData.then) {
return new Promise((resolve) => {
initData.then((selected: any) => {
state.remoteData = selected
if (vm.$refs.gridRef) {
vm.$refs.gridRef.loadData(selected)
}
resolve(selected)
})
})
}
selected = initData
state.remoteData = selected
if (vm.$refs.gridRef) {
vm.$refs.gridRef.loadData(selected)
}
}
return Promise.resolve(selected)
}
export const mounted =
({ api, state, props, vm, nextTick }) =>
() => {
const initSelected = () => {
if (!state.modelValue || (Array.isArray(state.modelValue) && state.modelValue.length === 0)) {
return
}
if (props.multiple) {
let initialNodes: any[] = []
if (Array.isArray(state.modelValue)) {
state.modelValue.forEach((value: any) => {
const option = api.getPluginOption(value)
initialNodes = initialNodes.concat(option)
})
}
const selected = initialNodes.map((node: any) => {
return {
...node,
currentLabel: node[props.textField],
value: node[props.valueField]
}
})
updateBaseSelect({ vm, props, data: selected })
state.selected = selected
if (vm.$refs.gridRef && selected.length > 0) {
vm.$refs.gridRef.clearSelection()
vm.$refs.gridRef.setSelection(selected, true)
}
} else {
const data = api.getPluginOption(state.modelValue)[0]
if (data) {
if (vm.$refs.baseSelectRef) {
updateBaseSelect({
vm,
props,
data: {
...data,
currentLabel: data[props.textField],
value: data[props.valueField],
state: {
currentLabel: data[props.textField]
}
}
})
}
state.selected = data
state.currentKey = data[props.valueField]
if (vm.$refs.gridRef) {
vm.$refs.gridRef.clearRadioRow()
vm.$refs.gridRef.setRadioRow(data)
}
}
}
}
nextTick(() => {
const initQueryPromise = api.initQuery({ init: true })
if (initQueryPromise && typeof initQueryPromise.then === 'function') {
initQueryPromise
.then(() => {
nextTick(() => {
initSelected()
})
})
.catch(() => {
nextTick(() => {
initSelected()
})
})
} else {
initSelected()
}
})
}
export const watchValue =
({ api, props, vm, state }) =>
(newValue: any, oldValue: any) => {
if (props.multiple) {
let initialNodes: any[] = []
if (Array.isArray(newValue) && newValue.length > 0) {
const isRemote =
(props.filterable || props.searchable) &&
props.remote &&
(typeof props.remoteMethod === 'function' || typeof props.initQuery === 'function')
const sourceData: any[] = isRemote
? state.remoteData
: Array.isArray(state.gridData)
? state.gridData
: state.gridData?.data || []
if (vm.$refs.gridRef) {
try {
const tableData = vm.$refs.gridRef.getTableData()
const fullData = tableData?.fullData || sourceData
newValue.forEach((value: any) => {
const foundRow = fullData.find((item: any) => item[props.valueField] === value)
if (foundRow) {
initialNodes.push(foundRow)
} else {
const existing = state.selected.find((item: any) => item[props.valueField] === value)
if (existing) {
initialNodes.push(existing)
}
}
})
} catch (e) {
newValue.forEach((value: any) => {
const foundRow = sourceData.find((item: any) => item[props.valueField] === value)
if (foundRow) {
initialNodes.push(foundRow)
} else {
const existing = state.selected.find((item: any) => item[props.valueField] === value)
if (existing) {
initialNodes.push(existing)
}
}
})
}
} else {
newValue.forEach((value: any) => {
const foundRow = sourceData.find((item: any) => item[props.valueField] === value)
if (foundRow) {
initialNodes.push(foundRow)
} else {
const existing = state.selected.find((item: any) => item[props.valueField] === value)
if (existing) {
initialNodes.push(existing)
}
}
})
}
}
const selected = initialNodes.map((node: any) => {
return {
...node,
currentLabel: node[props.textField],
value: node[props.valueField]
}
})
if (vm.$refs.baseSelectRef) {
updateBaseSelect({ vm, props, data: selected })
}
state.selected = selected
if (vm.$refs.gridRef) {
vm.$refs.gridRef.clearSelection()
if (selected.length > 0) {
try {
const tableData = vm.$refs.gridRef.getTableData()
const fullData = tableData?.fullData || []
const rowsToSelect = fullData.filter((row: any) =>
selected.some((sel: any) => sel[props.valueField] === row[props.valueField])
)
if (rowsToSelect.length > 0) {
vm.$refs.gridRef.setSelection(rowsToSelect, true)
}
} catch (e) {
vm.$refs.gridRef.setSelection(selected, true)
}
}
}
} else {
if (!newValue) {
state.selected = {}
state.currentKey = ''
if (vm.$refs.gridRef) {
vm.$refs.gridRef.clearRadioRow()
}
if (vm.$refs.baseSelectRef) {
updateBaseSelect({ vm, props, data: null })
}
return
}
const isRemote =
(props.filterable || props.searchable) &&
props.remote &&
(typeof props.remoteMethod === 'function' || typeof props.initQuery === 'function')
const sourceData: any[] = isRemote
? state.remoteData
: Array.isArray(state.gridData)
? state.gridData
: state.gridData?.data || []
let data = null
if (vm.$refs.gridRef) {
try {
const tableData = vm.$refs.gridRef.getTableData()
const fullData = tableData?.fullData || sourceData
data = fullData.find((item: any) => item[props.valueField] === newValue)
} catch (e) {
data = sourceData.find((item: any) => item[props.valueField] === newValue)
}
} else {
data = sourceData.find((item: any) => item[props.valueField] === newValue)
}
if (
!data &&
state.selected &&
typeof state.selected === 'object' &&
!Array.isArray(state.selected) &&
state.selected[props.valueField] === newValue
) {
data = state.selected
}
if (data && typeof data === 'object' && !Array.isArray(data)) {
updateBaseSelect({
vm,
props,
data: {
...(data as any),
currentLabel: data[props.textField],
value: data[props.valueField],
state: {
currentLabel: data[props.textField]
}
}
})
state.selected = data
state.currentKey = data[props.valueField]
if (vm.$refs.gridRef) {
vm.$refs.gridRef.clearRadioRow()
try {
const tableData = vm.$refs.gridRef.getTableData()
const fullData = tableData?.fullData || []
const rowToSelect = fullData.find((row: any) => row[props.valueField] === newValue)
if (rowToSelect) {
vm.$refs.gridRef.setRadioRow(rowToSelect)
} else {
vm.$refs.gridRef.setRadioRow(data)
}
} catch (e) {
vm.$refs.gridRef.setRadioRow(data)
}
}
}
}
}
export const radioChange =
({ props, vm, emit, state }) =>
({ row }: any) => {
if (!props.multiple) {
updateBaseSelect({
vm,
props,
data: {
...row,
currentLabel: row[props.textField],
value: row[props.valueField],
state: {
currentLabel: row[props.textField]
}
}
})
state.selected = row
state.currentKey = row[props.valueField]
state.modelValue = row[props.valueField]
vm.$refs.baseSelectRef.hidePanel()
emit('update:modelValue', row[props.valueField])
emit('change', row[props.valueField])
}
}
export const selectChange =
({ props, vm, emit, state, nextTick }) =>
({ $table, selection, checked, row }: any) => {
if (props.multiple) {
const { textField, valueField } = props
const remoteItem = (row: any) => {
const removeItem = state.selected.find((item: any) => item[valueField] === row[valueField])
if (removeItem) {
const index = state.selected.indexOf(removeItem)
state.selected.splice(index, 1)
}
}
if (row) {
if (checked) {
const exists = state.selected.find((item: any) => item[valueField] === row[valueField])
if (!exists) {
state.selected.push({
...row,
value: row[valueField],
currentLabel: row[textField]
})
}
} else {
remoteItem(row)
}
} else {
if (checked) {
selection.forEach((row: any) => {
const exists = state.selected.find((item: any) => item[valueField] === row[valueField])
if (!exists) {
state.selected.push({
...row,
value: row[valueField],
currentLabel: row[textField]
})
}
})
} else {
const tableData = $table?.tableFullData || []
tableData.forEach((row: any) => {
remoteItem(row)
})
}
}
const selectedData = state.selected.map((node: any) => ({
...node,
currentLabel: node[textField],
value: node[valueField],
isGrid: true
}))
updateBaseSelect({ vm, props, data: selectedData })
const currentValue = state.selected.map((item: any) => item[valueField])
state.modelValue = currentValue
emit('update:modelValue', currentValue)
emit('change', currentValue, state.selected)
if (vm.$refs.gridRef) {
nextTick(() => {
try {
const tableData = vm.$refs.gridRef.getTableData()
const fullData = tableData?.fullData || []
const rowsToSelect = fullData.filter((row: any) => currentValue.includes(row[valueField]))
vm.$refs.gridRef.clearSelection()
if (rowsToSelect.length > 0) {
vm.$refs.gridRef.setSelection(rowsToSelect, true)
}
} catch (e) {
}
})
}
}
}