141 lines
3.9 KiB
Vue
141 lines
3.9 KiB
Vue
<script lang="ts" setup>
|
|
import {
|
|
TableColumn,
|
|
TableColumnSelectable
|
|
} from '@idux/components/table'
|
|
import { TablePagination } from '@idux/components/table/src/types'
|
|
import { useAccessorAndControl } from '@idux/cdk/forms'
|
|
import { useFormItemRegister } from '@idux/components/form'
|
|
|
|
const props = defineProps<{
|
|
control?: string | number | (string | number)[] | object
|
|
disabled?: boolean
|
|
value?: string
|
|
placeholder?: string
|
|
searchFormPlaceholder?: string
|
|
columns: TableColumn<any>[]
|
|
getDatasource: (params: any) => Promise<G.PageResult<any>>
|
|
getKey: string | ((record: any) => any)
|
|
getLabel: string | ((record: any) => any)
|
|
}>()
|
|
|
|
// const emit = defineEmits([ 'update:value' ])
|
|
|
|
// useAccessorAndControl 内部对 props 中的 control, disabled, value 进行了处理
|
|
const {accessor, control: controlRef} = useAccessorAndControl()
|
|
|
|
// 在 FormItem 组件中注册 control, 让 FormItem 获取控件的验证状态
|
|
useFormItemRegister(controlRef)
|
|
// 表单 blur 状态
|
|
const onBlur = () => {
|
|
accessor.markAsBlurred()
|
|
}
|
|
|
|
const inputStatus = ref<'valid' | 'invalid' | 'validating'>('validating')
|
|
controlRef.value?.watchValue((newVal) => {
|
|
console.log(222, controlRef.value?.valid, newVal)
|
|
if (controlRef.value?.valid.value) {
|
|
inputStatus.value = 'valid'
|
|
} else {
|
|
inputStatus.value = 'invalid'
|
|
}
|
|
})
|
|
|
|
const valueRef = reactive<{
|
|
key?: string
|
|
label?: string
|
|
}>({})
|
|
|
|
const visible = ref(false)
|
|
const selectedRowKeys = ref<string[]>([])
|
|
const selectableColumn = reactive<TableColumnSelectable<ComboboxTableTypes.TableData>>({
|
|
type: 'selectable',
|
|
align: 'center',
|
|
multiple: false,
|
|
showIndex: false,
|
|
trigger: 'click',
|
|
onChange: (selectedKeys, selectedRows) => {
|
|
if (selectedKeys.length === 0) {
|
|
valueRef.key = undefined
|
|
valueRef.label = undefined
|
|
} else {
|
|
valueRef.key = selectedKeys[0] as string
|
|
if (props.getLabel instanceof Function) {
|
|
valueRef.label = props.getLabel(selectedRows[0])
|
|
} else {
|
|
valueRef.label = selectedRows[0][props.getLabel as string]
|
|
}
|
|
}
|
|
accessor.setValue(valueRef.key)
|
|
// emit('update:value', valueRef.key)
|
|
},
|
|
})
|
|
const columns_: TableColumn<any>[] = [
|
|
selectableColumn,
|
|
...props.columns
|
|
]
|
|
const datasource = ref<ComboboxTableTypes.TableData[]>([])
|
|
const tableSpin = ref(false)
|
|
const keywords = ref('')
|
|
|
|
function obtainData() {
|
|
tableSpin.value = true
|
|
props.getDatasource({
|
|
pageIndex: pagination.pageIndex,
|
|
pageSize: pagination.pageSize,
|
|
keywords: keywords.value
|
|
}).then(res => {
|
|
pagination.pageIndex = res.current
|
|
pagination.pageSize = res.size
|
|
pagination.total = res.total
|
|
datasource.value = res.records
|
|
}).finally(() => {
|
|
tableSpin.value = false
|
|
})
|
|
}
|
|
|
|
const pagination = reactive<TablePagination>({
|
|
pageIndex: 1,
|
|
pageSize: 10,
|
|
total: 0,
|
|
size: 'sm',
|
|
showTotal: true,
|
|
onChange: obtainData
|
|
})
|
|
|
|
watch(visible, (newVal) => {
|
|
if (newVal) {
|
|
obtainData()
|
|
}
|
|
})
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<IxPopover v-model:visible="visible" closable placement="bottom" trigger="click">
|
|
<IxInput v-model:value="valueRef.label" :placeholder="placeholder" :status="inputStatus" readonly @blur="onBlur"/>
|
|
<template #header>
|
|
<IxForm class="search-form" layout="inline" @submit.prevent="obtainData">
|
|
<IxFormItem>
|
|
<IxInput v-model:value="keywords" :placeholder="searchFormPlaceholder" clearable @clear="obtainData"/>
|
|
</IxFormItem>
|
|
<IxFormItem>
|
|
<IxButton mode="primary" type="submit">查询</IxButton>
|
|
</IxFormItem>
|
|
</IxForm>
|
|
</template>
|
|
<template #content>
|
|
<IxTable v-model:selectedRowKeys="selectedRowKeys" :columns="columns_" :dataSource="datasource" :get-key="getKey" :pagination="pagination" :spin="tableSpin"/>
|
|
</template>
|
|
</IxPopover>
|
|
</template>
|
|
|
|
<style lang="stylus" scoped>
|
|
.search-form {
|
|
width 100%
|
|
height 4rem
|
|
padding: var(--ix-padding-size-sm) var(--ix-padding-size-md);
|
|
border 1px solid #E5E7EB
|
|
}
|
|
</style>
|