|
@@ -1,5 +1,5 @@
|
|
|
<script setup lang="ts">
|
|
|
-import {computed, defineProps, onMounted, ref, watch} from "vue";
|
|
|
+import {computed, defineProps, nextTick, onMounted, ref, watch} from "vue";
|
|
|
import XEUtils from 'xe-utils'
|
|
|
import {onClickOutside} from '@vueuse/core'
|
|
|
|
|
@@ -19,6 +19,10 @@ const props = defineProps({
|
|
|
},
|
|
|
code: String,
|
|
|
name: String,
|
|
|
+ clearable: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
tableHeader: {
|
|
|
type: Array,
|
|
|
default: [
|
|
@@ -32,23 +36,25 @@ const emits = defineEmits(['input', 'rowClick', 'clear', 'focus', 'blur', 'updat
|
|
|
|
|
|
const isObj = typeof props.modelValue === 'object'
|
|
|
const tempData = ref([])
|
|
|
-const isShow = ref(false)
|
|
|
-const divRef = ref()
|
|
|
-const inputRef = ref()
|
|
|
-
|
|
|
-const states = ref({
|
|
|
- isFocus: false
|
|
|
+const pulldownRef = ref()
|
|
|
+const inputData = ref('')
|
|
|
+const placeholder = ref('')
|
|
|
+const vxeTableRef = ref()
|
|
|
+const theRowIsCurrentlySelected = ref({
|
|
|
+ row: {},
|
|
|
+ index: -1
|
|
|
})
|
|
|
-
|
|
|
+const currentIndex = ref(-1)
|
|
|
+const inputRef = ref()
|
|
|
+const isShow = ref()
|
|
|
|
|
|
const computedData = computed(() => {
|
|
|
return props.data === null ? tempData.value : props.data
|
|
|
})
|
|
|
|
|
|
-const inputData = ref('')
|
|
|
-
|
|
|
const change = XEUtils.debounce(async (value) => {
|
|
|
emits('input', value)
|
|
|
+ if (XEUtils.isEmpty(value)) return
|
|
|
if (props.queryDataFunc === null) return
|
|
|
try {
|
|
|
let res = await props.queryDataFunc(value)
|
|
@@ -60,34 +66,104 @@ const change = XEUtils.debounce(async (value) => {
|
|
|
}
|
|
|
} catch {
|
|
|
}
|
|
|
+ pulldownRef.value.showPanel()
|
|
|
+ currentIndex.value = -1
|
|
|
}, 500)
|
|
|
|
|
|
-const rowClick = (...val) => {
|
|
|
- console.log('row', ...val)
|
|
|
-}
|
|
|
+const rowClick = (val) => {
|
|
|
+ let {row, rowIndex} = val
|
|
|
+ pulldownRef.value?.hidePanel()
|
|
|
+ if (isObj) {
|
|
|
+ props.modelValue[props.code] = row.code
|
|
|
+ props.modelValue[props.name] = row.name
|
|
|
+ } else {
|
|
|
+ emits('update:modelValue', row.name)
|
|
|
+ }
|
|
|
+
|
|
|
+ emits('rowClick', row, rowIndex)
|
|
|
|
|
|
+ theRowIsCurrentlySelected.value = {
|
|
|
+ row, index: rowIndex
|
|
|
+ }
|
|
|
|
|
|
-const rowClassName = (...val) => {
|
|
|
- console.log('rowClassName', ...val)
|
|
|
+ inputRef.value.focus()
|
|
|
+ currentIndex.value = rowIndex
|
|
|
}
|
|
|
|
|
|
+const inputClick = async () => {
|
|
|
+ await pulldownRef.value.togglePanel()
|
|
|
+ if (await pulldownRef.value.isPanelVisible()) {
|
|
|
+ vxeTableRef.value.scrollToRow(theRowIsCurrentlySelected.value.row)
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
const handleFocus = () => {
|
|
|
- states.value.isFocus = true
|
|
|
- isShow.value = true
|
|
|
+ if (isObj) {
|
|
|
+ placeholder.value = props.modelValue[props.name]
|
|
|
+ } else {
|
|
|
+ placeholder.value = <string>props.modelValue;
|
|
|
+ }
|
|
|
+ inputData.value = ''
|
|
|
}
|
|
|
|
|
|
const handleBlur = () => {
|
|
|
- states.value.isFocus = false
|
|
|
+ emits('blur')
|
|
|
+ if (pulldownRef.value.isPanelVisible()) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (isObj) {
|
|
|
+ inputData.value = props.modelValue[props.name]
|
|
|
+ } else {
|
|
|
+ inputData.value = <string>props.modelValue;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-const divClick = () => {
|
|
|
- console.log('div点击事件')
|
|
|
+const keyUp = () => {
|
|
|
+ currentIndex.value -= 1
|
|
|
+ if (currentIndex.value <= -1) {
|
|
|
+ currentIndex.value = computedData.value.length - 1
|
|
|
+ }
|
|
|
+ let tempData = computedData.value[currentIndex.value]
|
|
|
+ vxeTableRef.value.setCurrentRow(computedData.value[currentIndex.value])
|
|
|
+ vxeTableRef.value.scrollToRow(tempData)
|
|
|
+}
|
|
|
+
|
|
|
+const keyDown = () => {
|
|
|
+ currentIndex.value += 1
|
|
|
+ if (computedData.value.length === currentIndex.value) {
|
|
|
+ currentIndex.value = 0
|
|
|
+ }
|
|
|
+ let tempData = computedData.value[currentIndex.value]
|
|
|
+ vxeTableRef.value.setCurrentRow(computedData.value[currentIndex.value])
|
|
|
+ vxeTableRef.value.scrollToRow(tempData)
|
|
|
+}
|
|
|
+
|
|
|
+const enterToSelect = () => {
|
|
|
+ if (pulldownRef.value.isPanelVisible()) {
|
|
|
+ let temp = vxeTableRef.value.getCurrentRecord()
|
|
|
+ if (!temp) {
|
|
|
+ pulldownRef.value.togglePanel()
|
|
|
+ } else {
|
|
|
+ rowClick({
|
|
|
+ row: temp,
|
|
|
+ rowIndex: currentIndex.value
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ pulldownRef.value.showPanel()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const handleClear = () => {
|
|
|
+ if (isObj) {
|
|
|
+ props.modelValue[props.code] = ''
|
|
|
+ props.modelValue[props.name] = ''
|
|
|
+ } else {
|
|
|
+ emits('update:modelValue', '')
|
|
|
+ }
|
|
|
+ placeholder.value = ''
|
|
|
}
|
|
|
|
|
|
-watch(() => isShow.value, () => {
|
|
|
- console.log('watch', isShow.value)
|
|
|
-})
|
|
|
|
|
|
onMounted(() => {
|
|
|
if (isObj) {
|
|
@@ -99,67 +175,53 @@ onMounted(() => {
|
|
|
inputData.value = <string>props.modelValue
|
|
|
}, {immediate: true, deep: true})
|
|
|
}
|
|
|
- onClickOutside(divRef, (event) => {
|
|
|
- if (event.target.id === inputRef.value.input.id) {
|
|
|
- isShow.value = true
|
|
|
- } else {
|
|
|
- isShow.value = false
|
|
|
- }
|
|
|
- console.log(isShow.value)
|
|
|
-
|
|
|
- })
|
|
|
-
|
|
|
})
|
|
|
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
- <el-tooltip placement="bottom"
|
|
|
- trigger="click"
|
|
|
- popper-class="popover_padding_zero"
|
|
|
- :visible="isShow"
|
|
|
- effect="light"
|
|
|
- pure
|
|
|
- :fallback-placements="['bottom-start', 'top-start', 'right', 'left']"
|
|
|
- :teleported="true"
|
|
|
- :width="0">
|
|
|
+ <vxe-pulldown
|
|
|
+ v-model="isShow"
|
|
|
+ ref="pulldownRef"
|
|
|
+ transfer>
|
|
|
<template #default>
|
|
|
- <el-input
|
|
|
- style="width: 120px;"
|
|
|
- @focus="handleFocus"
|
|
|
- @blur="handleBlur"
|
|
|
- ref="inputRef"
|
|
|
- @input="change"
|
|
|
- v-model="inputData"
|
|
|
- />
|
|
|
+ <el-input v-model="inputData"
|
|
|
+ @clear="handleClear"
|
|
|
+ ref="inputRef"
|
|
|
+ style="width: 120px;"
|
|
|
+ @keydown.up.prevent="keyUp"
|
|
|
+ @keydown.down.prevent="keyDown"
|
|
|
+ @keydown.enter.prevent="enterToSelect"
|
|
|
+ @input="change"
|
|
|
+ :clearable="props.clearable"
|
|
|
+ @click="inputClick"
|
|
|
+ @blur="handleBlur"
|
|
|
+ :placeholder="placeholder"
|
|
|
+ @focus="handleFocus"/>
|
|
|
</template>
|
|
|
- <template #content>
|
|
|
- <div ref="divRef" style="padding: 5px">
|
|
|
- <vxe-table
|
|
|
- :height="200"
|
|
|
- border
|
|
|
- :scroll-x="{gt: 20}"
|
|
|
- :scroll-y="{gt: 50,enabled: true}"
|
|
|
- :column-config="{resizable: true}"
|
|
|
- :row-config="{ height: 24}"
|
|
|
- class="vxe-padding_zero vxe-header-max_content hl-style vxe-scroll_15"
|
|
|
- header-row-class-name="padding_zero "
|
|
|
- :row-class-name="rowClassName"
|
|
|
- @cell-click="rowClick"
|
|
|
- show-header-overflow
|
|
|
- show-overflow
|
|
|
- :data="computedData">
|
|
|
-
|
|
|
- <vxe-column v-for="item in tableHeader"
|
|
|
- :title="item.title"
|
|
|
- :field="item.field"
|
|
|
- :width="item.width"/>
|
|
|
- <slot/>
|
|
|
- </vxe-table>
|
|
|
- </div>
|
|
|
+ <template #dropdown>
|
|
|
+ <vxe-table
|
|
|
+ ref="vxeTableRef"
|
|
|
+ :height="200"
|
|
|
+ border
|
|
|
+ :scroll-x="{gt: 20}"
|
|
|
+ :scroll-y="{gt: 50,enabled: true}"
|
|
|
+ :column-config="{resizable: true}"
|
|
|
+ :row-config="{ height: 24,isCurrent: true,isHover:true }"
|
|
|
+ class="vxe-padding_zero vxe-header-max_content hl-style vxe-scroll_15"
|
|
|
+ header-row-class-name="padding_zero "
|
|
|
+ @cell-click="rowClick"
|
|
|
+ show-header-overflow
|
|
|
+ show-overflow
|
|
|
+ :data="computedData">
|
|
|
+ <vxe-column v-for="item in tableHeader"
|
|
|
+ :title="item.title"
|
|
|
+ :field="item.field"
|
|
|
+ :width="item.width"/>
|
|
|
+ <slot/>
|
|
|
+ </vxe-table>
|
|
|
</template>
|
|
|
-
|
|
|
- </el-tooltip>
|
|
|
+ </vxe-pulldown>
|
|
|
</template>
|
|
|
|
|
|
<style lang="scss">
|